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.
45 #include "wine/exception.h"
46 #include "wine/debug.h"
47 #include "dbghelp_private.h"
48 #include "wine/mscvpdb.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_msc
);
52 static const GUID null_guid
;
54 struct pdb_stream_name
60 enum pdb_kind
{PDB_JG
, PDB_DS
};
67 struct pdb_stream_name
* stream_dict
;
68 unsigned fpoext_stream
;
73 struct PDB_JG_TOC
* toc
;
77 struct PDB_DS_TOC
* toc
;
82 /* FIXME: don't make it static */
83 #define CV_MAX_MODULES 32
84 struct pdb_module_info
86 unsigned used_subfiles
;
87 struct pdb_file_info pdb_files
[CV_MAX_MODULES
];
90 #define loc_cv_local_range (loc_user + 0) /* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */
92 struct cv_module_snarf
94 const struct codeview_type_parse
* ipi_ctp
;
95 const struct CV_DebugSSubsectionHeader_t
* dbgsubsect
;
96 unsigned dbgsubsect_size
;
97 const PDB_STRING_TABLE
* strimage
;
100 /*========================================================================
101 * Debug file access helper routines
104 static void dump(const void* ptr
, unsigned len
)
108 const char* hexof
= "0123456789abcdef";
111 for (i
= 0; i
< len
; i
+= 16)
113 sprintf(msg
, "%08x: ", i
);
114 memset(msg
+ 10, ' ', 3 * 16 + 1 + 16);
115 for (j
= 0; j
< min(16, len
- i
); j
++)
117 msg
[10 + 3 * j
+ 0] = hexof
[x
[i
+ j
] >> 4];
118 msg
[10 + 3 * j
+ 1] = hexof
[x
[i
+ j
] & 15];
119 msg
[10 + 3 * j
+ 2] = ' ';
120 msg
[10 + 3 * 16 + 1 + j
] = (x
[i
+ j
] >= 0x20 && x
[i
+ j
] < 0x7f) ?
123 msg
[10 + 3 * 16] = ' ';
124 msg
[10 + 3 * 16 + 1 + 16] = '\0';
129 /*========================================================================
130 * Process CodeView type information.
133 static struct symt
* cv_basic_types
[T_MAXPREDEFINEDTYPE
];
135 struct cv_defined_module
138 unsigned int first_type_index
;
139 unsigned int last_type_index
;
140 struct symt
** defined_types
;
142 /* FIXME: don't make it static */
143 #define CV_MAX_MODULES 32
144 static struct cv_defined_module cv_zmodules
[CV_MAX_MODULES
];
145 static struct cv_defined_module
*cv_current_module
;
147 static void codeview_init_basic_types(struct module
* module
)
149 unsigned ptrsz
= module
->cpu
->word_size
;
152 * These are the common builtin types that are used by VC++.
154 cv_basic_types
[T_NOTYPE
] = NULL
;
155 cv_basic_types
[T_ABS
] = NULL
;
156 cv_basic_types
[T_VOID
] = &symt_get_basic(btVoid
, 0)->symt
; /* void */
157 cv_basic_types
[T_CHAR
] = &symt_get_basic(btInt
, 1)->symt
; /* signed char (and char in C) */
158 cv_basic_types
[T_SHORT
] = &symt_get_basic(btInt
, 2)->symt
; /* short int */
159 cv_basic_types
[T_LONG
] = &symt_get_basic(btLong
, 4)->symt
; /* long int */
160 cv_basic_types
[T_QUAD
] = &symt_get_basic(btInt
, 8)->symt
; /* long long int */
161 cv_basic_types
[T_UCHAR
] = &symt_get_basic(btUInt
, 1)->symt
; /* unsigned char */
162 cv_basic_types
[T_USHORT
] = &symt_get_basic(btUInt
, 2)->symt
; /* unsigned short */
163 cv_basic_types
[T_ULONG
] = &symt_get_basic(btULong
, 4)->symt
; /* unsigned long */
164 cv_basic_types
[T_UQUAD
] = &symt_get_basic(btUInt
, 8)->symt
; /* unsigned long long */
165 cv_basic_types
[T_BOOL08
] = &symt_get_basic(btBool
, 1)->symt
; /* BOOL08 */
166 cv_basic_types
[T_BOOL16
] = &symt_get_basic(btBool
, 2)->symt
; /* BOOL16 */
167 cv_basic_types
[T_BOOL32
] = &symt_get_basic(btBool
, 4)->symt
; /* BOOL32 */
168 cv_basic_types
[T_BOOL64
] = &symt_get_basic(btBool
, 8)->symt
; /* BOOL64 */
169 cv_basic_types
[T_REAL32
] = &symt_get_basic(btFloat
, 4)->symt
; /* float */
170 cv_basic_types
[T_REAL64
] = &symt_get_basic(btFloat
, 8)->symt
; /* double */
171 cv_basic_types
[T_REAL80
] = &symt_get_basic(btFloat
, 10)->symt
; /* long double */
172 cv_basic_types
[T_RCHAR
] = &symt_get_basic(btChar
, 1)->symt
; /* "real" char (char in C++) */
173 cv_basic_types
[T_WCHAR
] = &symt_get_basic(btWChar
, 2)->symt
; /* char8_t */
174 cv_basic_types
[T_CHAR16
] = &symt_get_basic(btChar16
, 2)->symt
; /* char16_t */
175 cv_basic_types
[T_CHAR32
] = &symt_get_basic(btChar32
, 4)->symt
; /* char32_t */
176 cv_basic_types
[T_CHAR8
] = &symt_get_basic(btChar8
, 1)->symt
; /* char8_t */
177 cv_basic_types
[T_INT2
] = &symt_get_basic(btInt
, 2)->symt
; /* INT2 */
178 cv_basic_types
[T_UINT2
] = &symt_get_basic(btUInt
, 2)->symt
; /* UINT2 */
179 cv_basic_types
[T_INT4
] = &symt_get_basic(btInt
, 4)->symt
; /* INT4 */
180 cv_basic_types
[T_UINT4
] = &symt_get_basic(btUInt
, 4)->symt
; /* UINT4 */
181 cv_basic_types
[T_INT8
] = &symt_get_basic(btInt
, 8)->symt
; /* INT8 */
182 cv_basic_types
[T_UINT8
] = &symt_get_basic(btUInt
, 8)->symt
; /* UINT8 */
183 cv_basic_types
[T_HRESULT
]= &symt_get_basic(btUInt
, 4)->symt
; /* HRESULT */
185 cv_basic_types
[T_32PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], 4)->symt
;
186 cv_basic_types
[T_32PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], 4)->symt
;
187 cv_basic_types
[T_32PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], 4)->symt
;
188 cv_basic_types
[T_32PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], 4)->symt
;
189 cv_basic_types
[T_32PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], 4)->symt
;
190 cv_basic_types
[T_32PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], 4)->symt
;
191 cv_basic_types
[T_32PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], 4)->symt
;
192 cv_basic_types
[T_32PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], 4)->symt
;
193 cv_basic_types
[T_32PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], 4)->symt
;
194 cv_basic_types
[T_32PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], 4)->symt
;
195 cv_basic_types
[T_32PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], 4)->symt
;
196 cv_basic_types
[T_32PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], 4)->symt
;
197 cv_basic_types
[T_32PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], 4)->symt
;
198 cv_basic_types
[T_32PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], 4)->symt
;
199 cv_basic_types
[T_32PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], 4)->symt
;
200 cv_basic_types
[T_32PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], 4)->symt
;
201 cv_basic_types
[T_32PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], 4)->symt
;
202 cv_basic_types
[T_32PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], 4)->symt
;
203 cv_basic_types
[T_32PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], 4)->symt
;
204 cv_basic_types
[T_32PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], 4)->symt
;
205 cv_basic_types
[T_32PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], 4)->symt
;
206 cv_basic_types
[T_32PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], 4)->symt
;
207 cv_basic_types
[T_32PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], 4)->symt
;
208 cv_basic_types
[T_32PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], 4)->symt
;
209 cv_basic_types
[T_32PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], 4)->symt
;
210 cv_basic_types
[T_32PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], 4)->symt
;
211 cv_basic_types
[T_32PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], 4)->symt
;
212 cv_basic_types
[T_32PHRESULT
]= &symt_new_pointer(module
, cv_basic_types
[T_HRESULT
], 4)->symt
;
214 cv_basic_types
[T_64PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], 8)->symt
;
215 cv_basic_types
[T_64PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], 8)->symt
;
216 cv_basic_types
[T_64PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], 8)->symt
;
217 cv_basic_types
[T_64PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], 8)->symt
;
218 cv_basic_types
[T_64PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], 8)->symt
;
219 cv_basic_types
[T_64PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], 8)->symt
;
220 cv_basic_types
[T_64PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], 8)->symt
;
221 cv_basic_types
[T_64PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], 8)->symt
;
222 cv_basic_types
[T_64PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], 8)->symt
;
223 cv_basic_types
[T_64PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], 8)->symt
;
224 cv_basic_types
[T_64PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], 8)->symt
;
225 cv_basic_types
[T_64PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], 8)->symt
;
226 cv_basic_types
[T_64PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], 8)->symt
;
227 cv_basic_types
[T_64PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], 8)->symt
;
228 cv_basic_types
[T_64PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], 8)->symt
;
229 cv_basic_types
[T_64PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], 8)->symt
;
230 cv_basic_types
[T_64PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], 8)->symt
;
231 cv_basic_types
[T_64PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], 8)->symt
;
232 cv_basic_types
[T_64PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], 8)->symt
;
233 cv_basic_types
[T_64PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], 8)->symt
;
234 cv_basic_types
[T_64PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], 8)->symt
;
235 cv_basic_types
[T_64PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], 8)->symt
;
236 cv_basic_types
[T_64PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], 8)->symt
;
237 cv_basic_types
[T_64PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], 8)->symt
;
238 cv_basic_types
[T_64PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], 8)->symt
;
239 cv_basic_types
[T_64PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], 8)->symt
;
240 cv_basic_types
[T_64PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], 8)->symt
;
241 cv_basic_types
[T_64PHRESULT
]= &symt_new_pointer(module
, cv_basic_types
[T_HRESULT
], 8)->symt
;
243 cv_basic_types
[T_PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], ptrsz
)->symt
;
244 cv_basic_types
[T_PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], ptrsz
)->symt
;
245 cv_basic_types
[T_PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], ptrsz
)->symt
;
246 cv_basic_types
[T_PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], ptrsz
)->symt
;
247 cv_basic_types
[T_PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], ptrsz
)->symt
;
248 cv_basic_types
[T_PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], ptrsz
)->symt
;
249 cv_basic_types
[T_PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], ptrsz
)->symt
;
250 cv_basic_types
[T_PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], ptrsz
)->symt
;
251 cv_basic_types
[T_PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], ptrsz
)->symt
;
252 cv_basic_types
[T_PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], ptrsz
)->symt
;
253 cv_basic_types
[T_PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], ptrsz
)->symt
;
254 cv_basic_types
[T_PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], ptrsz
)->symt
;
255 cv_basic_types
[T_PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], ptrsz
)->symt
;
256 cv_basic_types
[T_PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], ptrsz
)->symt
;
257 cv_basic_types
[T_PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], ptrsz
)->symt
;
258 cv_basic_types
[T_PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], ptrsz
)->symt
;
259 cv_basic_types
[T_PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], ptrsz
)->symt
;
260 cv_basic_types
[T_PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], ptrsz
)->symt
;
261 cv_basic_types
[T_PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], ptrsz
)->symt
;
262 cv_basic_types
[T_PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], ptrsz
)->symt
;
263 cv_basic_types
[T_PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], ptrsz
)->symt
;
264 cv_basic_types
[T_PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], ptrsz
)->symt
;
265 cv_basic_types
[T_PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], ptrsz
)->symt
;
266 cv_basic_types
[T_PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], ptrsz
)->symt
;
267 cv_basic_types
[T_PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], ptrsz
)->symt
;
268 cv_basic_types
[T_PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], ptrsz
)->symt
;
269 cv_basic_types
[T_PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], ptrsz
)->symt
;
272 static int leaf_as_variant(VARIANT
* v
, const unsigned short int* leaf
)
274 unsigned short int type
= *leaf
++;
277 if (type
< LF_NUMERIC
)
289 V_I1(v
) = *(const char*)leaf
;
295 V_I2(v
) = *(const short*)leaf
;
307 V_I4(v
) = *(const int*)leaf
;
313 V_UI4(v
) = *(const unsigned int*)leaf
;
319 V_I8(v
) = *(const long long int*)leaf
;
325 V_UI8(v
) = *(const long long unsigned int*)leaf
;
331 V_R4(v
) = *(const float*)leaf
;
335 FIXME("Unsupported numeric leaf type %04x\n", type
);
337 V_VT(v
) = VT_EMPTY
; /* FIXME */
343 V_R8(v
) = *(const double*)leaf
;
347 FIXME("Unsupported numeric leaf type %04x\n", type
);
349 V_VT(v
) = VT_EMPTY
; /* FIXME */
353 FIXME("Unsupported numeric leaf type %04x\n", type
);
355 V_VT(v
) = VT_EMPTY
; /* FIXME */
359 FIXME("Unsupported numeric leaf type %04x\n", type
);
361 V_VT(v
) = VT_EMPTY
; /* FIXME */
365 FIXME("Unsupported numeric leaf type %04x\n", type
);
367 V_VT(v
) = VT_EMPTY
; /* FIXME */
371 FIXME("Unsupported numeric leaf type %04x\n", type
);
376 FIXME("Unsupported numeric leaf type %04x\n", type
);
378 V_VT(v
) = VT_EMPTY
; /* FIXME */
382 FIXME("Unsupported numeric leaf type %04x\n", type
);
384 V_VT(v
) = VT_EMPTY
; /* FIXME */
388 FIXME("Unknown numeric leaf type %04x\n", type
);
389 V_VT(v
) = VT_EMPTY
; /* FIXME */
397 static int numeric_leaf(int* value
, const unsigned short int* leaf
)
399 unsigned short int type
= *leaf
++;
402 if (type
< LF_NUMERIC
)
412 *value
= *(const char*)leaf
;
417 *value
= *(const short*)leaf
;
427 *value
= *(const int*)leaf
;
432 *value
= *(const unsigned int*)leaf
;
437 FIXME("Unsupported numeric leaf type %04x\n", type
);
439 *value
= 0; /* FIXME */
443 FIXME("Unsupported numeric leaf type %04x\n", type
);
445 *value
= 0; /* FIXME */
449 FIXME("Unsupported numeric leaf type %04x\n", type
);
451 *value
= 0; /* FIXME */
455 FIXME("Unsupported numeric leaf type %04x\n", type
);
457 *value
= 0; /* FIXME */
461 FIXME("Unsupported numeric leaf type %04x\n", type
);
463 *value
= 0; /* FIXME */
467 FIXME("Unsupported numeric leaf type %04x\n", type
);
469 *value
= 0; /* FIXME */
473 FIXME("Unsupported numeric leaf type %04x\n", type
);
475 *value
= 0; /* FIXME */
479 FIXME("Unsupported numeric leaf type %04x\n", type
);
481 *value
= 0; /* FIXME */
485 FIXME("Unsupported numeric leaf type %04x\n", type
);
487 *value
= 0; /* FIXME */
491 FIXME("Unsupported numeric leaf type %04x\n", type
);
493 *value
= 0; /* FIXME */
497 FIXME("Unsupported numeric leaf type %04x\n", type
);
499 *value
= 0; /* FIXME */
503 FIXME("Unknown numeric leaf type %04x\n", type
);
512 /* convert a pascal string (as stored in debug information) into
513 * a C string (null terminated).
515 static const char* terminate_string(const struct p_string
* p_name
)
517 static char symname
[256];
519 memcpy(symname
, p_name
->name
, p_name
->namelen
);
520 symname
[p_name
->namelen
] = '\0';
522 return (!*symname
|| strcmp(symname
, "__unnamed") == 0) ? NULL
: symname
;
525 static struct symt
* codeview_get_type(unsigned int typeno
, BOOL quiet
)
527 struct symt
* symt
= NULL
;
530 * Convert Codeview type numbers into something we can grok internally.
531 * Numbers < T_MAXPREDEFINEDTYPE all fixed builtin types.
532 * Numbers from T_FIRSTDEFINABLETYPE and up are all user defined (structs, etc).
534 if (typeno
< T_MAXPREDEFINEDTYPE
)
535 symt
= cv_basic_types
[typeno
];
536 else if (typeno
>= T_FIRSTDEFINABLETYPE
)
538 unsigned mod_index
= typeno
>> 24;
539 unsigned mod_typeno
= typeno
& 0x00FFFFFF;
540 struct cv_defined_module
* mod
;
542 mod
= (mod_index
== 0) ? cv_current_module
: &cv_zmodules
[mod_index
];
544 if (mod_index
>= CV_MAX_MODULES
|| !mod
->allowed
)
545 FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index
, typeno
);
548 if (mod_typeno
>= mod
->first_type_index
&& mod_typeno
< mod
->last_type_index
)
549 symt
= mod
->defined_types
[mod_typeno
- mod
->first_type_index
];
552 if (!quiet
&& !symt
&& typeno
) FIXME("Returning NULL symt for type-id %x\n", typeno
);
559 struct hash_link
* next
;
562 struct codeview_type_parse
564 struct module
* module
;
567 const DWORD
* offset
; /* typeindex => offset in 'table' */
568 BYTE
* hash_stream
; /* content of stream header.hash_file */
569 struct hash_link
** hash
; /* hash_table (deserialized from PDB hash table) */
570 struct hash_link
* alloc_hash
; /* allocated hash_link (id => hash_link) */
573 static inline const void* codeview_jump_to_type(const struct codeview_type_parse
* ctp
, DWORD idx
)
575 return (idx
>= ctp
->header
.first_index
&& idx
< ctp
->header
.last_index
) ?
576 ctp
->table
+ ctp
->offset
[idx
- ctp
->header
.first_index
] : NULL
;
579 static int codeview_add_type(unsigned int typeno
, struct symt
* dt
)
582 if (!cv_current_module
)
584 FIXME("Adding %x to non allowed module\n", typeno
);
587 if ((typeno
>> 24) != 0)
588 FIXME("No module index while inserting type-id assumption is wrong %x\n",
590 if (typeno
< cv_current_module
->first_type_index
|| typeno
>= cv_current_module
->last_type_index
)
592 FIXME("Type number %x out of bounds [%x, %x)\n",
593 typeno
, cv_current_module
->first_type_index
, typeno
>= cv_current_module
->last_type_index
);
596 idx
= typeno
- cv_current_module
->first_type_index
;
597 if (cv_current_module
->defined_types
[idx
])
599 if (cv_current_module
->defined_types
[idx
] != dt
)
600 FIXME("Overwriting at %x\n", typeno
);
602 cv_current_module
->defined_types
[idx
] = dt
;
606 static void codeview_clear_type_table(void)
610 for (i
= 0; i
< CV_MAX_MODULES
; i
++)
612 if (cv_zmodules
[i
].allowed
)
613 free(cv_zmodules
[i
].defined_types
);
614 cv_zmodules
[i
].allowed
= FALSE
;
615 cv_zmodules
[i
].defined_types
= NULL
;
616 cv_zmodules
[i
].first_type_index
= 0;
617 cv_zmodules
[i
].last_type_index
= 0;
619 cv_current_module
= NULL
;
622 static struct symt
* codeview_parse_one_type(struct codeview_type_parse
* ctp
,
624 const union codeview_type
* type
);
626 static struct symt
* codeview_fetch_type(struct codeview_type_parse
* ctp
,
630 const union codeview_type
* p
;
632 if (!typeno
) return NULL
;
633 if ((symt
= codeview_get_type(typeno
, TRUE
))) return symt
;
635 if ((p
= codeview_jump_to_type(ctp
, typeno
)))
636 symt
= codeview_parse_one_type(ctp
, typeno
, p
);
637 if (!symt
) FIXME("Couldn't load type %x\n", typeno
);
641 static UINT32
codeview_compute_hash(const char* ptr
, unsigned len
)
643 const char* last
= ptr
+ len
;
646 while (ptr
+ sizeof(UINT32
) <= last
)
648 ret
^= *(UINT32
*)ptr
;
649 ptr
+= sizeof(UINT32
);
651 if (ptr
+ sizeof(UINT16
) <= last
)
653 ret
^= *(UINT16
*)ptr
;
654 ptr
+= sizeof(UINT16
);
656 if (ptr
+ sizeof(BYTE
) <= last
)
660 return ret
^ (ret
>> 16);
663 /* We call 'forwardable' a type which can have a forward declaration, and we need to merge
664 * (when they both exist) the type record of the forward declaration and the type record
665 * of the full definition into a single symt.
667 static BOOL
codeview_is_forwardable_type(const union codeview_type
* type
)
669 switch (type
->generic
.id
)
677 case LF_STRUCTURE_V1
:
678 case LF_STRUCTURE_V2
:
679 case LF_STRUCTURE_V3
:
689 static BOOL
codeview_type_is_forward(const union codeview_type
* cvtype
)
691 cv_property_t property
;
693 switch (cvtype
->generic
.id
)
695 case LF_STRUCTURE_V1
:
696 case LF_CLASS_V1
: property
= cvtype
->struct_v1
.property
; break;
697 case LF_STRUCTURE_V2
:
698 case LF_CLASS_V2
: property
= cvtype
->struct_v2
.property
; break;
699 case LF_STRUCTURE_V3
:
700 case LF_CLASS_V3
: property
= cvtype
->struct_v3
.property
; break;
701 case LF_UNION_V1
: property
= cvtype
->union_v1
.property
; break;
702 case LF_UNION_V2
: property
= cvtype
->union_v2
.property
; break;
703 case LF_UNION_V3
: property
= cvtype
->union_v3
.property
; break;
704 case LF_ENUM_V1
: property
= cvtype
->enumeration_v1
.property
; break;
705 case LF_ENUM_V2
: property
= cvtype
->enumeration_v2
.property
; break;
706 case LF_ENUM_V3
: property
= cvtype
->enumeration_v3
.property
; break;
710 return property
.is_forward_defn
;
713 static BOOL
codeview_type_extract_name(const union codeview_type
* cvtype
,
714 const char** name
, unsigned* len
, const char** decorated_name
)
717 const struct p_string
* p_name
= NULL
;
718 const char* c_name
= NULL
;
719 BOOL decorated
= FALSE
;
721 switch (cvtype
->generic
.id
)
723 case LF_STRUCTURE_V1
:
725 leaf_len
= numeric_leaf(&value
, &cvtype
->struct_v1
.structlen
);
726 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->struct_v1
.structlen
+ leaf_len
);
728 case LF_STRUCTURE_V2
:
730 leaf_len
= numeric_leaf(&value
, &cvtype
->struct_v2
.structlen
);
731 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->struct_v2
.structlen
+ leaf_len
);
733 case LF_STRUCTURE_V3
:
735 leaf_len
= numeric_leaf(&value
, &cvtype
->struct_v3
.structlen
);
736 c_name
= (const char*)&cvtype
->struct_v3
.structlen
+ leaf_len
;
737 decorated
= cvtype
->struct_v3
.property
.has_decorated_name
;
740 leaf_len
= numeric_leaf(&value
, &cvtype
->union_v1
.un_len
);
741 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->union_v1
.un_len
+ leaf_len
);
744 leaf_len
= numeric_leaf(&value
, &cvtype
->union_v2
.un_len
);
745 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->union_v2
.un_len
+ leaf_len
);
748 leaf_len
= numeric_leaf(&value
, &cvtype
->union_v3
.un_len
);
749 c_name
= (const char*)&cvtype
->union_v3
.un_len
+ leaf_len
;
750 decorated
= cvtype
->union_v3
.property
.has_decorated_name
;
753 p_name
= &cvtype
->enumeration_v1
.p_name
;
756 p_name
= &cvtype
->enumeration_v2
.p_name
;
759 c_name
= cvtype
->enumeration_v3
.name
;
760 decorated
= cvtype
->union_v3
.property
.has_decorated_name
;
767 *name
= p_name
->name
;
768 *len
= p_name
->namelen
;
769 *decorated_name
= NULL
;
775 *len
= strlen(c_name
);
776 *decorated_name
= decorated
? (c_name
+ *len
+ 1) : NULL
;
782 static unsigned pdb_read_hash_value(const struct codeview_type_parse
* ctp
, unsigned idx
)
784 const void* where
= ctp
->hash_stream
+ ctp
->header
.hash_offset
+ (idx
- ctp
->header
.first_index
) * ctp
->header
.hash_value_size
;
785 switch (ctp
->header
.hash_value_size
)
787 case 2: return *(unsigned short*)where
;
788 case 4: return *(unsigned*)where
;
793 static BOOL
codeview_resolve_forward_type(struct codeview_type_parse
* ctp
, const union codeview_type
* cvref
,
794 unsigned reftype
, unsigned *impl_type
)
796 const union codeview_type
* cvdecl
;
797 struct hash_link
* hl
;
799 const char* decoratedref
;
803 /* Unfortunately, hash of forward defs are computed on the whole type record, not its name
804 * (unlike hash of UDT & enum implementations which is based primarily on the name... sigh)
805 * So compute the hash of the expected implementation.
807 if (!codeview_type_extract_name(cvref
, &nameref
, &lenref
, &decoratedref
)) return FALSE
;
808 hash
= codeview_compute_hash(nameref
, lenref
) % ctp
->header
.hash_num_buckets
;
810 for (hl
= ctp
->hash
[hash
]; hl
; hl
= hl
->next
)
812 if (hl
->id
== reftype
) continue;
813 cvdecl
= codeview_jump_to_type(ctp
, hl
->id
);
814 if (cvdecl
&& !codeview_type_is_forward(cvdecl
) && cvref
->generic
.id
== cvdecl
->generic
.id
)
816 const char* namedecl
;
817 const char* decorateddecl
;
820 if (codeview_type_extract_name(cvdecl
, &namedecl
, &lendecl
, &decorateddecl
) &&
821 ((decoratedref
&& decorateddecl
&& !strcmp(decoratedref
, decorateddecl
)) ||
822 (!decoratedref
&& !decorateddecl
&& lenref
== lendecl
&& !memcmp(nameref
, namedecl
, lenref
))))
824 TRACE("mapping forward type %.*s (%s) %x into %x\n", lenref
, nameref
, debugstr_a(decoratedref
), reftype
, hl
->id
);
833 static struct symt
* codeview_add_type_pointer(struct codeview_type_parse
* ctp
,
834 unsigned int pointee_type
)
836 struct symt
* pointee
;
838 pointee
= codeview_fetch_type(ctp
, pointee_type
);
839 if (!pointee
) return NULL
;
840 return &symt_new_pointer(ctp
->module
, pointee
, ctp
->module
->cpu
->word_size
)->symt
;
843 static struct symt
* codeview_add_type_array(struct codeview_type_parse
* ctp
,
845 unsigned int elemtype
,
846 unsigned int indextype
,
847 unsigned int arr_len
)
849 struct symt
* elem
= codeview_fetch_type(ctp
, elemtype
);
850 struct symt
* index
= codeview_fetch_type(ctp
, indextype
);
854 if (symt_get_info(ctp
->module
, elem
, TI_GET_LENGTH
, &elem_size
) && elem_size
)
856 if (arr_len
% (DWORD
)elem_size
)
857 FIXME("array size should be a multiple of element size %u %I64u\n", arr_len
, elem_size
);
858 count
= arr_len
/ (unsigned)elem_size
;
860 return &symt_new_array(ctp
->module
, 0, count
, elem
, index
)->symt
;
863 static BOOL
codeview_add_type_enum_field_list(struct codeview_type_parse
* ctp
,
864 struct symt_enum
* symt
,
867 const union codeview_reftype
* ref_type
;
868 const unsigned char* ptr
;
869 const unsigned char* last
;
870 const union codeview_fieldtype
* type
;
872 if (!typeno
) return TRUE
;
873 if (!(ref_type
= codeview_jump_to_type(ctp
, typeno
))) return FALSE
;
874 ptr
= ref_type
->fieldlist
.list
;
875 last
= (const BYTE
*)ref_type
+ ref_type
->generic
.len
+ 2;
879 if (*ptr
>= 0xf0) /* LF_PAD... */
885 type
= (const union codeview_fieldtype
*)ptr
;
887 switch (type
->generic
.id
)
889 case LF_ENUMERATE_V1
:
891 int value
, vlen
= numeric_leaf(&value
, &type
->enumerate_v1
.value
);
892 const struct p_string
* p_name
= (const struct p_string
*)((const unsigned char*)&type
->enumerate_v1
.value
+ vlen
);
894 symt_add_enum_element(ctp
->module
, symt
, terminate_string(p_name
), value
);
895 ptr
+= 2 + 2 + vlen
+ (1 + p_name
->namelen
);
898 case LF_ENUMERATE_V3
:
900 int value
, vlen
= numeric_leaf(&value
, &type
->enumerate_v3
.value
);
901 const char* name
= (const char*)&type
->enumerate_v3
.value
+ vlen
;
903 symt_add_enum_element(ctp
->module
, symt
, name
, value
);
904 ptr
+= 2 + 2 + vlen
+ (1 + strlen(name
));
909 if (!codeview_add_type_enum_field_list(ctp
, symt
, type
->index_v1
.ref
))
915 if (!codeview_add_type_enum_field_list(ctp
, symt
, type
->index_v2
.ref
))
921 FIXME("Unsupported type %04x in ENUM field list\n", type
->generic
.id
);
928 static void codeview_add_udt_element(struct codeview_type_parse
* ctp
,
929 struct symt_udt
* symt
, const char* name
,
930 int value
, unsigned type
)
932 struct symt
* subtype
;
933 const union codeview_reftype
*cv_type
;
935 if ((cv_type
= codeview_jump_to_type(ctp
, type
)))
937 switch (cv_type
->generic
.id
)
940 symt_add_udt_element(ctp
->module
, symt
, name
,
941 codeview_fetch_type(ctp
, cv_type
->bitfield_v1
.type
),
942 value
, cv_type
->bitfield_v1
.bitoff
,
943 cv_type
->bitfield_v1
.nbits
);
946 symt_add_udt_element(ctp
->module
, symt
, name
,
947 codeview_fetch_type(ctp
, cv_type
->bitfield_v2
.type
),
948 value
, cv_type
->bitfield_v2
.bitoff
,
949 cv_type
->bitfield_v2
.nbits
);
953 subtype
= codeview_fetch_type(ctp
, type
);
957 DWORD64 elem_size
= 0;
958 symt_get_info(ctp
->module
, subtype
, TI_GET_LENGTH
, &elem_size
);
959 symt_add_udt_element(ctp
->module
, symt
, name
, subtype
, value
, 0, 0);
963 static int codeview_add_type_struct_field_list(struct codeview_type_parse
* ctp
,
964 struct symt_udt
* symt
,
965 unsigned fieldlistno
)
967 const unsigned char* ptr
;
968 const unsigned char* last
;
970 const struct p_string
* p_name
;
972 const union codeview_reftype
*type_ref
;
973 const union codeview_fieldtype
* type
;
975 if (!fieldlistno
) return TRUE
;
976 type_ref
= codeview_jump_to_type(ctp
, fieldlistno
);
977 ptr
= type_ref
->fieldlist
.list
;
978 last
= (const BYTE
*)type_ref
+ type_ref
->generic
.len
+ 2;
982 if (*ptr
>= 0xf0) /* LF_PAD... */
988 type
= (const union codeview_fieldtype
*)ptr
;
990 switch (type
->generic
.id
)
993 leaf_len
= numeric_leaf(&value
, &type
->bclass_v1
.offset
);
995 /* FIXME: ignored for now */
997 ptr
+= 2 + 2 + 2 + leaf_len
;
1001 leaf_len
= numeric_leaf(&value
, &type
->bclass_v2
.offset
);
1003 /* FIXME: ignored for now */
1005 ptr
+= 2 + 2 + 4 + leaf_len
;
1009 case LF_IVBCLASS_V1
:
1011 const unsigned short int* p_vboff
;
1013 leaf_len
= numeric_leaf(&value
, &type
->vbclass_v1
.vbpoff
);
1014 p_vboff
= (const unsigned short int*)((const char*)&type
->vbclass_v1
.vbpoff
+ leaf_len
);
1015 vplen
= numeric_leaf(&vpoff
, p_vboff
);
1017 /* FIXME: ignored for now */
1019 ptr
+= 2 + 2 + 2 + 2 + leaf_len
+ vplen
;
1024 case LF_IVBCLASS_V2
:
1026 const unsigned short int* p_vboff
;
1028 leaf_len
= numeric_leaf(&value
, &type
->vbclass_v2
.vbpoff
);
1029 p_vboff
= (const unsigned short int*)((const char*)&type
->vbclass_v2
.vbpoff
+ leaf_len
);
1030 vplen
= numeric_leaf(&vpoff
, p_vboff
);
1032 /* FIXME: ignored for now */
1034 ptr
+= 2 + 2 + 4 + 4 + leaf_len
+ vplen
;
1039 leaf_len
= numeric_leaf(&value
, &type
->member_v1
.offset
);
1040 p_name
= (const struct p_string
*)((const char*)&type
->member_v1
.offset
+ leaf_len
);
1042 codeview_add_udt_element(ctp
, symt
, terminate_string(p_name
), value
,
1043 type
->member_v1
.type
);
1045 ptr
+= 2 + 2 + 2 + leaf_len
+ (1 + p_name
->namelen
);
1049 leaf_len
= numeric_leaf(&value
, &type
->member_v2
.offset
);
1050 p_name
= (const struct p_string
*)((const unsigned char*)&type
->member_v2
.offset
+ leaf_len
);
1052 codeview_add_udt_element(ctp
, symt
, terminate_string(p_name
), value
,
1053 type
->member_v2
.type
);
1055 ptr
+= 2 + 2 + 4 + leaf_len
+ (1 + p_name
->namelen
);
1059 leaf_len
= numeric_leaf(&value
, &type
->member_v3
.offset
);
1060 c_name
= (const char*)&type
->member_v3
.offset
+ leaf_len
;
1062 codeview_add_udt_element(ctp
, symt
, c_name
, value
, type
->member_v3
.type
);
1064 ptr
+= 2 + 2 + 4 + leaf_len
+ (strlen(c_name
) + 1);
1067 case LF_STMEMBER_V1
:
1068 /* FIXME: ignored for now */
1069 ptr
+= 2 + 2 + 2 + (1 + type
->stmember_v1
.p_name
.namelen
);
1072 case LF_STMEMBER_V2
:
1073 /* FIXME: ignored for now */
1074 ptr
+= 2 + 4 + 2 + (1 + type
->stmember_v2
.p_name
.namelen
);
1077 case LF_STMEMBER_V3
:
1078 /* FIXME: ignored for now */
1079 ptr
+= 2 + 4 + 2 + (strlen(type
->stmember_v3
.name
) + 1);
1083 /* FIXME: ignored for now */
1084 ptr
+= 2 + 2 + 2 + (1 + type
->method_v1
.p_name
.namelen
);
1088 /* FIXME: ignored for now */
1089 ptr
+= 2 + 2 + 4 + (1 + type
->method_v2
.p_name
.namelen
);
1093 /* FIXME: ignored for now */
1094 ptr
+= 2 + 2 + 4 + (strlen(type
->method_v3
.name
) + 1);
1097 case LF_NESTTYPE_V1
:
1098 /* FIXME: ignored for now */
1099 ptr
+= 2 + 2 + (1 + type
->nesttype_v1
.p_name
.namelen
);
1102 case LF_NESTTYPE_V2
:
1103 /* FIXME: ignored for now */
1104 ptr
+= 2 + 2 + 4 + (1 + type
->nesttype_v2
.p_name
.namelen
);
1107 case LF_NESTTYPE_V3
:
1108 /* FIXME: ignored for now */
1109 ptr
+= 2 + 2 + 4 + (strlen(type
->nesttype_v3
.name
) + 1);
1112 case LF_VFUNCTAB_V1
:
1113 /* FIXME: ignored for now */
1117 case LF_VFUNCTAB_V2
:
1118 /* FIXME: ignored for now */
1122 case LF_ONEMETHOD_V1
:
1123 /* FIXME: ignored for now */
1124 switch ((type
->onemethod_v1
.attribute
>> 2) & 7)
1126 case 4: case 6: /* (pure) introducing virtual method */
1127 ptr
+= 2 + 2 + 2 + 4 + (1 + type
->onemethod_virt_v1
.p_name
.namelen
);
1131 ptr
+= 2 + 2 + 2 + (1 + type
->onemethod_v1
.p_name
.namelen
);
1136 case LF_ONEMETHOD_V2
:
1137 /* FIXME: ignored for now */
1138 switch ((type
->onemethod_v2
.attribute
>> 2) & 7)
1140 case 4: case 6: /* (pure) introducing virtual method */
1141 ptr
+= 2 + 2 + 4 + 4 + (1 + type
->onemethod_virt_v2
.p_name
.namelen
);
1145 ptr
+= 2 + 2 + 4 + (1 + type
->onemethod_v2
.p_name
.namelen
);
1150 case LF_ONEMETHOD_V3
:
1151 /* FIXME: ignored for now */
1152 switch ((type
->onemethod_v3
.attribute
>> 2) & 7)
1154 case 4: case 6: /* (pure) introducing virtual method */
1155 ptr
+= 2 + 2 + 4 + 4 + (strlen(type
->onemethod_virt_v3
.name
) + 1);
1159 ptr
+= 2 + 2 + 4 + (strlen(type
->onemethod_v3
.name
) + 1);
1165 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v1
.ref
))
1171 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v2
.ref
))
1177 FIXME("Unsupported type %04x in STRUCT field list\n", type
->generic
.id
);
1185 static struct symt
* codeview_new_func_signature(struct codeview_type_parse
* ctp
,
1186 enum CV_call_e call_conv
)
1188 struct symt_function_signature
* sym
;
1190 sym
= symt_new_function_signature(ctp
->module
, NULL
, call_conv
);
1194 static void codeview_add_func_signature_args(struct codeview_type_parse
* ctp
,
1195 struct symt_function_signature
* sym
,
1199 const union codeview_reftype
* reftype
;
1201 sym
->rettype
= codeview_fetch_type(ctp
, ret_type
);
1202 if (args_list
&& (reftype
= codeview_jump_to_type(ctp
, args_list
)))
1205 switch (reftype
->generic
.id
)
1208 for (i
= 0; i
< reftype
->arglist_v1
.num
; i
++)
1209 symt_add_function_signature_parameter(ctp
->module
, sym
,
1210 codeview_fetch_type(ctp
, reftype
->arglist_v1
.args
[i
]));
1213 for (i
= 0; i
< reftype
->arglist_v2
.num
; i
++)
1214 symt_add_function_signature_parameter(ctp
->module
, sym
,
1215 codeview_fetch_type(ctp
, reftype
->arglist_v2
.args
[i
]));
1218 FIXME("Unexpected leaf %x for signature's pmt\n", reftype
->generic
.id
);
1223 static struct symt
* codeview_parse_one_type(struct codeview_type_parse
* ctp
,
1225 const union codeview_type
* type
)
1227 struct symt
* symt
= NULL
;
1228 int value
, leaf_len
;
1229 const struct p_string
* p_name
;
1232 switch (type
->generic
.id
)
1234 case LF_MODIFIER_V1
:
1235 /* FIXME: we don't handle modifiers,
1236 * but read previous type on the curr_type
1238 WARN("Modifier on %x: %s%s%s%s\n",
1239 type
->modifier_v1
.type
,
1240 type
->modifier_v1
.attribute
& 0x01 ? "const " : "",
1241 type
->modifier_v1
.attribute
& 0x02 ? "volatile " : "",
1242 type
->modifier_v1
.attribute
& 0x04 ? "unaligned " : "",
1243 type
->modifier_v1
.attribute
& ~0x07 ? "unknown " : "");
1244 symt
= codeview_fetch_type(ctp
, type
->modifier_v1
.type
);
1246 case LF_MODIFIER_V2
:
1247 /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
1248 WARN("Modifier on %x: %s%s%s%s\n",
1249 type
->modifier_v2
.type
,
1250 type
->modifier_v2
.attribute
& 0x01 ? "const " : "",
1251 type
->modifier_v2
.attribute
& 0x02 ? "volatile " : "",
1252 type
->modifier_v2
.attribute
& 0x04 ? "unaligned " : "",
1253 type
->modifier_v2
.attribute
& ~0x07 ? "unknown " : "");
1254 symt
= codeview_fetch_type(ctp
, type
->modifier_v2
.type
);
1258 symt
= codeview_add_type_pointer(ctp
, type
->pointer_v1
.datatype
);
1261 symt
= codeview_add_type_pointer(ctp
, type
->pointer_v2
.datatype
);
1265 leaf_len
= numeric_leaf(&value
, &type
->array_v1
.arrlen
);
1266 p_name
= (const struct p_string
*)((const unsigned char*)&type
->array_v1
.arrlen
+ leaf_len
);
1267 symt
= codeview_add_type_array(ctp
, terminate_string(p_name
),
1268 type
->array_v1
.elemtype
,
1269 type
->array_v1
.idxtype
, value
);
1272 leaf_len
= numeric_leaf(&value
, &type
->array_v2
.arrlen
);
1273 p_name
= (const struct p_string
*)((const unsigned char*)&type
->array_v2
.arrlen
+ leaf_len
);
1275 symt
= codeview_add_type_array(ctp
, terminate_string(p_name
),
1276 type
->array_v2
.elemtype
,
1277 type
->array_v2
.idxtype
, value
);
1280 leaf_len
= numeric_leaf(&value
, &type
->array_v3
.arrlen
);
1281 c_name
= (const char*)&type
->array_v3
.arrlen
+ leaf_len
;
1283 symt
= codeview_add_type_array(ctp
, c_name
,
1284 type
->array_v3
.elemtype
,
1285 type
->array_v3
.idxtype
, value
);
1288 case LF_STRUCTURE_V1
:
1290 if (!type
->struct_v1
.property
.is_forward_defn
)
1291 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1292 type
->struct_v1
.fieldlist
);
1295 case LF_STRUCTURE_V2
:
1297 if (!type
->struct_v2
.property
.is_forward_defn
)
1298 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1299 type
->struct_v2
.fieldlist
);
1302 case LF_STRUCTURE_V3
:
1304 if (!type
->struct_v3
.property
.is_forward_defn
)
1305 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1306 type
->struct_v3
.fieldlist
);
1310 if (!type
->union_v1
.property
.is_forward_defn
)
1311 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1312 type
->union_v1
.fieldlist
);
1316 if (!type
->union_v2
.property
.is_forward_defn
)
1317 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1318 type
->union_v2
.fieldlist
);
1322 if (!type
->union_v3
.property
.is_forward_defn
)
1323 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1324 type
->union_v3
.fieldlist
);
1329 struct symt_enum
* senum
= (struct symt_enum
*)codeview_get_type(curr_type
, TRUE
);
1330 senum
->base_type
= codeview_fetch_type(ctp
, type
->enumeration_v1
.type
);
1331 codeview_add_type_enum_field_list(ctp
, senum
, type
->enumeration_v1
.fieldlist
);
1337 struct symt_enum
* senum
= (struct symt_enum
*)codeview_get_type(curr_type
, TRUE
);
1338 senum
->base_type
= codeview_fetch_type(ctp
, type
->enumeration_v2
.type
);
1339 codeview_add_type_enum_field_list(ctp
, senum
, type
->enumeration_v2
.fieldlist
);
1345 struct symt_enum
* senum
= (struct symt_enum
*)codeview_get_type(curr_type
, TRUE
);
1346 senum
->base_type
= codeview_fetch_type(ctp
, type
->enumeration_v3
.type
);
1347 codeview_add_type_enum_field_list(ctp
, senum
, type
->enumeration_v3
.fieldlist
);
1351 case LF_PROCEDURE_V1
:
1352 symt
= codeview_new_func_signature(ctp
, type
->procedure_v1
.callconv
);
1353 codeview_add_func_signature_args(ctp
,
1354 (struct symt_function_signature
*)symt
,
1355 type
->procedure_v1
.rvtype
,
1356 type
->procedure_v1
.arglist
);
1358 case LF_PROCEDURE_V2
:
1359 symt
= codeview_new_func_signature(ctp
,type
->procedure_v2
.callconv
);
1360 codeview_add_func_signature_args(ctp
,
1361 (struct symt_function_signature
*)symt
,
1362 type
->procedure_v2
.rvtype
,
1363 type
->procedure_v2
.arglist
);
1366 case LF_MFUNCTION_V1
:
1367 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1368 * nor class information, this would just do for now
1370 symt
= codeview_new_func_signature(ctp
, type
->mfunction_v1
.callconv
);
1371 codeview_add_func_signature_args(ctp
,
1372 (struct symt_function_signature
*)symt
,
1373 type
->mfunction_v1
.rvtype
,
1374 type
->mfunction_v1
.arglist
);
1376 case LF_MFUNCTION_V2
:
1377 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1378 * nor class information, this would just do for now
1380 symt
= codeview_new_func_signature(ctp
, type
->mfunction_v2
.callconv
);
1381 codeview_add_func_signature_args(ctp
,
1382 (struct symt_function_signature
*)symt
,
1383 type
->mfunction_v2
.rvtype
,
1384 type
->mfunction_v2
.arglist
);
1388 /* this is an ugly hack... FIXME when we have C++ support */
1391 snprintf(buf
, sizeof(buf
), "__internal_vt_shape_%x\n", curr_type
);
1392 symt
= &symt_new_udt(ctp
->module
, buf
, 0, UdtStruct
)->symt
;
1396 FIXME("Unsupported type-id leaf %x\n", type
->generic
.id
);
1397 dump(type
, 2 + type
->generic
.len
);
1400 return symt
&& codeview_add_type(curr_type
, symt
) ? symt
: NULL
;
1403 static struct symt
* codeview_load_forwardable_type(struct codeview_type_parse
* ctp
,
1404 const union codeview_type
* type
)
1407 int value
, leaf_len
;
1408 const struct p_string
* p_name
;
1411 switch (type
->generic
.id
)
1413 case LF_STRUCTURE_V1
:
1415 leaf_len
= numeric_leaf(&value
, &type
->struct_v1
.structlen
);
1416 p_name
= (const struct p_string
*)((const unsigned char*)&type
->struct_v1
.structlen
+ leaf_len
);
1417 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
,
1418 type
->generic
.id
== LF_CLASS_V1
? UdtClass
: UdtStruct
)->symt
;
1421 case LF_STRUCTURE_V2
:
1423 leaf_len
= numeric_leaf(&value
, &type
->struct_v2
.structlen
);
1424 p_name
= (const struct p_string
*)((const unsigned char*)&type
->struct_v2
.structlen
+ leaf_len
);
1425 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
,
1426 type
->generic
.id
== LF_CLASS_V2
? UdtClass
: UdtStruct
)->symt
;
1429 case LF_STRUCTURE_V3
:
1431 leaf_len
= numeric_leaf(&value
, &type
->struct_v3
.structlen
);
1432 c_name
= (const char*)&type
->struct_v3
.structlen
+ leaf_len
;
1433 symt
= &symt_new_udt(ctp
->module
, c_name
, value
,
1434 type
->generic
.id
== LF_CLASS_V3
? UdtClass
: UdtStruct
)->symt
;
1438 leaf_len
= numeric_leaf(&value
, &type
->union_v1
.un_len
);
1439 p_name
= (const struct p_string
*)((const unsigned char*)&type
->union_v1
.un_len
+ leaf_len
);
1440 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
, UdtUnion
)->symt
;
1444 leaf_len
= numeric_leaf(&value
, &type
->union_v2
.un_len
);
1445 p_name
= (const struct p_string
*)((const unsigned char*)&type
->union_v2
.un_len
+ leaf_len
);
1446 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
, UdtUnion
)->symt
;
1450 leaf_len
= numeric_leaf(&value
, &type
->union_v3
.un_len
);
1451 c_name
= (const char*)&type
->union_v3
.un_len
+ leaf_len
;
1452 symt
= &symt_new_udt(ctp
->module
, c_name
, value
, UdtUnion
)->symt
;
1456 symt
= &symt_new_enum(ctp
->module
, terminate_string(&type
->enumeration_v1
.p_name
), NULL
)->symt
;
1460 symt
= &symt_new_enum(ctp
->module
, terminate_string(&type
->enumeration_v2
.p_name
), NULL
)->symt
;
1464 symt
= &symt_new_enum(ctp
->module
, type
->enumeration_v3
.name
, NULL
)->symt
;
1467 default: symt
= NULL
;
1472 static inline BOOL
codeview_is_top_level_type(const union codeview_type
* type
)
1474 /* type records we're interested in are the ones referenced by symbols
1475 * The known ranges are (X mark the ones we want):
1476 * X 0000-0016 for V1 types
1477 * 0200-020c for V1 types referenced by other types
1478 * 0400-040f for V1 types (complex lists & sets)
1479 * X 1000-100f for V2 types
1480 * 1200-120c for V2 types referenced by other types
1481 * 1400-140f for V1 types (complex lists & sets)
1482 * X 1500-150d for V3 types
1483 * 8000-8010 for numeric leafes
1485 return !(type
->generic
.id
& 0x8600) || (type
->generic
.id
& 0x0100);
1488 static BOOL
codeview_parse_type_table(struct codeview_type_parse
* ctp
)
1490 unsigned int i
, curr_type
;
1491 const union codeview_type
* type
;
1493 cv_current_module
->first_type_index
= ctp
->header
.first_index
;
1494 cv_current_module
->last_type_index
= ctp
->header
.last_index
;
1495 cv_current_module
->defined_types
= calloc(ctp
->header
.last_index
- ctp
->header
.first_index
,
1496 sizeof(*cv_current_module
->defined_types
));
1498 /* pass I: + load implementation of forwardable types, but without their content
1499 * + merge forward declarations with their implementations (when the later exists)
1500 * + do it in the order generated from PDB hash table to preserve that order
1501 * (several versions coming from different compilations can exist in the PDB file,
1502 * and using PDB order ensures that we use the relevant one.
1503 * (needed for forward resolution and type lookup by name)
1504 * (dbghelp hash table inserts new elements at the end of bucket's list)
1505 * Note: for a given type, we must handle:
1506 * - only an implementation type record
1507 * - only a forward type record (eg using struct foo* without struct foo being defined)
1508 * - a forward type record and on an implementation type record: this is the most common, but
1509 * depending on hash values, we cannot tell which on will show up first
1511 for (i
= 0; i
< ctp
->header
.hash_num_buckets
; i
++)
1513 struct hash_link
* hl
;
1514 for (hl
= ctp
->hash
[i
]; hl
; hl
= hl
->next
)
1517 type
= codeview_jump_to_type(ctp
, hl
->id
);
1518 if (!codeview_is_top_level_type(type
)) continue;
1519 if (codeview_type_is_forward(type
))
1522 /* make the forward declaration point to the implementation (if any) */
1523 if (codeview_resolve_forward_type(ctp
, type
, hl
->id
, &impl_type
))
1525 /* impl already loaded? */
1526 if (!(symt
= codeview_get_type(impl_type
, TRUE
)))
1529 if ((symt
= codeview_load_forwardable_type(ctp
, codeview_jump_to_type(ctp
, impl_type
))))
1530 codeview_add_type(impl_type
, symt
);
1532 FIXME("forward def of %x => %x, unable to load impl\n", hl
->id
, impl_type
);
1536 /* forward type definition without implementation, create empty type */
1537 symt
= codeview_load_forwardable_type(ctp
, type
);
1541 /* if not already loaded (from previous forward declaration), load it */
1542 if (!(symt
= codeview_get_type(hl
->id
, TRUE
)))
1543 symt
= codeview_load_forwardable_type(ctp
, type
);
1545 codeview_add_type(hl
->id
, symt
);
1548 /* pass II: + non forwardable types: load them, but since they can be indirectly
1549 * loaded (from another type), but don't load them twice
1550 * + forwardable types: load their content
1552 for (curr_type
= ctp
->header
.first_index
; curr_type
< ctp
->header
.last_index
; curr_type
++)
1554 type
= codeview_jump_to_type(ctp
, curr_type
);
1555 if (codeview_is_top_level_type(type
) &&
1556 (!codeview_get_type(curr_type
, TRUE
) || codeview_is_forwardable_type(type
)))
1557 codeview_parse_one_type(ctp
, curr_type
, type
);
1563 /*========================================================================
1564 * Process CodeView line number information.
1566 static ULONG_PTR
codeview_get_address(const struct msc_debug_info
* msc_dbg
,
1567 unsigned seg
, unsigned offset
);
1569 static void codeview_snarf_linetab(const struct msc_debug_info
* msc_dbg
, const BYTE
* linetab
,
1570 int size
, BOOL pascal_str
)
1572 const BYTE
* ptr
= linetab
;
1576 const unsigned int* filetab
;
1577 const unsigned int* lt_ptr
;
1578 const unsigned short* linenos
;
1579 const struct startend
* start
;
1581 ULONG_PTR addr
, func_addr0
;
1582 struct symt_function
* func
;
1583 const struct codeview_linetab_block
* ltb
;
1585 nfile
= *(const short*)linetab
;
1586 filetab
= (const unsigned int*)(linetab
+ 2 * sizeof(short));
1588 for (i
= 0; i
< nfile
; i
++)
1590 ptr
= linetab
+ filetab
[i
];
1591 nseg
= *(const short*)ptr
;
1592 lt_ptr
= (const unsigned int*)(ptr
+ 2 * sizeof(short));
1593 start
= (const struct startend
*)(lt_ptr
+ nseg
);
1596 * Now snarf the filename for all of the segments for this file.
1599 source
= source_new(msc_dbg
->module
, NULL
, terminate_string((const struct p_string
*)(start
+ nseg
)));
1601 source
= source_new(msc_dbg
->module
, NULL
, (const char*)(start
+ nseg
));
1603 for (j
= 0; j
< nseg
; j
++)
1605 ltb
= (const struct codeview_linetab_block
*)(linetab
+ *lt_ptr
++);
1606 linenos
= (const unsigned short*)<b
->offsets
[ltb
->num_lines
];
1607 func_addr0
= codeview_get_address(msc_dbg
, ltb
->seg
, start
[j
].start
);
1608 if (!func_addr0
) continue;
1609 for (func
= NULL
, k
= 0; k
< ltb
->num_lines
; k
++)
1611 /* now locate function (if any) */
1612 addr
= func_addr0
+ ltb
->offsets
[k
] - start
[j
].start
;
1613 /* unfortunately, we can have several functions in the same block, if there's no
1614 * gap between them... find the new function if needed
1616 if (!func
|| addr
>= func
->ranges
[0].high
)
1618 func
= (struct symt_function
*)symt_find_symbol_at(msc_dbg
->module
, addr
);
1619 /* FIXME: at least labels support line numbers */
1620 if (!symt_check_tag(&func
->symt
, SymTagFunction
) && !symt_check_tag(&func
->symt
, SymTagInlineSite
))
1622 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1623 ltb
->seg
, ltb
->offsets
[k
], addr
, func
? func
->symt
.tag
: -1);
1628 symt_add_func_line(msc_dbg
->module
, func
, source
, linenos
[k
], addr
);
1634 static const char* pdb_get_string_table_entry(const PDB_STRING_TABLE
* table
, unsigned offset
);
1636 static void codeview_snarf_linetab2(const struct msc_debug_info
* msc_dbg
, const struct cv_module_snarf
* cvmod
)
1639 const void* hdr_last
= (const char*)cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
;
1640 const struct CV_DebugSSubsectionHeader_t
* hdr
;
1641 const struct CV_DebugSSubsectionHeader_t
* hdr_next
;
1642 const struct CV_DebugSSubsectionHeader_t
* hdr_files
= NULL
;
1643 const struct CV_DebugSLinesHeader_t
* lines_hdr
;
1644 const struct CV_DebugSLinesFileBlockHeader_t
* files_hdr
;
1645 const struct CV_Line_t
* lines
;
1646 const struct CV_Checksum_t
* chksms
;
1648 struct symt_function
* func
;
1650 /* locate DEBUG_S_FILECHKSMS (if any) */
1651 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, hdr_last
); hdr
= CV_RECORD_GAP(hdr
, hdr
->cbLen
))
1653 if (hdr
->type
== DEBUG_S_FILECHKSMS
)
1661 TRACE("No DEBUG_S_FILECHKSMS found\n");
1665 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, hdr_last
); hdr
= hdr_next
)
1667 hdr_next
= CV_RECORD_GAP(hdr
, hdr
->cbLen
);
1668 if (!(hdr
->type
& DEBUG_S_IGNORE
))
1670 ULONG_PTR lineblk_base
;
1671 /* FIXME: should also check that whole lines_blk fits in linetab + size */
1675 lines_hdr
= CV_RECORD_AFTER(hdr
);
1676 files_hdr
= CV_RECORD_AFTER(lines_hdr
);
1677 /* Skip blocks that are too small - Intel C Compiler generates these. */
1678 if (!CV_IS_INSIDE(files_hdr
, hdr_next
)) break;
1679 TRACE("block from %04x:%08x #%x\n",
1680 lines_hdr
->segCon
, lines_hdr
->offCon
, lines_hdr
->cbCon
);
1681 chksms
= CV_RECORD_GAP(hdr_files
, files_hdr
->offFile
);
1682 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
)))
1684 WARN("Corrupt PDB file: offset in CHKSMS subsection is invalid\n");
1687 source
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
1688 lineblk_base
= codeview_get_address(msc_dbg
, lines_hdr
->segCon
, lines_hdr
->offCon
);
1689 lines
= CV_RECORD_AFTER(files_hdr
);
1690 for (i
= 0; i
< files_hdr
->nLines
; i
++)
1692 func
= (struct symt_function
*)symt_find_symbol_at(msc_dbg
->module
, lineblk_base
+ lines
[i
].offset
);
1693 /* FIXME: at least labels support line numbers */
1694 if (!symt_check_tag(&func
->symt
, SymTagFunction
) && !symt_check_tag(&func
->symt
, SymTagInlineSite
))
1696 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1697 lines_hdr
->segCon
, lines_hdr
->offCon
+ lines
[i
].offset
, lineblk_base
+ lines
[i
].offset
, func
? func
->symt
.tag
: -1);
1700 symt_add_func_line(msc_dbg
->module
, func
, source
,
1701 lines
[i
].linenumStart
, lineblk_base
+ lines
[i
].offset
);
1704 case DEBUG_S_FILECHKSMS
: /* skip */
1714 /*========================================================================
1715 * Process CodeView symbol information.
1718 static unsigned int codeview_map_offset(const struct msc_debug_info
* msc_dbg
,
1719 unsigned int offset
)
1721 int nomap
= msc_dbg
->nomap
;
1722 const OMAP
* omapp
= msc_dbg
->omapp
;
1725 if (!nomap
|| !omapp
) return offset
;
1727 /* FIXME: use binary search */
1728 for (i
= 0; i
< nomap
- 1; i
++)
1729 if (omapp
[i
].rva
<= offset
&& omapp
[i
+1].rva
> offset
)
1730 return !omapp
[i
].rvaTo
? 0 : omapp
[i
].rvaTo
+ (offset
- omapp
[i
].rva
);
1735 static ULONG_PTR
codeview_get_address(const struct msc_debug_info
* msc_dbg
,
1736 unsigned seg
, unsigned offset
)
1738 int nsect
= msc_dbg
->nsect
;
1739 const IMAGE_SECTION_HEADER
* sectp
= msc_dbg
->sectp
;
1741 if (!seg
|| seg
> nsect
) return 0;
1742 return msc_dbg
->module
->module
.BaseOfImage
+
1743 codeview_map_offset(msc_dbg
, sectp
[seg
-1].VirtualAddress
+ offset
);
1746 static BOOL
func_has_local(struct symt_function
* func
, const char* name
)
1750 for (i
= 0; i
< func
->vchildren
.num_elts
; ++i
)
1752 struct symt
* p
= *(struct symt
**)vector_at(&func
->vchildren
, i
);
1753 if (symt_check_tag(p
, SymTagData
) && !strcmp(((struct symt_data
*)p
)->hash_elt
.name
, name
))
1759 static const union codeview_symbol
* get_next_sym(const union codeview_symbol
* sym
)
1761 return (const union codeview_symbol
*)((const char*)sym
+ sym
->generic
.len
+ 2);
1764 static inline void codeview_add_variable(const struct msc_debug_info
* msc_dbg
,
1765 struct symt_compiland
* compiland
,
1766 struct symt_function
* func
,
1767 struct symt_block
* block
,
1769 unsigned segment
, unsigned offset
,
1770 unsigned symtype
, BOOL is_local
, BOOL in_tls
, BOOL dontcheck
)
1774 struct location loc
;
1776 loc
.kind
= in_tls
? loc_tlsrel
: loc_absolute
;
1778 loc
.offset
= in_tls
? offset
: codeview_get_address(msc_dbg
, segment
, offset
);
1781 if (!is_local
|| in_tls
) WARN("Unsupported construct\n");
1782 symt_add_func_local(msc_dbg
->module
, func
, DataIsStaticLocal
, &loc
, block
,
1783 codeview_get_type(symtype
, FALSE
), name
);
1786 if (!dontcheck
&& !in_tls
)
1788 /* Check that we don't add twice the same variable */
1789 struct hash_table_iter hti
;
1791 struct symt_ht
* sym
;
1793 hash_table_iter_init(&msc_dbg
->module
->ht_symbols
, &hti
, name
);
1794 while ((ptr
= hash_table_iter_up(&hti
)))
1796 sym
= CONTAINING_RECORD(ptr
, struct symt_ht
, hash_elt
);
1797 if (symt_check_tag(&sym
->symt
, SymTagData
) && !strcmp(sym
->hash_elt
.name
, name
))
1799 struct symt_data
* symdata
= (struct symt_data
*)&sym
->symt
;
1800 if (symdata
->kind
== (is_local
? DataIsFileStatic
: DataIsGlobal
) &&
1801 symdata
->u
.var
.kind
== loc
.kind
&&
1802 symdata
->u
.var
.offset
== loc
.offset
&&
1803 symdata
->container
== &compiland
->symt
)
1805 /* We don't compare types yet... Unfortunately, they are not
1806 * always the same typeid... it'd require full type equivalence
1807 * (eg: we've seen 'int* foo' <> 'int[4] foo')
1814 if (is_local
^ (compiland
!= NULL
)) FIXME("Unsupported construct\n");
1815 symt_new_global_variable(msc_dbg
->module
, compiland
, name
, is_local
, loc
, 0,
1816 codeview_get_type(symtype
, FALSE
));
1820 struct cv_local_info
1822 unsigned short kind
; /* the S_DEFRANGE* */
1823 unsigned short ngaps
; /* number of gaps */
1825 unsigned short rangelen
; /* after start */
1828 struct cv_addr_gap gaps
[0];
1831 static const struct cv_addr_gap
* codeview_get_gaps(const union codeview_symbol
* symrange
)
1833 const struct cv_addr_gap
* gap
;
1834 switch (symrange
->generic
.id
)
1836 case S_DEFRANGE
: gap
= symrange
->defrange_v3
.gaps
; break;
1837 case S_DEFRANGE_SUBFIELD
: gap
= symrange
->defrange_subfield_v3
.gaps
; break;
1838 case S_DEFRANGE_REGISTER
: gap
= symrange
->defrange_register_v3
.gaps
; break;
1839 case S_DEFRANGE_FRAMEPOINTER_REL
: gap
= symrange
->defrange_frameptrrel_v3
.gaps
; break;
1840 case S_DEFRANGE_SUBFIELD_REGISTER
: gap
= symrange
->defrange_subfield_register_v3
.gaps
; break;
1841 case S_DEFRANGE_REGISTER_REL
: gap
= symrange
->defrange_registerrel_v3
.gaps
; break;
1842 /* no gaps for that one */
1843 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
1844 default: return NULL
;
1846 return gap
!= (const struct cv_addr_gap
*)get_next_sym(symrange
) ? gap
: NULL
;
1849 static void codeview_xform_range(const struct msc_debug_info
* msc_dbg
,
1850 struct cv_local_info
* locinfo
,
1851 const struct cv_addr_range
* adrange
)
1853 locinfo
->start
= codeview_get_address(msc_dbg
, adrange
->isectStart
, adrange
->offStart
);
1854 locinfo
->rangelen
= adrange
->cbRange
;
1857 static unsigned codeview_defrange_length(const union codeview_symbol
* sym
)
1859 const union codeview_symbol
* first_symrange
= get_next_sym(sym
);
1860 const union codeview_symbol
* symrange
;
1862 for (symrange
= first_symrange
;
1863 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1864 symrange
= get_next_sym(symrange
)) {}
1865 return (const char*)symrange
- (const char*)first_symrange
;
1868 static unsigned codeview_transform_defrange(const struct msc_debug_info
* msc_dbg
,
1869 struct symt_function
* curr_func
,
1870 const union codeview_symbol
* sym
,
1871 struct location
* loc
)
1873 const union codeview_symbol
* first_symrange
= get_next_sym(sym
);
1874 const union codeview_symbol
* symrange
;
1875 const struct cv_addr_gap
* gap
;
1876 unsigned len
, alloc
= sizeof(DWORD
); /* for terminating kind = 0 */
1879 /* we need to transform the cv_addr_range into cv_local_info */
1880 for (symrange
= first_symrange
;
1881 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1882 symrange
= get_next_sym(symrange
))
1884 gap
= codeview_get_gaps(symrange
);
1885 alloc
+= sizeof(struct cv_local_info
) +
1886 (gap
? (const char*)get_next_sym(symrange
) - (const char*)gap
: 0);
1888 /* total length of all S_DEFRANGE* records (in bytes) following S_LOCAL */
1889 len
= (const char*)symrange
- (const char*)first_symrange
;
1891 ptr
= pool_alloc(&msc_dbg
->module
->pool
, alloc
);
1894 struct cv_local_info
* locinfo
= (struct cv_local_info
*)ptr
;
1896 loc
->kind
= loc_cv_local_range
;
1897 loc
->offset
= (DWORD_PTR
)ptr
;
1898 /* transform the cv_addr_range into cv_local_info */
1899 for (symrange
= first_symrange
;
1900 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1901 symrange
= get_next_sym(symrange
))
1903 locinfo
->kind
= symrange
->generic
.id
;
1904 switch (symrange
->generic
.id
)
1907 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_v3
.range
);
1908 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1910 case S_DEFRANGE_SUBFIELD
:
1911 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_subfield_v3
.range
);
1912 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1914 case S_DEFRANGE_REGISTER
:
1915 locinfo
->reg
= symrange
->defrange_register_v3
.reg
;
1916 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_register_v3
.range
);
1918 case S_DEFRANGE_FRAMEPOINTER_REL
:
1919 locinfo
->offset
= symrange
->defrange_frameptrrel_v3
.offFramePointer
;
1920 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_frameptrrel_v3
.range
);
1922 case S_DEFRANGE_SUBFIELD_REGISTER
:
1923 locinfo
->reg
= symrange
->defrange_subfield_register_v3
.reg
;
1924 locinfo
->offset
= symrange
->defrange_subfield_register_v3
.offParent
;
1925 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_subfield_register_v3
.range
);
1927 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
1928 locinfo
->offset
= symrange
->defrange_frameptr_relfullscope_v3
.offFramePointer
;
1929 locinfo
->start
= curr_func
->ranges
[0].low
;
1930 locinfo
->rangelen
= addr_range_size(&curr_func
->ranges
[0]);
1932 case S_DEFRANGE_REGISTER_REL
:
1933 locinfo
->reg
= symrange
->defrange_registerrel_v3
.baseReg
;
1934 locinfo
->offset
= symrange
->defrange_registerrel_v3
.offBasePointer
;
1935 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_registerrel_v3
.range
);
1940 gap
= codeview_get_gaps(symrange
);
1943 unsigned gaplen
= (const char*)get_next_sym(symrange
) - (const char*)gap
;
1944 locinfo
->ngaps
= gaplen
/ sizeof(*gap
);
1945 memcpy(locinfo
->gaps
, gap
, gaplen
);
1946 locinfo
= (struct cv_local_info
*)((char*)(locinfo
+ 1) + gaplen
);
1954 *(DWORD
*)locinfo
= 0; /* store terminating kind == 0 */
1958 loc
->kind
= loc_error
;
1959 loc
->reg
= loc_err_internal
;
1964 static unsigned codeview_binannot_uncompress(const unsigned char** pptr
)
1966 unsigned res
= (unsigned)(-1);
1967 const unsigned char* ptr
= *pptr
;
1969 if ((*ptr
& 0x80) == 0x00)
1970 res
= (unsigned)(*ptr
++);
1971 else if ((*ptr
& 0xC0) == 0x80)
1973 res
= (unsigned)((*ptr
++ & 0x3f) << 8);
1976 else if ((*ptr
& 0xE0) == 0xC0)
1978 res
= (*ptr
++ & 0x1f) << 24;
1979 res
|= *ptr
++ << 16;
1983 else res
= (unsigned)(-1);
1990 const unsigned char* annot
; /* current pointer */
1991 const unsigned char* last_annot
; /* end of binary annotation stream (first byte after) */
1992 unsigned opcode
; /* last decoded opcode */
1993 unsigned arg1
, arg2
;
1996 static BOOL
codeview_advance_binannot(struct cv_binannot
* cvba
)
1998 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
1999 cvba
->opcode
= codeview_binannot_uncompress(&cvba
->annot
);
2000 if (cvba
->opcode
<= BA_OP_Invalid
|| cvba
->opcode
> BA_OP_ChangeColumnEnd
) return FALSE
;
2001 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
2002 cvba
->arg1
= codeview_binannot_uncompress(&cvba
->annot
);
2003 if (cvba
->opcode
== BA_OP_ChangeCodeOffsetAndLineOffset
)
2005 cvba
->arg2
= cvba
->arg1
>> 4;
2008 else if (cvba
->opcode
== BA_OP_ChangeCodeLengthAndCodeOffset
)
2010 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
2011 cvba
->arg2
= codeview_binannot_uncompress(&cvba
->annot
);
2013 else cvba
->arg2
= 0;
2017 static inline int binannot_getsigned(unsigned i
)
2019 return (i
& 1) ? -(int)(i
>> 1) : (int)(i
>> 1);
2022 static BOOL
cv_dbgsubsect_find_inlinee(const struct msc_debug_info
* msc_dbg
,
2024 const struct cv_module_snarf
* cvmod
,
2025 const struct CV_DebugSSubsectionHeader_t
* hdr_files
,
2026 unsigned* srcfile
, unsigned* srcline
)
2028 const struct CV_DebugSSubsectionHeader_t
* hdr
;
2029 const struct CV_DebugSSubsectionHeader_t
* next_hdr
;
2030 const struct CV_InlineeSourceLine_t
* inlsrc
;
2031 const struct CV_InlineeSourceLineEx_t
* inlsrcex
;
2032 const struct CV_Checksum_t
* chksms
;
2034 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
); hdr
= next_hdr
)
2036 next_hdr
= CV_RECORD_GAP(hdr
, hdr
->cbLen
);
2037 if (hdr
->type
!= DEBUG_S_INLINEELINES
) continue;
2038 /* subsection starts with a DWORD signature */
2039 switch (*(DWORD
*)CV_RECORD_AFTER(hdr
))
2041 case CV_INLINEE_SOURCE_LINE_SIGNATURE
:
2042 inlsrc
= CV_RECORD_GAP(hdr
, sizeof(DWORD
));
2043 while (CV_IS_INSIDE(inlsrc
, next_hdr
))
2045 if (inlsrc
->inlinee
== inlineeid
)
2047 chksms
= CV_RECORD_GAP(hdr_files
, inlsrc
->fileId
);
2048 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))) return FALSE
;
2049 *srcfile
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
2050 *srcline
= inlsrc
->sourceLineNum
;
2056 case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
:
2057 inlsrcex
= CV_RECORD_GAP(hdr
, sizeof(DWORD
));
2058 while (CV_IS_INSIDE(inlsrcex
, next_hdr
))
2060 if (inlsrcex
->inlinee
== inlineeid
)
2062 chksms
= CV_RECORD_GAP(hdr_files
, inlsrcex
->fileId
);
2063 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))) return FALSE
;
2064 *srcfile
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
2065 *srcline
= inlsrcex
->sourceLineNum
;
2068 inlsrcex
= CV_RECORD_GAP(inlsrcex
, inlsrcex
->countOfExtraFiles
* sizeof(inlsrcex
->extraFileId
[0]));
2072 FIXME("Unknown signature %lx in INLINEELINES subsection\n", *(DWORD
*)CV_RECORD_AFTER(hdr
));
2079 static inline void inline_site_update_last_range(struct symt_function
* inlined
, unsigned index
, ULONG_PTR hi
)
2081 if (index
&& index
<= inlined
->num_ranges
)
2083 struct addr_range
* range
= &inlined
->ranges
[index
- 1];
2084 /* only change range if it has no span (code start without code end) */
2085 if (range
->low
== range
->high
)
2090 static unsigned inline_site_get_num_ranges(const unsigned char* annot
,
2091 const unsigned char* last_annot
)
2093 struct cv_binannot cvba
;
2094 unsigned num_ranges
= 0;
2097 cvba
.last_annot
= last_annot
;
2099 while (codeview_advance_binannot(&cvba
))
2101 switch (cvba
.opcode
)
2103 case BA_OP_CodeOffset
:
2104 case BA_OP_ChangeCodeLength
:
2105 case BA_OP_ChangeFile
:
2106 case BA_OP_ChangeLineOffset
:
2108 case BA_OP_ChangeCodeOffset
:
2109 case BA_OP_ChangeCodeOffsetAndLineOffset
:
2110 case BA_OP_ChangeCodeLengthAndCodeOffset
:
2114 WARN("Unsupported op %d\n", cvba
.opcode
);
2121 static struct symt_function
* codeview_create_inline_site(const struct msc_debug_info
* msc_dbg
,
2122 const struct cv_module_snarf
* cvmod
,
2123 struct symt_function
* top_func
,
2124 struct symt
* container
,
2125 cv_itemid_t inlinee
,
2126 const unsigned char* annot
,
2127 const unsigned char* last_annot
)
2129 const struct CV_DebugSSubsectionHeader_t
* hdr_files
= NULL
;
2130 const union codeview_type
* cvt
;
2131 struct symt_function
* inlined
;
2132 struct cv_binannot cvba
;
2134 unsigned num_ranges
;
2135 unsigned offset
, index
, line
, srcfile
;
2136 const struct CV_Checksum_t
* chksms
;
2138 if (!cvmod
->ipi_ctp
|| !(cvt
= codeview_jump_to_type(cvmod
->ipi_ctp
, inlinee
)))
2140 FIXME("Couldn't find type %x in IPI stream\n", inlinee
);
2143 num_ranges
= inline_site_get_num_ranges(annot
, last_annot
);
2144 if (!num_ranges
) return NULL
;
2146 switch (cvt
->generic
.id
)
2149 inlined
= symt_new_inlinesite(msc_dbg
->module
, top_func
, container
,
2150 cvt
->func_id_v3
.name
,
2151 codeview_get_type(cvt
->func_id_v3
.type
, FALSE
),
2155 /* FIXME we just declare a function, not a method */
2156 inlined
= symt_new_inlinesite(msc_dbg
->module
, top_func
, container
,
2157 cvt
->mfunc_id_v3
.name
,
2158 codeview_get_type(cvt
->mfunc_id_v3
.type
, FALSE
),
2162 FIXME("unsupported inlinee kind %x\n", cvt
->generic
.id
);
2166 for (hdr_files
= cvmod
->dbgsubsect
;
2167 CV_IS_INSIDE(hdr_files
, cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
);
2168 hdr_files
= CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))
2170 if (hdr_files
->type
== DEBUG_S_FILECHKSMS
)
2173 if (!hdr_files
) return FALSE
;
2174 srcok
= cv_dbgsubsect_find_inlinee(msc_dbg
, inlinee
, cvmod
, hdr_files
, &srcfile
, &line
);
2179 /* rescan all annotations and store ranges & line information */
2183 cvba
.last_annot
= last_annot
;
2185 while (codeview_advance_binannot(&cvba
))
2187 switch (cvba
.opcode
)
2189 case BA_OP_CodeOffset
:
2192 case BA_OP_ChangeCodeOffset
:
2193 offset
+= cvba
.arg1
;
2194 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2196 symt_add_func_line(msc_dbg
->module
, inlined
, srcfile
, line
, top_func
->ranges
[0].low
+ offset
);
2197 inlined
->ranges
[index
].low
= top_func
->ranges
[0].low
+ offset
;
2198 inlined
->ranges
[index
++].high
= top_func
->ranges
[0].low
+ offset
;
2200 case BA_OP_ChangeCodeLength
:
2201 /* this op isn't widely used by MSVC, but clang uses it a lot... */
2202 offset
+= cvba
.arg1
;
2203 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2205 case BA_OP_ChangeFile
:
2206 chksms
= CV_RECORD_GAP(hdr_files
, cvba
.arg1
);
2207 if (CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
)))
2208 srcfile
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
2210 case BA_OP_ChangeLineOffset
:
2211 line
+= binannot_getsigned(cvba
.arg1
);
2213 case BA_OP_ChangeCodeOffsetAndLineOffset
:
2214 line
+= binannot_getsigned(cvba
.arg2
);
2215 offset
+= cvba
.arg1
;
2216 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2218 symt_add_func_line(msc_dbg
->module
, inlined
, srcfile
, line
, top_func
->ranges
[0].low
+ offset
);
2219 inlined
->ranges
[index
].low
= top_func
->ranges
[0].low
+ offset
;
2220 inlined
->ranges
[index
++].high
= top_func
->ranges
[0].low
+ offset
;
2222 case BA_OP_ChangeCodeLengthAndCodeOffset
:
2223 offset
+= cvba
.arg2
;
2224 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2226 symt_add_func_line(msc_dbg
->module
, inlined
, srcfile
, line
, top_func
->ranges
[0].low
+ offset
);
2227 inlined
->ranges
[index
].low
= top_func
->ranges
[0].low
+ offset
;
2228 inlined
->ranges
[index
++].high
= top_func
->ranges
[0].low
+ offset
+ cvba
.arg1
;
2231 WARN("Unsupported op %d\n", cvba
.opcode
);
2235 if (index
!= num_ranges
) /* sanity check */
2236 FIXME("Internal logic error\n");
2237 if (inlined
->num_ranges
)
2239 struct addr_range
* range
= &inlined
->ranges
[inlined
->num_ranges
- 1];
2240 if (range
->low
== range
->high
) WARN("pending empty range at end of %s inside %s\n",
2241 inlined
->hash_elt
.name
,
2242 top_func
->hash_elt
.name
);
2247 static struct symt_compiland
* codeview_new_compiland(const struct msc_debug_info
* msc_dbg
, const char* objname
)
2249 unsigned int src_idx
= source_new(msc_dbg
->module
, NULL
, objname
);
2252 /* In some cases MSVC generates several compiland entries with same pathname in PDB file.
2253 * (for example: for an import library, one compiland entry per imported function is generated).
2254 * But native dbghelp (in this case) merges in a single compiland instance.
2256 for (i
= 0; i
< msc_dbg
->module
->top
->vchildren
.num_elts
; i
++)
2258 struct symt_compiland
** p
= vector_at(&msc_dbg
->module
->top
->vchildren
, i
);
2259 if (symt_check_tag(&(*p
)->symt
, SymTagCompiland
) && (*p
)->source
== src_idx
)
2262 return symt_new_compiland(msc_dbg
->module
, src_idx
);
2265 static BOOL
codeview_snarf(const struct msc_debug_info
* msc_dbg
,
2266 const BYTE
* root
, unsigned offset
, unsigned size
,
2267 const struct cv_module_snarf
* cvmod
,
2268 const char* objname
)
2270 struct symt_function
* top_func
= NULL
;
2271 struct symt_function
* curr_func
= NULL
;
2273 struct symt_block
* block
= NULL
;
2275 struct symt_compiland
* compiland
= NULL
;
2276 struct location loc
;
2278 /* overwrite compiland name from outer context (if any) */
2280 compiland
= codeview_new_compiland(msc_dbg
, objname
);
2282 * Loop over the different types of records and whenever we
2283 * find something we are interested in, record it and move on.
2285 for (i
= offset
; i
< size
; i
+= length
)
2287 const union codeview_symbol
* sym
= (const union codeview_symbol
*)(root
+ i
);
2288 length
= sym
->generic
.len
+ 2;
2289 if (i
+ length
> size
) break;
2290 if (!sym
->generic
.id
|| length
< 4) break;
2291 if (length
& 3) FIXME("unpadded len %u\n", length
);
2293 switch (sym
->generic
.id
)
2296 * Global and local data symbols. We don't associate these
2297 * with any given source file.
2301 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->data_v1
.p_name
),
2302 sym
->data_v1
.segment
, sym
->data_v1
.offset
, sym
->data_v1
.symtype
,
2303 sym
->generic
.id
== S_LDATA32_16t
, FALSE
, TRUE
);
2307 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->data_v2
.p_name
),
2308 sym
->data_v2
.segment
, sym
->data_v2
.offset
, sym
->data_v2
.symtype
,
2309 sym
->generic
.id
== S_LDATA32_ST
, FALSE
, TRUE
);
2313 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, sym
->data_v3
.name
,
2314 sym
->data_v3
.segment
, sym
->data_v3
.offset
, sym
->data_v3
.symtype
,
2315 sym
->generic
.id
== S_LDATA32
, FALSE
, TRUE
);
2318 /* variables with thread storage */
2319 case S_GTHREAD32_16t
:
2320 case S_LTHREAD32_16t
:
2321 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->thread_v1
.p_name
),
2322 sym
->thread_v1
.segment
, sym
->thread_v1
.offset
, sym
->thread_v1
.symtype
,
2323 sym
->generic
.id
== S_LTHREAD32_16t
, TRUE
, TRUE
);
2325 case S_GTHREAD32_ST
:
2326 case S_LTHREAD32_ST
:
2327 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->thread_v2
.p_name
),
2328 sym
->thread_v2
.segment
, sym
->thread_v2
.offset
, sym
->thread_v2
.symtype
,
2329 sym
->generic
.id
== S_LTHREAD32_ST
, TRUE
, TRUE
);
2333 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, sym
->thread_v3
.name
,
2334 sym
->thread_v3
.segment
, sym
->thread_v3
.offset
, sym
->thread_v3
.symtype
,
2335 sym
->generic
.id
== S_LTHREAD32
, TRUE
, TRUE
);
2338 /* Public symbols */
2344 /* will be handled later on in codeview_snarf_public */
2348 * Sort of like a global function, but it just points
2349 * to a thunk, which is a stupid name for what amounts to
2350 * a PLT slot in the normal jargon that everyone else uses.
2353 symt_new_thunk(msc_dbg
->module
, compiland
,
2354 terminate_string(&sym
->thunk_v1
.p_name
), sym
->thunk_v1
.thtype
,
2355 codeview_get_address(msc_dbg
, sym
->thunk_v1
.segment
, sym
->thunk_v1
.offset
),
2356 sym
->thunk_v1
.thunk_len
);
2359 symt_new_thunk(msc_dbg
->module
, compiland
,
2360 sym
->thunk_v3
.name
, sym
->thunk_v3
.thtype
,
2361 codeview_get_address(msc_dbg
, sym
->thunk_v3
.segment
, sym
->thunk_v3
.offset
),
2362 sym
->thunk_v3
.thunk_len
);
2366 * Global and static functions.
2370 if (top_func
) FIXME("nested function\n");
2371 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2372 terminate_string(&sym
->proc_v1
.p_name
),
2373 codeview_get_address(msc_dbg
, sym
->proc_v1
.segment
, sym
->proc_v1
.offset
),
2374 sym
->proc_v1
.proc_len
,
2375 codeview_get_type(sym
->proc_v1
.proctype
, FALSE
));
2376 curr_func
= top_func
;
2377 loc
.kind
= loc_absolute
;
2378 loc
.offset
= sym
->proc_v1
.debug_start
;
2379 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2380 loc
.offset
= sym
->proc_v1
.debug_end
;
2381 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2385 if (top_func
) FIXME("nested function\n");
2386 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2387 terminate_string(&sym
->proc_v2
.p_name
),
2388 codeview_get_address(msc_dbg
, sym
->proc_v2
.segment
, sym
->proc_v2
.offset
),
2389 sym
->proc_v2
.proc_len
,
2390 codeview_get_type(sym
->proc_v2
.proctype
, FALSE
));
2391 curr_func
= top_func
;
2392 loc
.kind
= loc_absolute
;
2393 loc
.offset
= sym
->proc_v2
.debug_start
;
2394 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2395 loc
.offset
= sym
->proc_v2
.debug_end
;
2396 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2400 if (top_func
) FIXME("nested function\n");
2401 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2403 codeview_get_address(msc_dbg
, sym
->proc_v3
.segment
, sym
->proc_v3
.offset
),
2404 sym
->proc_v3
.proc_len
,
2405 codeview_get_type(sym
->proc_v3
.proctype
, FALSE
));
2406 curr_func
= top_func
;
2407 loc
.kind
= loc_absolute
;
2408 loc
.offset
= sym
->proc_v3
.debug_start
;
2409 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2410 loc
.offset
= sym
->proc_v3
.debug_end
;
2411 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2414 * Function parameters and stack variables.
2417 loc
.kind
= loc_regrel
;
2418 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2419 loc
.reg
= CV_REG_EBP
;
2420 loc
.offset
= sym
->stack_v1
.offset
;
2421 symt_add_func_local(msc_dbg
->module
, curr_func
,
2422 sym
->stack_v1
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2424 codeview_get_type(sym
->stack_v1
.symtype
, FALSE
),
2425 terminate_string(&sym
->stack_v1
.p_name
));
2428 loc
.kind
= loc_regrel
;
2429 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2430 loc
.reg
= CV_REG_EBP
;
2431 loc
.offset
= sym
->stack_v2
.offset
;
2432 symt_add_func_local(msc_dbg
->module
, curr_func
,
2433 sym
->stack_v2
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2435 codeview_get_type(sym
->stack_v2
.symtype
, FALSE
),
2436 terminate_string(&sym
->stack_v2
.p_name
));
2439 /* S_BPREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2440 if (func_has_local(curr_func
, sym
->stack_v3
.name
)) break;
2441 loc
.kind
= loc_regrel
;
2442 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2443 loc
.reg
= CV_REG_EBP
;
2444 loc
.offset
= sym
->stack_v3
.offset
;
2445 symt_add_func_local(msc_dbg
->module
, curr_func
,
2446 sym
->stack_v3
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2448 codeview_get_type(sym
->stack_v3
.symtype
, FALSE
),
2449 sym
->stack_v3
.name
);
2452 /* S_REGREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2453 if (func_has_local(curr_func
, sym
->regrel_v3
.name
)) break;
2454 loc
.kind
= loc_regrel
;
2455 loc
.reg
= sym
->regrel_v3
.reg
;
2456 loc
.offset
= sym
->regrel_v3
.offset
;
2457 symt_add_func_local(msc_dbg
->module
, curr_func
,
2458 /* FIXME this is wrong !!! */
2459 sym
->regrel_v3
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2461 codeview_get_type(sym
->regrel_v3
.symtype
, FALSE
),
2462 sym
->regrel_v3
.name
);
2465 case S_REGISTER_16t
:
2466 loc
.kind
= loc_register
;
2467 loc
.reg
= sym
->register_v1
.reg
;
2469 symt_add_func_local(msc_dbg
->module
, curr_func
,
2471 block
, codeview_get_type(sym
->register_v1
.type
, FALSE
),
2472 terminate_string(&sym
->register_v1
.p_name
));
2475 loc
.kind
= loc_register
;
2476 loc
.reg
= sym
->register_v2
.reg
;
2478 symt_add_func_local(msc_dbg
->module
, curr_func
,
2480 block
, codeview_get_type(sym
->register_v2
.type
, FALSE
),
2481 terminate_string(&sym
->register_v2
.p_name
));
2484 /* S_REGISTER can be present after S_LOCAL; prefer S_LOCAL when present */
2485 if (func_has_local(curr_func
, sym
->register_v3
.name
)) break;
2486 loc
.kind
= loc_register
;
2487 loc
.reg
= sym
->register_v3
.reg
;
2489 symt_add_func_local(msc_dbg
->module
, curr_func
,
2491 block
, codeview_get_type(sym
->register_v3
.type
, FALSE
),
2492 sym
->register_v3
.name
);
2496 block
= symt_open_func_block(msc_dbg
->module
, curr_func
, block
, 1);
2497 block
->ranges
[0].low
= codeview_get_address(msc_dbg
, sym
->block_v1
.segment
, sym
->block_v1
.offset
);
2498 block
->ranges
[0].high
= block
->ranges
[0].low
+ sym
->block_v1
.length
;
2501 block
= symt_open_func_block(msc_dbg
->module
, curr_func
, block
, 1);
2502 block
->ranges
[0].low
= codeview_get_address(msc_dbg
, sym
->block_v3
.segment
, sym
->block_v3
.offset
);
2503 block
->ranges
[0].high
= block
->ranges
[0].low
+ sym
->block_v3
.length
;
2509 block
= symt_close_func_block(msc_dbg
->module
, curr_func
, block
);
2513 if (curr_func
!= top_func
) FIXME("shouldn't close a top function with an opened inlined function\n");
2514 top_func
= curr_func
= NULL
;
2519 TRACE("S-Compile-V1 machine:%x language:%x %s\n",
2520 sym
->compile_v1
.machine
, sym
->compile_v1
.flags
.language
, terminate_string(&sym
->compile_v1
.p_name
));
2524 TRACE("S-Compile-V2 machine:%x language:%x %s\n",
2525 sym
->compile2_v2
.machine
, sym
->compile2_v2
.flags
.iLanguage
, terminate_string(&sym
->compile2_v2
.p_name
));
2529 TRACE("S-Compile-V3 machine:%x language:%x %s\n", sym
->compile2_v3
.machine
, sym
->compile2_v3
.flags
.iLanguage
, sym
->compile2_v3
.name
);
2533 TRACE("S-Compile3-V3 machine:%x language:%x %s\n", sym
->compile3_v3
.machine
, sym
->compile3_v3
.flags
.iLanguage
, sym
->compile3_v3
.name
);
2540 TRACE("S-ObjName-V3 %s\n", sym
->objname_v3
.name
);
2542 compiland
= codeview_new_compiland(msc_dbg
, sym
->objname_v3
.name
);
2546 TRACE("S-ObjName-V1 %s\n", terminate_string(&sym
->objname_v1
.p_name
));
2548 compiland
= codeview_new_compiland(msc_dbg
, terminate_string(&sym
->objname_v1
.p_name
));
2554 loc
.kind
= loc_absolute
;
2555 loc
.offset
= codeview_get_address(msc_dbg
, sym
->label_v1
.segment
, sym
->label_v1
.offset
) - curr_func
->ranges
[0].low
;
2556 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagLabel
, &loc
,
2557 terminate_string(&sym
->label_v1
.p_name
));
2559 else symt_new_label(msc_dbg
->module
, compiland
,
2560 terminate_string(&sym
->label_v1
.p_name
),
2561 codeview_get_address(msc_dbg
, sym
->label_v1
.segment
, sym
->label_v1
.offset
));
2566 loc
.kind
= loc_absolute
;
2567 loc
.offset
= codeview_get_address(msc_dbg
, sym
->label_v3
.segment
, sym
->label_v3
.offset
) - curr_func
->ranges
[0].low
;
2568 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagLabel
,
2569 &loc
, sym
->label_v3
.name
);
2571 else symt_new_label(msc_dbg
->module
, compiland
, sym
->label_v3
.name
,
2572 codeview_get_address(msc_dbg
, sym
->label_v3
.segment
, sym
->label_v3
.offset
));
2575 case S_CONSTANT_16t
:
2578 const struct p_string
* name
;
2582 vlen
= leaf_as_variant(&v
, &sym
->constant_v1
.cvalue
);
2583 name
= (const struct p_string
*)((const char*)&sym
->constant_v1
.cvalue
+ vlen
);
2584 se
= codeview_get_type(sym
->constant_v1
.type
, FALSE
);
2586 TRACE("S-Constant-V1 %u %s %x\n", V_INT(&v
), terminate_string(name
), sym
->constant_v1
.type
);
2587 symt_new_constant(msc_dbg
->module
, compiland
, terminate_string(name
),
2594 const struct p_string
* name
;
2598 vlen
= leaf_as_variant(&v
, &sym
->constant_v2
.cvalue
);
2599 name
= (const struct p_string
*)((const char*)&sym
->constant_v2
.cvalue
+ vlen
);
2600 se
= codeview_get_type(sym
->constant_v2
.type
, FALSE
);
2602 TRACE("S-Constant-V2 %u %s %x\n", V_INT(&v
), terminate_string(name
), sym
->constant_v2
.type
);
2603 symt_new_constant(msc_dbg
->module
, compiland
, terminate_string(name
),
2614 vlen
= leaf_as_variant(&v
, &sym
->constant_v3
.cvalue
);
2615 name
= (const char*)&sym
->constant_v3
.cvalue
+ vlen
;
2616 se
= codeview_get_type(sym
->constant_v3
.type
, FALSE
);
2618 TRACE("S-Constant-V3 %u %s %x\n", V_INT(&v
), name
, sym
->constant_v3
.type
);
2619 /* FIXME: we should add this as a constant value */
2620 symt_new_constant(msc_dbg
->module
, compiland
, name
, se
, &v
);
2625 if (sym
->udt_v1
.type
)
2627 if ((symt
= codeview_get_type(sym
->udt_v1
.type
, FALSE
)))
2628 symt_new_typedef(msc_dbg
->module
, symt
,
2629 terminate_string(&sym
->udt_v1
.p_name
));
2631 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2632 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
2636 if (sym
->udt_v2
.type
)
2638 if ((symt
= codeview_get_type(sym
->udt_v2
.type
, FALSE
)))
2639 symt_new_typedef(msc_dbg
->module
, symt
,
2640 terminate_string(&sym
->udt_v2
.p_name
));
2642 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2643 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
2647 if (sym
->udt_v3
.type
)
2649 if ((symt
= codeview_get_type(sym
->udt_v3
.type
, FALSE
)))
2650 symt_new_typedef(msc_dbg
->module
, symt
, sym
->udt_v3
.name
);
2652 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2653 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
2657 /* FIXME: don't store global/static variables accessed through registers... we don't support that
2658 * in locals... anyway, global data record should be present as well (so the variable will be available
2659 * through the global definition, but potentially not updated)
2661 if (!sym
->local_v3
.varflags
.enreg_global
&& !sym
->local_v3
.varflags
.enreg_static
)
2663 length
+= codeview_transform_defrange(msc_dbg
, curr_func
, sym
, &loc
);
2664 symt_add_func_local(msc_dbg
->module
, curr_func
,
2665 sym
->local_v3
.varflags
.is_param
? DataIsParam
: DataIsLocal
,
2667 codeview_get_type(sym
->local_v3
.symtype
, FALSE
),
2668 sym
->local_v3
.name
);
2671 length
+= codeview_defrange_length(sym
);
2675 struct symt_function
* inlined
= codeview_create_inline_site(msc_dbg
, cvmod
, top_func
,
2676 block
? &block
->symt
: &curr_func
->symt
,
2677 sym
->inline_site_v3
.inlinee
,
2678 sym
->inline_site_v3
.binaryAnnotations
,
2679 (const unsigned char*)sym
+ length
);
2682 curr_func
= inlined
;
2687 /* skip all records until paired S_INLINESITE_END */
2688 sym
= (const union codeview_symbol
*)(root
+ sym
->inline_site_v3
.pEnd
);
2689 if (sym
->generic
.id
!= S_INLINESITE_END
) FIXME("complete wreckage\n");
2690 length
= sym
->inline_site_v3
.pEnd
- i
+ sym
->generic
.len
;
2696 struct symt_function
* inlined
= codeview_create_inline_site(msc_dbg
, cvmod
, top_func
,
2697 block
? &block
->symt
: &curr_func
->symt
,
2698 sym
->inline_site2_v3
.inlinee
,
2699 sym
->inline_site2_v3
.binaryAnnotations
,
2700 (const unsigned char*)sym
+ length
);
2703 curr_func
= inlined
;
2708 /* skip all records until paired S_INLINESITE_END */
2709 sym
= (const union codeview_symbol
*)(root
+ sym
->inline_site2_v3
.pEnd
);
2710 if (sym
->generic
.id
!= S_INLINESITE_END
) FIXME("complete wreckage\n");
2711 length
= sym
->inline_site_v3
.pEnd
- i
+ sym
->generic
.len
;
2716 case S_INLINESITE_END
:
2717 block
= symt_check_tag(curr_func
->container
, SymTagBlock
) ?
2718 (struct symt_block
*)curr_func
->container
: NULL
;
2719 curr_func
= (struct symt_function
*)symt_get_upper_inlined(curr_func
);
2723 * These are special, in that they are always followed by an
2724 * additional length-prefixed string which is *not* included
2725 * into the symbol length count. We need to skip it.
2733 name
= (const char*)sym
+ length
;
2734 length
+= (*name
+ 1 + 3) & ~3;
2739 TRACE("Start search: seg=0x%x at offset 0x%08x\n",
2740 sym
->ssearch_v1
.segment
, sym
->ssearch_v1
.offset
);
2744 TRACE("S-Align V1\n");
2746 case S_HEAPALLOCSITE
:
2747 TRACE("S-heap site V3: offset=0x%08x at sect_idx 0x%04x, inst_len 0x%08x, index 0x%08x\n",
2748 sym
->heap_alloc_site_v3
.offset
, sym
->heap_alloc_site_v3
.sect_idx
,
2749 sym
->heap_alloc_site_v3
.inst_len
, sym
->heap_alloc_site_v3
.index
);
2755 ULONG_PTR parent_addr
= codeview_get_address(msc_dbg
, sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2756 struct symt_ht
* parent
= symt_find_symbol_at(msc_dbg
->module
, parent_addr
);
2757 if (symt_check_tag(&parent
->symt
, SymTagFunction
))
2759 struct symt_function
* pfunc
= (struct symt_function
*)parent
;
2760 top_func
= symt_new_function(msc_dbg
->module
, compiland
, pfunc
->hash_elt
.name
,
2761 codeview_get_address(msc_dbg
, sym
->sepcode_v3
.sect
, sym
->sepcode_v3
.off
),
2762 sym
->sepcode_v3
.length
, pfunc
->type
);
2763 curr_func
= top_func
;
2766 WARN("Couldn't find function referenced by S_SEPCODE at %04x:%08x\n",
2767 sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2770 FIXME("S_SEPCODE inside top-level function %s\n", top_func
->hash_elt
.name
);
2773 /* the symbols we can safely ignore for now */
2780 case S_CALLSITEINFO
:
2781 /* even if S_LOCAL groks all the S_DEFRANGE* records following itself,
2782 * those kinds of records can also be present after a S_FILESTATIC record
2783 * so silence them until (at least) S_FILESTATIC is supported
2785 case S_DEFRANGE_REGISTER
:
2786 case S_DEFRANGE_FRAMEPOINTER_REL
:
2787 case S_DEFRANGE_SUBFIELD_REGISTER
:
2788 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
2789 case S_DEFRANGE_REGISTER_REL
:
2797 TRACE("Unsupported symbol id %x\n", sym
->generic
.id
);
2801 FIXME("Unsupported symbol id %x\n", sym
->generic
.id
);
2802 dump(sym
, 2 + sym
->generic
.len
);
2806 if (cvmod
) codeview_snarf_linetab2(msc_dbg
, cvmod
);
2810 static BOOL
codeview_is_inside(const struct cv_local_info
* locinfo
, const struct symt_function
* func
, DWORD_PTR ip
)
2813 /* ip must be in local_info range, but not in any of its gaps */
2814 if (ip
< locinfo
->start
|| ip
>= locinfo
->start
+ locinfo
->rangelen
) return FALSE
;
2815 for (i
= 0; i
< locinfo
->ngaps
; ++i
)
2816 if (func
->ranges
[0].low
+ locinfo
->gaps
[i
].gapStartOffset
<= ip
&&
2817 ip
< func
->ranges
[0].low
+ locinfo
->gaps
[i
].gapStartOffset
+ locinfo
->gaps
[i
].cbRange
)
2822 static void pdb_location_compute(struct process
* pcs
,
2823 const struct module_format
* modfmt
,
2824 const struct symt_function
* func
,
2825 struct location
* loc
)
2827 const struct cv_local_info
* locinfo
;
2831 case loc_cv_local_range
:
2832 for (locinfo
= (const struct cv_local_info
*)loc
->offset
;
2834 locinfo
= (const struct cv_local_info
*)((const char*)(locinfo
+ 1) + locinfo
->ngaps
* sizeof(locinfo
->gaps
[0])))
2836 if (!codeview_is_inside(locinfo
, func
, pcs
->localscope_pc
)) continue;
2837 switch (locinfo
->kind
)
2840 case S_DEFRANGE_SUBFIELD
:
2842 FIXME("Unsupported defrange %d\n", locinfo
->kind
);
2843 loc
->kind
= loc_error
;
2844 loc
->reg
= loc_err_internal
;
2846 case S_DEFRANGE_SUBFIELD_REGISTER
:
2847 FIXME("sub-field part not handled\n");
2849 case S_DEFRANGE_REGISTER
:
2850 loc
->kind
= loc_register
;
2851 loc
->reg
= locinfo
->reg
;
2853 case S_DEFRANGE_REGISTER_REL
:
2854 loc
->kind
= loc_regrel
;
2855 loc
->reg
= locinfo
->reg
;
2856 loc
->offset
= locinfo
->offset
;
2858 case S_DEFRANGE_FRAMEPOINTER_REL
:
2859 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
2860 loc
->kind
= loc_regrel
;
2861 loc
->reg
= modfmt
->module
->cpu
->frame_regno
;
2862 loc
->offset
= locinfo
->offset
;
2869 loc
->kind
= loc_error
;
2870 loc
->reg
= loc_err_internal
;
2873 static void* pdb_read_stream(const struct pdb_file_info
* pdb_file
, DWORD stream_nr
);
2874 static unsigned pdb_get_stream_size(const struct pdb_file_info
* pdb_file
, DWORD stream_nr
);
2876 static BOOL
codeview_snarf_sym_hashtable(const struct msc_debug_info
* msc_dbg
, const BYTE
* symroot
, DWORD symsize
,
2877 const BYTE
* hashroot
, DWORD hashsize
,
2878 BOOL (*feed
)(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
*))
2880 const DBI_HASH_HEADER
* hash_hdr
= (const DBI_HASH_HEADER
*)hashroot
;
2881 unsigned num_hash_records
, i
;
2882 const DBI_HASH_RECORD
* hr
;
2884 if (hashsize
< sizeof(DBI_HASH_HEADER
) ||
2885 hash_hdr
->signature
!= 0xFFFFFFFF ||
2886 hash_hdr
->version
!= 0xeffe0000 + 19990810 ||
2887 (hash_hdr
->hash_records_size
% sizeof(DBI_HASH_RECORD
)) != 0 ||
2888 sizeof(DBI_HASH_HEADER
) + hash_hdr
->hash_records_size
+ DBI_BITMAP_HASH_SIZE
> hashsize
||
2889 (hashsize
- (sizeof(DBI_HASH_HEADER
) + hash_hdr
->hash_records_size
+ DBI_BITMAP_HASH_SIZE
)) % sizeof(unsigned))
2891 FIXME("Incorrect hash structure\n");
2895 hr
= (DBI_HASH_RECORD
*)(hash_hdr
+ 1);
2896 num_hash_records
= hash_hdr
->hash_records_size
/ sizeof(DBI_HASH_RECORD
);
2898 /* Only iterate over the records listed in the hash table.
2899 * We assume that records present in stream, but not listed in hash table, are
2900 * invalid (and thus not loaded).
2902 for (i
= 0; i
< num_hash_records
; i
++)
2904 if (hr
[i
].offset
&& hr
[i
].offset
< symsize
)
2906 const union codeview_symbol
* sym
= (const union codeview_symbol
*)(symroot
+ hr
[i
].offset
- 1);
2907 (*feed
)(msc_dbg
, sym
);
2913 static BOOL
pdb_global_feed_types(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
2916 switch (sym
->generic
.id
)
2919 if (sym
->udt_v1
.type
)
2921 if ((symt
= codeview_get_type(sym
->udt_v1
.type
, FALSE
)))
2922 symt_new_typedef(msc_dbg
->module
, symt
,
2923 terminate_string(&sym
->udt_v1
.p_name
));
2925 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2926 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
2930 if (sym
->udt_v2
.type
)
2932 if ((symt
= codeview_get_type(sym
->udt_v2
.type
, FALSE
)))
2933 symt_new_typedef(msc_dbg
->module
, symt
,
2934 terminate_string(&sym
->udt_v2
.p_name
));
2936 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2937 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
2941 if (sym
->udt_v3
.type
)
2943 if ((symt
= codeview_get_type(sym
->udt_v3
.type
, FALSE
)))
2944 symt_new_typedef(msc_dbg
->module
, symt
, sym
->udt_v3
.name
);
2946 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2947 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
2950 default: return FALSE
;
2955 static BOOL
pdb_global_feed_variables(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
2957 /* The only interest here is to add global variables that haven't been seen
2958 * in module (=compilation unit) stream.
2959 * So we don't care about 'local' symbols since we cannot tell their compiland.
2961 switch (sym
->generic
.id
)
2964 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->data_v1
.p_name
),
2965 sym
->data_v1
.segment
, sym
->data_v1
.offset
, sym
->data_v1
.symtype
,
2966 FALSE
, FALSE
, FALSE
);
2969 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->data_v2
.p_name
),
2970 sym
->data_v2
.segment
, sym
->data_v2
.offset
, sym
->data_v2
.symtype
,
2971 FALSE
, FALSE
, FALSE
);
2974 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, sym
->data_v3
.name
,
2975 sym
->data_v3
.segment
, sym
->data_v3
.offset
, sym
->data_v3
.symtype
,
2976 FALSE
, FALSE
, FALSE
);
2978 /* variables with thread storage */
2979 case S_GTHREAD32_16t
:
2980 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->thread_v1
.p_name
),
2981 sym
->thread_v1
.segment
, sym
->thread_v1
.offset
, sym
->thread_v1
.symtype
,
2982 FALSE
, TRUE
, FALSE
);
2984 case S_GTHREAD32_ST
:
2985 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->thread_v2
.p_name
),
2986 sym
->thread_v2
.segment
, sym
->thread_v2
.offset
, sym
->thread_v2
.symtype
,
2987 FALSE
, TRUE
, FALSE
);
2990 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, sym
->thread_v3
.name
,
2991 sym
->thread_v3
.segment
, sym
->thread_v3
.offset
, sym
->thread_v3
.symtype
,
2992 FALSE
, TRUE
, FALSE
);
2994 default: return FALSE
;
2999 static BOOL
pdb_global_feed_public(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
3001 switch (sym
->generic
.id
)
3004 symt_new_public(msc_dbg
->module
, NULL
,
3005 terminate_string(&sym
->public_v1
.p_name
),
3006 sym
->public_v1
.pubsymflags
== SYMTYPE_FUNCTION
,
3007 codeview_get_address(msc_dbg
, sym
->public_v1
.segment
, sym
->public_v1
.offset
), 1);
3010 symt_new_public(msc_dbg
->module
, NULL
,
3011 terminate_string(&sym
->public_v2
.p_name
),
3012 sym
->public_v2
.pubsymflags
== SYMTYPE_FUNCTION
,
3013 codeview_get_address(msc_dbg
, sym
->public_v2
.segment
, sym
->public_v2
.offset
), 1);
3016 symt_new_public(msc_dbg
->module
, NULL
,
3017 sym
->public_v3
.name
,
3018 sym
->public_v3
.pubsymflags
== SYMTYPE_FUNCTION
,
3019 codeview_get_address(msc_dbg
, sym
->public_v3
.segment
, sym
->public_v3
.offset
), 1);
3021 default: return FALSE
;
3026 /*========================================================================
3030 static void* pdb_jg_read(const struct PDB_JG_HEADER
* pdb
, const WORD
* block_list
,
3036 if (!size
) return NULL
;
3038 num_blocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
3039 buffer
= HeapAlloc(GetProcessHeap(), 0, num_blocks
* pdb
->block_size
);
3040 if (!buffer
) return NULL
;
3042 for (i
= 0; i
< num_blocks
; i
++)
3043 memcpy(buffer
+ i
* pdb
->block_size
,
3044 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
3049 static void* pdb_ds_read(const struct PDB_DS_HEADER
* pdb
, const UINT
*block_list
,
3055 if (!size
) return NULL
;
3057 num_blocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
3058 buffer
= HeapAlloc(GetProcessHeap(), 0, num_blocks
* pdb
->block_size
);
3059 if (!buffer
) return NULL
;
3061 for (i
= 0; i
< num_blocks
; i
++)
3062 memcpy(buffer
+ i
* pdb
->block_size
,
3063 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
3068 static void* pdb_read_jg_stream(const struct PDB_JG_HEADER
* pdb
,
3069 const struct PDB_JG_TOC
* toc
, DWORD stream_nr
)
3071 const WORD
* block_list
;
3074 if (!toc
|| stream_nr
>= toc
->num_streams
) return NULL
;
3076 block_list
= (const WORD
*) &toc
->streams
[toc
->num_streams
];
3077 for (i
= 0; i
< stream_nr
; i
++)
3078 block_list
+= (toc
->streams
[i
].size
+ pdb
->block_size
- 1) / pdb
->block_size
;
3080 return pdb_jg_read(pdb
, block_list
, toc
->streams
[stream_nr
].size
);
3083 static void* pdb_read_ds_stream(const struct PDB_DS_HEADER
* pdb
,
3084 const struct PDB_DS_TOC
* toc
, DWORD stream_nr
)
3086 const UINT
*block_list
;
3089 if (!toc
|| stream_nr
>= toc
->num_streams
) return NULL
;
3090 if (toc
->stream_size
[stream_nr
] == 0 || toc
->stream_size
[stream_nr
] == 0xFFFFFFFF) return NULL
;
3092 block_list
= &toc
->stream_size
[toc
->num_streams
];
3093 for (i
= 0; i
< stream_nr
; i
++)
3094 block_list
+= (toc
->stream_size
[i
] + pdb
->block_size
- 1) / pdb
->block_size
;
3096 return pdb_ds_read(pdb
, block_list
, toc
->stream_size
[stream_nr
]);
3099 static void* pdb_read_stream(const struct pdb_file_info
* pdb_file
,
3102 switch (pdb_file
->kind
)
3105 return pdb_read_jg_stream((const struct PDB_JG_HEADER
*)pdb_file
->image
,
3106 pdb_file
->u
.jg
.toc
, stream_nr
);
3108 return pdb_read_ds_stream((const struct PDB_DS_HEADER
*)pdb_file
->image
,
3109 pdb_file
->u
.ds
.toc
, stream_nr
);
3114 static unsigned pdb_get_stream_size(const struct pdb_file_info
* pdb_file
, DWORD stream_nr
)
3116 switch (pdb_file
->kind
)
3118 case PDB_JG
: return pdb_file
->u
.jg
.toc
->streams
[stream_nr
].size
;
3119 case PDB_DS
: return pdb_file
->u
.ds
.toc
->stream_size
[stream_nr
];
3124 static void pdb_free(void* buffer
)
3126 HeapFree(GetProcessHeap(), 0, buffer
);
3129 static void pdb_free_file(struct pdb_file_info
* pdb_file
)
3131 switch (pdb_file
->kind
)
3134 pdb_free(pdb_file
->u
.jg
.toc
);
3135 pdb_file
->u
.jg
.toc
= NULL
;
3138 pdb_free(pdb_file
->u
.ds
.toc
);
3139 pdb_file
->u
.ds
.toc
= NULL
;
3142 HeapFree(GetProcessHeap(), 0, pdb_file
->stream_dict
);
3145 static struct pdb_stream_name
* pdb_load_stream_name_table(const char* str
, unsigned cb
)
3147 struct pdb_stream_name
* stream_dict
;
3154 pdw
= (DWORD
*)(str
+ cb
);
3158 stream_dict
= HeapAlloc(GetProcessHeap(), 0, (numok
+ 1) * sizeof(struct pdb_stream_name
) + cb
);
3159 if (!stream_dict
) return NULL
;
3160 cpstr
= (char*)(stream_dict
+ numok
+ 1);
3161 memcpy(cpstr
, str
, cb
);
3163 /* bitfield: first dword is len (in dword), then data */
3165 pdw
+= *ok_bits
++ + 1;
3166 pdw
+= *pdw
+ 1; /* skip deleted vector */
3168 for (i
= j
= 0; i
< count
; i
++)
3170 if (ok_bits
[i
/ 32] & (1 << (i
% 32)))
3172 if (j
>= numok
) break;
3173 stream_dict
[j
].name
= &cpstr
[*pdw
++];
3174 stream_dict
[j
].index
= *pdw
++;
3179 stream_dict
[numok
].name
= NULL
;
3183 static unsigned pdb_get_stream_by_name(const struct pdb_file_info
* pdb_file
, const char* name
)
3185 struct pdb_stream_name
* psn
;
3187 for (psn
= pdb_file
->stream_dict
; psn
&& psn
->name
; psn
++)
3189 if (!strcmp(psn
->name
, name
)) return psn
->index
;
3194 static PDB_STRING_TABLE
* pdb_read_strings(const struct pdb_file_info
* pdb_file
)
3197 PDB_STRING_TABLE
*ret
;
3199 idx
= pdb_get_stream_by_name(pdb_file
, "/names");
3202 ret
= pdb_read_stream( pdb_file
, idx
);
3203 if (ret
&& ret
->magic
== 0xeffeeffe &&
3204 sizeof(*ret
) + ret
->length
<= pdb_get_stream_size(pdb_file
, idx
)) return ret
;
3207 WARN("string table not found\n");
3211 static const char* pdb_get_string_table_entry(const PDB_STRING_TABLE
* table
, unsigned offset
)
3213 return (!table
|| offset
>= table
->length
) ? NULL
: (const char*)(table
+ 1) + offset
;
3216 static void pdb_module_remove(struct process
* pcsn
, struct module_format
* modfmt
)
3220 for (i
= 0; i
< modfmt
->u
.pdb_info
->used_subfiles
; i
++)
3222 pdb_free_file(&modfmt
->u
.pdb_info
->pdb_files
[i
]);
3223 if (modfmt
->u
.pdb_info
->pdb_files
[i
].image
)
3224 UnmapViewOfFile(modfmt
->u
.pdb_info
->pdb_files
[i
].image
);
3225 if (modfmt
->u
.pdb_info
->pdb_files
[i
].hMap
)
3226 CloseHandle(modfmt
->u
.pdb_info
->pdb_files
[i
].hMap
);
3228 HeapFree(GetProcessHeap(), 0, modfmt
);
3231 static BOOL
pdb_convert_types_header(PDB_TYPES
* types
, const BYTE
* image
)
3233 if (!image
) return FALSE
;
3235 if (*(const DWORD
*)image
< 19960000) /* FIXME: correct version? */
3237 /* Old version of the types record header */
3238 const PDB_TYPES_OLD
* old
= (const PDB_TYPES_OLD
*)image
;
3239 memset(types
, 0, sizeof(PDB_TYPES
));
3240 types
->version
= old
->version
;
3241 types
->type_offset
= sizeof(PDB_TYPES_OLD
);
3242 types
->type_size
= old
->type_size
;
3243 types
->first_index
= old
->first_index
;
3244 types
->last_index
= old
->last_index
;
3245 types
->hash_stream
= old
->hash_stream
;
3249 /* New version of the types record header */
3250 *types
= *(const PDB_TYPES
*)image
;
3255 static void pdb_convert_symbols_header(PDB_SYMBOLS
* symbols
,
3256 int* header_size
, const BYTE
* image
)
3258 memset(symbols
, 0, sizeof(PDB_SYMBOLS
));
3261 if (*(const DWORD
*)image
!= 0xffffffff)
3263 /* Old version of the symbols record header */
3264 const PDB_SYMBOLS_OLD
* old
= (const PDB_SYMBOLS_OLD
*)image
;
3265 symbols
->version
= 0;
3266 symbols
->module_size
= old
->module_size
;
3267 symbols
->sectcontrib_size
= old
->sectcontrib_size
;
3268 symbols
->segmap_size
= old
->segmap_size
;
3269 symbols
->srcmodule_size
= old
->srcmodule_size
;
3270 symbols
->pdbimport_size
= 0;
3271 symbols
->global_hash_stream
= old
->global_hash_stream
;
3272 symbols
->public_stream
= old
->public_stream
;
3273 symbols
->gsym_stream
= old
->gsym_stream
;
3275 *header_size
= sizeof(PDB_SYMBOLS_OLD
);
3279 /* New version of the symbols record header */
3280 *symbols
= *(const PDB_SYMBOLS
*)image
;
3281 *header_size
= sizeof(PDB_SYMBOLS
);
3285 static void pdb_convert_symbol_file(const PDB_SYMBOLS
* symbols
,
3286 PDB_SYMBOL_FILE_EX
* sfile
,
3287 unsigned* size
, const void* image
)
3290 if (symbols
->version
< 19970000)
3292 const PDB_SYMBOL_FILE
*sym_file
= image
;
3293 memset(sfile
, 0, sizeof(*sfile
));
3294 sfile
->stream
= sym_file
->stream
;
3295 sfile
->range
.index
= sym_file
->range
.index
;
3296 sfile
->symbol_size
= sym_file
->symbol_size
;
3297 sfile
->lineno_size
= sym_file
->lineno_size
;
3298 sfile
->lineno2_size
= sym_file
->lineno2_size
;
3299 *size
= sizeof(PDB_SYMBOL_FILE
) - 1;
3303 memcpy(sfile
, image
, sizeof(PDB_SYMBOL_FILE_EX
));
3304 *size
= sizeof(PDB_SYMBOL_FILE_EX
) - 1;
3308 static void pdb_dispose_type_parse(struct codeview_type_parse
* ctp
)
3310 pdb_free(ctp
->hash_stream
);
3311 free((DWORD
*)ctp
->offset
);
3312 free((DWORD
*)ctp
->hash
);
3313 free((DWORD
*)ctp
->alloc_hash
);
3316 static BOOL
pdb_bitfield_is_bit_set(const unsigned* dw
, unsigned len
, unsigned i
)
3318 if (i
>= len
* sizeof(unsigned) * 8) return FALSE
;
3319 return (dw
[i
>> 5] & (1u << (i
& 31u))) != 0;
3322 static BOOL
pdb_init_type_parse(const struct msc_debug_info
* msc_dbg
,
3323 const struct pdb_file_info
* pdb_file
,
3324 struct codeview_type_parse
* ctp
,
3331 ctp
->hash_stream
= NULL
;
3334 ctp
->alloc_hash
= NULL
;
3335 if (!pdb_convert_types_header(&ctp
->header
, image
))
3338 /* Check for unknown versions */
3339 switch (ctp
->header
.version
)
3341 case 19950410: /* VC 4.0 */
3343 case 19961031: /* VC 5.0 / 6.0 */
3344 case 19990903: /* VC 7.0 */
3345 case 20040203: /* VC 8.0 */
3348 ERR("-Unknown type info version %d\n", ctp
->header
.version
);
3351 if (ctp
->header
.hash_value_size
!= 2 && ctp
->header
.hash_value_size
!= 4)
3353 ERR("-Unsupported hash of size %u\n", ctp
->header
.hash_value_size
);
3356 if (!(ctp
->hash_stream
= pdb_read_stream(pdb_file
, ctp
->header
.hash_stream
)))
3358 if (ctp
->header
.last_index
> ctp
->header
.first_index
)
3360 /* may be reconstruct hash table ? */
3361 FIXME("-No hash table, while types exist\n");
3366 ctp
->module
= msc_dbg
->module
;
3367 /* Reconstruct the types offset table
3368 * Note: the hash stream of the PDB_TYPES only contains a partial table
3369 * (not all the indexes are present, so it requires first a binary search in partial table,
3370 * followed by a linear search...)
3372 offset
= malloc(sizeof(DWORD
) * (ctp
->header
.last_index
- ctp
->header
.first_index
));
3373 if (!offset
) goto oom
;
3374 ctp
->table
= ptr
= image
+ ctp
->header
.type_offset
;
3375 for (i
= ctp
->header
.first_index
; i
< ctp
->header
.last_index
; i
++)
3377 offset
[i
- ctp
->header
.first_index
] = ptr
- ctp
->table
;
3378 ptr
+= ((const union codeview_type
*)ptr
)->generic
.len
+ 2;
3380 ctp
->offset
= offset
;
3381 ctp
->hash
= calloc(ctp
->header
.hash_num_buckets
, sizeof(struct hash_link
*));
3382 if (!ctp
->hash
) goto oom
;
3383 ctp
->alloc_hash
= calloc(ctp
->header
.last_index
- ctp
->header
.first_index
, sizeof(struct hash_link
));
3384 if (!ctp
->alloc_hash
) goto oom
;
3385 for (i
= ctp
->header
.first_index
; i
< ctp
->header
.last_index
; i
++)
3387 unsigned hash_i
= pdb_read_hash_value(ctp
, i
);
3388 ctp
->alloc_hash
[i
- ctp
->header
.first_index
].id
= i
;
3389 ctp
->alloc_hash
[i
- ctp
->header
.first_index
].next
= ctp
->hash
[hash_i
];
3390 ctp
->hash
[hash_i
] = &ctp
->alloc_hash
[i
- ctp
->header
.first_index
];
3392 /* parse the remap table
3393 * => move listed type_id at first position of their hash buckets so that we force remap to them
3395 if (ctp
->hash_stream
&& ctp
->header
.type_remap_size
)
3397 const unsigned* remap
= (const unsigned*)((const BYTE
*)ctp
->hash_stream
+ ctp
->header
.type_remap_offset
);
3398 unsigned i
, capa
, count_present
;
3399 const unsigned* present_bitset
;
3400 remap
++; /* no need of num */
3402 count_present
= *remap
++;
3403 present_bitset
= remap
;
3404 remap
+= count_present
;
3405 remap
+= *remap
+ 1; /* skip deleted bit set */
3406 for (i
= 0; i
< capa
; ++i
)
3408 if (pdb_bitfield_is_bit_set(present_bitset
, count_present
, i
))
3411 struct hash_link
** phl
;
3412 /* remap[0] is an offset for a string in /string stream, followed by type_id to force */
3413 hash_i
= pdb_read_hash_value(ctp
, remap
[1]);
3414 for (phl
= &ctp
->hash
[hash_i
]; *phl
; phl
= &(*phl
)->next
)
3415 if ((*phl
)->id
== remap
[1])
3417 struct hash_link
* hl
= *phl
;
3418 /* move hl node at first position of its hash bucket */
3420 hl
->next
= ctp
->hash
[hash_i
];
3421 ctp
->hash
[hash_i
] = hl
;
3430 pdb_dispose_type_parse(ctp
);
3434 static void pdb_process_types(const struct msc_debug_info
* msc_dbg
,
3435 const struct pdb_file_info
* pdb_file
)
3437 struct codeview_type_parse ctp
;
3438 BYTE
* types_image
= pdb_read_stream(pdb_file
, 2);
3442 if (pdb_init_type_parse(msc_dbg
, pdb_file
, &ctp
, types_image
))
3444 /* Read type table */
3445 codeview_parse_type_table(&ctp
);
3446 pdb_dispose_type_parse(&ctp
);
3448 pdb_free(types_image
);
3452 static const char PDB_JG_IDENT
[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0";
3453 static const char PDB_DS_IDENT
[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
3455 /******************************************************************
3458 * Tries to load a pdb file
3460 static BOOL
pdb_init(struct pdb_file_info
* pdb_file
, const char* image
)
3462 /* check the file header, and if ok, load the TOC */
3463 TRACE("PDB: %.40s\n", debugstr_an(image
, 40));
3465 if (!memcmp(image
, PDB_JG_IDENT
, sizeof(PDB_JG_IDENT
)))
3467 const struct PDB_JG_HEADER
* pdb
= (const struct PDB_JG_HEADER
*)image
;
3468 struct PDB_JG_ROOT
* root
;
3469 struct PDB_JG_TOC
* jg_toc
;
3471 jg_toc
= pdb_jg_read(pdb
, pdb
->toc_block
, pdb
->toc
.size
);
3474 ERR("-Unable to get TOC from .PDB\n");
3477 root
= pdb_read_jg_stream(pdb
, jg_toc
, 1);
3480 ERR("-Unable to get root from .PDB\n");
3484 switch (root
->Version
)
3486 case 19950623: /* VC 4.0 */
3488 case 19960307: /* VC 5.0 */
3489 case 19970604: /* VC 6.0 */
3492 ERR("-Unknown root block version %d\n", root
->Version
);
3494 pdb_file
->kind
= PDB_JG
;
3495 pdb_file
->u
.jg
.toc
= jg_toc
;
3496 TRACE("found JG: age=%x timestamp=%x\n", root
->Age
, root
->TimeDateStamp
);
3497 pdb_file
->stream_dict
= pdb_load_stream_name_table(&root
->names
[0], root
->cbNames
);
3498 pdb_file
->fpoext_stream
= -1;
3502 else if (!memcmp(image
, PDB_DS_IDENT
, sizeof(PDB_DS_IDENT
)))
3504 const struct PDB_DS_HEADER
* pdb
= (const struct PDB_DS_HEADER
*)image
;
3505 struct PDB_DS_ROOT
* root
;
3506 struct PDB_DS_TOC
* ds_toc
;
3508 ds_toc
= pdb_ds_read(pdb
, (const UINT
*)((const char*)pdb
+ pdb
->toc_block
* pdb
->block_size
),
3512 ERR("-Unable to get TOC from .PDB\n");
3515 root
= pdb_read_ds_stream(pdb
, ds_toc
, 1);
3518 ERR("-Unable to get root from .PDB\n");
3522 switch (root
->Version
)
3527 ERR("-Unknown root block version %u\n", root
->Version
);
3529 pdb_file
->kind
= PDB_DS
;
3530 pdb_file
->u
.ds
.toc
= ds_toc
;
3531 TRACE("found DS for: age=%x guid=%s\n", root
->Age
, debugstr_guid(&root
->guid
));
3532 pdb_file
->stream_dict
= pdb_load_stream_name_table(&root
->names
[0], root
->cbNames
);
3533 pdb_file
->fpoext_stream
= -1;
3538 if (0) /* some tool to dump the internal files from a PDB file */
3542 switch (pdb_file
->kind
)
3544 case PDB_JG
: num_streams
= pdb_file
->u
.jg
.toc
->num_streams
; break;
3545 case PDB_DS
: num_streams
= pdb_file
->u
.ds
.toc
->num_streams
; break;
3548 for (i
= 1; i
< num_streams
; i
++)
3550 unsigned char* x
= pdb_read_stream(pdb_file
, i
);
3551 FIXME("********************** [%u]: size=%08x\n",
3552 i
, pdb_get_stream_size(pdb_file
, i
));
3553 dump(x
, pdb_get_stream_size(pdb_file
, i
));
3557 return pdb_file
->stream_dict
!= NULL
;
3560 static BOOL
pdb_process_internal(const struct process
*pcs
,
3561 const struct msc_debug_info
*msc_dbg
,
3562 const WCHAR
*filename
,
3563 struct pdb_module_info
*pdb_module_info
,
3564 unsigned module_index
);
3566 DWORD
pdb_get_file_indexinfo(void* image
, DWORD size
, SYMSRV_INDEX_INFOW
* info
)
3568 /* check the file header, and if ok, load the TOC */
3569 TRACE("PDB: %.40s\n", debugstr_an(image
, 40));
3571 if (!memcmp(image
, PDB_JG_IDENT
, sizeof(PDB_JG_IDENT
)))
3573 const struct PDB_JG_HEADER
* pdb
= (const struct PDB_JG_HEADER
*)image
;
3574 struct PDB_JG_TOC
* jg_toc
;
3575 struct PDB_JG_ROOT
* root
;
3576 DWORD ec
= ERROR_SUCCESS
;
3578 jg_toc
= pdb_jg_read(pdb
, pdb
->toc_block
, pdb
->toc
.size
);
3579 root
= pdb_read_jg_stream(pdb
, jg_toc
, 1);
3582 ERR("-Unable to get root from .PDB\n");
3584 return ERROR_FILE_CORRUPT
;
3586 switch (root
->Version
)
3588 case 19950623: /* VC 4.0 */
3590 case 19960307: /* VC 5.0 */
3591 case 19970604: /* VC 6.0 */
3594 ERR("-Unknown root block version %d\n", root
->Version
);
3595 ec
= ERROR_FILE_CORRUPT
;
3597 if (ec
== ERROR_SUCCESS
)
3599 info
->dbgfile
[0] = '\0';
3600 memset(&info
->guid
, 0, sizeof(GUID
));
3601 info
->guid
.Data1
= root
->TimeDateStamp
;
3602 info
->pdbfile
[0] = '\0';
3603 info
->age
= root
->Age
;
3604 info
->sig
= root
->TimeDateStamp
;
3606 info
->stripped
= FALSE
;
3607 info
->timestamp
= 0;
3615 if (!memcmp(image
, PDB_DS_IDENT
, sizeof(PDB_DS_IDENT
)))
3617 const struct PDB_DS_HEADER
* pdb
= (const struct PDB_DS_HEADER
*)image
;
3618 struct PDB_DS_TOC
* ds_toc
;
3619 struct PDB_DS_ROOT
* root
;
3620 DWORD ec
= ERROR_SUCCESS
;
3622 ds_toc
= pdb_ds_read(pdb
, (const UINT
*)((const char*)pdb
+ pdb
->toc_block
* pdb
->block_size
),
3624 root
= pdb_read_ds_stream(pdb
, ds_toc
, 1);
3628 return ERROR_FILE_CORRUPT
;
3630 switch (root
->Version
)
3635 ERR("-Unknown root block version %u\n", root
->Version
);
3636 ec
= ERROR_FILE_CORRUPT
;
3638 /* The age field is present twice (in PDB_ROOT and in PDB_SYMBOLS ),
3639 * It's the one in PDB_SYMBOLS which is reported.
3641 if (ec
== ERROR_SUCCESS
)
3643 PDB_SYMBOLS
* symbols
= pdb_read_ds_stream(pdb
, ds_toc
, 3);
3645 if (symbols
&& symbols
->version
== 19990903)
3647 info
->age
= symbols
->age
;
3652 ERR("-Unknown symbol info version %u %08x\n", symbols
->version
, symbols
->version
);
3653 ec
= ERROR_FILE_CORRUPT
;
3657 if (ec
== ERROR_SUCCESS
)
3659 info
->dbgfile
[0] = '\0';
3660 info
->guid
= root
->guid
;
3661 info
->pdbfile
[0] = '\0';
3664 info
->stripped
= FALSE
;
3665 info
->timestamp
= 0;
3672 return ERROR_BAD_FORMAT
;
3675 static void pdb_process_symbol_imports(const struct process
*pcs
,
3676 const struct msc_debug_info
*msc_dbg
,
3677 const PDB_SYMBOLS
*symbols
,
3678 const void *symbols_image
,
3680 struct pdb_module_info
*pdb_module_info
,
3681 unsigned module_index
)
3683 if (module_index
== -1 && symbols
&& symbols
->pdbimport_size
)
3685 const PDB_SYMBOL_IMPORT
*imp
;
3691 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)symbols_image
+ sizeof(PDB_SYMBOLS
) +
3692 symbols
->module_size
+ symbols
->sectcontrib_size
+
3693 symbols
->segmap_size
+ symbols
->srcmodule_size
);
3695 last
= (const char*)imp
+ symbols
->pdbimport_size
;
3696 while (imp
< (const PDB_SYMBOL_IMPORT
*)last
)
3698 SYMSRV_INDEX_INFOW info
;
3700 ptr
= (const char*)imp
+ sizeof(*imp
) + strlen(imp
->filename
);
3701 if (i
>= CV_MAX_MODULES
) FIXME("Out of bounds!!!\n");
3702 TRACE("got for %s: age=%u ts=%x\n",
3703 imp
->filename
, imp
->Age
, imp
->TimeDateStamp
);
3704 if (path_find_symbol_file(pcs
, msc_dbg
->module
, imp
->filename
, TRUE
, NULL
, imp
->TimeDateStamp
, imp
->Age
, &info
,
3705 &msc_dbg
->module
->module
.PdbUnmatched
))
3706 pdb_process_internal(pcs
, msc_dbg
, info
.pdbfile
, pdb_module_info
, i
);
3708 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)first
+ ((ptr
- (const char*)first
+ strlen(ptr
) + 1 + 3) & ~3));
3710 pdb_module_info
->used_subfiles
= i
;
3712 if (module_index
== -1)
3715 pdb_module_info
->used_subfiles
= 1;
3717 cv_current_module
= &cv_zmodules
[module_index
];
3718 if (cv_current_module
->allowed
) FIXME("Already allowed??\n");
3719 cv_current_module
->allowed
= TRUE
;
3722 static BOOL
pdb_process_internal(const struct process
*pcs
,
3723 const struct msc_debug_info
*msc_dbg
,
3724 const WCHAR
*filename
,
3725 struct pdb_module_info
*pdb_module_info
,
3726 unsigned module_index
)
3728 HANDLE hFile
= NULL
, hMap
= NULL
;
3730 BYTE
* symbols_image
= NULL
;
3731 PDB_STRING_TABLE
* files_image
= NULL
;
3732 struct pdb_file_info
* pdb_file
;
3734 TRACE("Processing PDB file %ls\n", filename
);
3736 pdb_file
= &pdb_module_info
->pdb_files
[module_index
== -1 ? 0 : module_index
];
3737 /* Open and map() .PDB file */
3738 if ((hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
3739 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
)) == INVALID_HANDLE_VALUE
||
3740 (hMap
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
)) == NULL
||
3741 (image
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) == NULL
)
3743 WARN("Unable to open .PDB file: %ls\n", filename
);
3749 if (!pdb_init(pdb_file
, image
))
3752 UnmapViewOfFile(image
);
3756 pdb_file
->hMap
= hMap
;
3757 pdb_file
->image
= image
;
3758 symbols_image
= pdb_read_stream(pdb_file
, 3);
3761 PDB_SYMBOLS symbols
;
3765 struct codeview_type_parse ipi_ctp
;
3767 int header_size
= 0;
3768 unsigned num_sub_streams
;
3769 const unsigned short* sub_streams
;
3772 pdb_convert_symbols_header(&symbols
, &header_size
, symbols_image
);
3773 switch (symbols
.version
)
3775 case 0: /* VC 4.0 */
3776 case 19960307: /* VC 5.0 */
3777 case 19970606: /* VC 6.0 */
3781 ERR("-Unknown symbol info version %u %08x\n",
3782 symbols
.version
, symbols
.version
);
3785 num_sub_streams
= symbols
.stream_index_size
/ sizeof(sub_streams
[0]);
3786 sub_streams
= (const unsigned short*)((const char*)symbols_image
+ sizeof(PDB_SYMBOLS
) +
3787 symbols
.module_size
+ symbols
.sectcontrib_size
+
3788 symbols
.segmap_size
+ symbols
.srcmodule_size
+
3789 symbols
.pdbimport_size
+ symbols
.unknown2_size
);
3790 if (PDB_SIDX_FPOEXT
< num_sub_streams
)
3791 pdb_file
->fpoext_stream
= sub_streams
[PDB_SIDX_FPOEXT
];
3793 files_image
= pdb_read_strings(pdb_file
);
3795 pdb_process_symbol_imports(pcs
, msc_dbg
, &symbols
, symbols_image
, image
,
3796 pdb_module_info
, module_index
);
3797 pdb_process_types(msc_dbg
, pdb_file
);
3799 ipi_image
= pdb_read_stream(pdb_file
, 4);
3800 ipi_ok
= pdb_init_type_parse(msc_dbg
, pdb_file
, &ipi_ctp
, ipi_image
);
3802 /* Read global types first, so that lookup by name in module (=compilation unit)
3803 * streams' loading can succeed them.
3805 globalimage
= pdb_read_stream(pdb_file
, symbols
.gsym_stream
);
3809 unsigned global_size
= pdb_get_stream_size(pdb_file
, symbols
.gsym_stream
);
3811 data
= pdb_read_stream(pdb_file
, symbols
.global_hash_stream
);
3814 codeview_snarf_sym_hashtable(msc_dbg
, globalimage
, global_size
,
3815 data
, pdb_get_stream_size(pdb_file
, symbols
.global_hash_stream
),
3816 pdb_global_feed_types
);
3817 pdb_free((void*)data
);
3821 /* Read per-module symbols' tables */
3822 file
= symbols_image
+ header_size
;
3823 while (file
- symbols_image
< header_size
+ symbols
.module_size
)
3825 PDB_SYMBOL_FILE_EX sfile
;
3826 const char* file_name
;
3829 HeapValidate(GetProcessHeap(), 0, NULL
);
3830 pdb_convert_symbol_file(&symbols
, &sfile
, &size
, file
);
3832 modimage
= pdb_read_stream(pdb_file
, sfile
.stream
);
3833 file_name
= (const char*)file
+ size
;
3836 struct cv_module_snarf cvmod
= {ipi_ok
? &ipi_ctp
: NULL
, (const void*)(modimage
+ sfile
.symbol_size
), sfile
.lineno2_size
,
3838 codeview_snarf(msc_dbg
, modimage
, sizeof(DWORD
), sfile
.symbol_size
, &cvmod
, file_name
);
3840 if (sfile
.lineno_size
&& sfile
.lineno2_size
)
3841 FIXME("Both line info present... only supporting second\n");
3842 else if (sfile
.lineno_size
)
3843 codeview_snarf_linetab(msc_dbg
,
3844 modimage
+ sfile
.symbol_size
,
3846 pdb_file
->kind
== PDB_JG
);
3850 file_name
+= strlen(file_name
) + 1;
3851 /* now at lib_name */
3852 file
= (BYTE
*)((DWORD_PTR
)(file_name
+ strlen(file_name
) + 1 + 3) & ~3);
3854 /* Load the global variables and constants (if not yet loaded) and public information */
3858 unsigned global_size
= pdb_get_stream_size(pdb_file
, symbols
.gsym_stream
);
3860 data
= pdb_read_stream(pdb_file
, symbols
.global_hash_stream
);
3863 codeview_snarf_sym_hashtable(msc_dbg
, globalimage
, global_size
,
3864 data
, pdb_get_stream_size(pdb_file
, symbols
.global_hash_stream
),
3865 pdb_global_feed_variables
);
3866 pdb_free((void*)data
);
3868 if (!(dbghelp_options
& SYMOPT_NO_PUBLICS
) && (data
= pdb_read_stream(pdb_file
, symbols
.public_stream
)))
3870 const DBI_PUBLIC_HEADER
* pubhdr
= (const DBI_PUBLIC_HEADER
*)data
;
3871 codeview_snarf_sym_hashtable(msc_dbg
, globalimage
, pdb_get_stream_size(pdb_file
, symbols
.gsym_stream
),
3872 (const BYTE
*)(pubhdr
+ 1), pubhdr
->hash_size
, pdb_global_feed_public
);
3873 pdb_free((void*)data
);
3875 pdb_free(globalimage
);
3877 HeapFree(GetProcessHeap(), 0, (DWORD
*)ipi_ctp
.offset
);
3878 pdb_free(ipi_image
);
3881 pdb_process_symbol_imports(pcs
, msc_dbg
, NULL
, NULL
, image
,
3882 pdb_module_info
, module_index
);
3884 pdb_free(symbols_image
);
3885 pdb_free(files_image
);
3890 static BOOL
pdb_process_file(const struct process
*pcs
,
3891 const struct msc_debug_info
*msc_dbg
,
3892 const char *filename
, const GUID
*guid
, DWORD timestamp
, DWORD age
)
3894 struct module_format
* modfmt
;
3895 struct pdb_module_info
* pdb_module_info
;
3896 SYMSRV_INDEX_INFOW info
;
3899 if (!msc_dbg
->module
->dont_load_symbols
&&
3900 path_find_symbol_file(pcs
, msc_dbg
->module
, filename
, TRUE
, guid
, timestamp
, age
, &info
, &unmatched
) &&
3901 (modfmt
= HeapAlloc(GetProcessHeap(), 0,
3902 sizeof(struct module_format
) + sizeof(struct pdb_module_info
))))
3906 pdb_module_info
= (void*)(modfmt
+ 1);
3907 msc_dbg
->module
->format_info
[DFI_PDB
] = modfmt
;
3908 modfmt
->module
= msc_dbg
->module
;
3909 modfmt
->remove
= pdb_module_remove
;
3910 modfmt
->loc_compute
= pdb_location_compute
;
3911 modfmt
->u
.pdb_info
= pdb_module_info
;
3913 memset(cv_zmodules
, 0, sizeof(cv_zmodules
));
3914 codeview_init_basic_types(msc_dbg
->module
);
3915 ret
= pdb_process_internal(pcs
, msc_dbg
, info
.pdbfile
,
3916 msc_dbg
->module
->format_info
[DFI_PDB
]->u
.pdb_info
, -1);
3917 codeview_clear_type_table();
3920 msc_dbg
->module
->module
.SymType
= SymPdb
;
3921 msc_dbg
->module
->module
.PdbSig
= info
.sig
;
3922 msc_dbg
->module
->module
.PdbAge
= info
.age
;
3923 msc_dbg
->module
->module
.PdbSig70
= info
.guid
;
3924 msc_dbg
->module
->module
.PdbUnmatched
= unmatched
;
3925 wcscpy(msc_dbg
->module
->module
.LoadedPdbName
, info
.pdbfile
);
3927 /* FIXME: we could have a finer grain here */
3928 msc_dbg
->module
->module
.LineNumbers
= TRUE
;
3929 msc_dbg
->module
->module
.GlobalSymbols
= TRUE
;
3930 msc_dbg
->module
->module
.TypeInfo
= TRUE
;
3931 msc_dbg
->module
->module
.SourceIndexed
= TRUE
;
3932 msc_dbg
->module
->module
.Publics
= TRUE
;
3936 msc_dbg
->module
->format_info
[DFI_PDB
] = NULL
;
3937 HeapFree(GetProcessHeap(), 0, modfmt
);
3939 msc_dbg
->module
->module
.SymType
= SymNone
;
3941 msc_dbg
->module
->module
.PdbSig70
= *guid
;
3943 memset(&msc_dbg
->module
->module
.PdbSig70
, 0, sizeof(GUID
));
3944 msc_dbg
->module
->module
.PdbSig
= 0;
3945 msc_dbg
->module
->module
.PdbAge
= age
;
3949 /*========================================================================
3950 * FPO unwinding code
3953 /* Stack unwinding is based on postfixed operations.
3954 * Let's define our Postfix EValuator
3956 #define PEV_MAX_LEN 32
3959 struct cpu_stack_walk
* csw
;
3961 struct vector stack
;
3963 struct hash_table values
;
3970 struct hash_table_elt elt
;
3973 #define PEV_ERROR(pev, msg) snprintf((pev)->error, sizeof((pev)->error), "%s", (msg))
3974 #define PEV_ERROR1(pev, msg, pmt) snprintf((pev)->error, sizeof((pev)->error), (msg), (pmt))
3977 static void pev_dump_stack(struct pevaluator
* pev
)
3980 FIXME("stack #%d\n", pev
->stk_index
);
3981 for (i
= 0; i
< pev
->stk_index
; i
++)
3983 FIXME("\t%d) %s\n", i
, *(char**)vector_at(&pev
->stack
, i
));
3988 /* get the value out of an operand (variable or literal) */
3989 static BOOL
pev_get_val(struct pevaluator
* pev
, const char* str
, DWORD_PTR
* val
)
3992 struct hash_table_iter hti
;
3999 hash_table_iter_init(&pev
->values
, &hti
, str
);
4000 while ((ptr
= hash_table_iter_up(&hti
)))
4002 if (!strcmp(CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->elt
.name
, str
))
4004 *val
= CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->value
;
4008 return PEV_ERROR1(pev
, "get_zvalue: no value found (%s)", str
);
4010 *val
= strtol(str
, &n
, 10);
4011 if (n
== str
|| *n
!= '\0')
4012 return PEV_ERROR1(pev
, "get_val: not a literal (%s)", str
);
4017 /* push an operand onto the stack */
4018 static BOOL
pev_push(struct pevaluator
* pev
, const char* elt
)
4021 if (pev
->stk_index
< vector_length(&pev
->stack
))
4022 at
= vector_at(&pev
->stack
, pev
->stk_index
);
4024 at
= vector_add(&pev
->stack
, &pev
->pool
);
4025 if (!at
) return PEV_ERROR(pev
, "push: out of memory");
4026 *at
= pool_strdup(&pev
->pool
, elt
);
4031 /* pop an operand from the stack */
4032 static BOOL
pev_pop(struct pevaluator
* pev
, char* elt
)
4034 char** at
= vector_at(&pev
->stack
, --pev
->stk_index
);
4035 if (!at
) return PEV_ERROR(pev
, "pop: stack empty");
4040 /* pop an operand from the stack, and gets its value */
4041 static BOOL
pev_pop_val(struct pevaluator
* pev
, DWORD_PTR
* val
)
4043 char p
[PEV_MAX_LEN
];
4045 return pev_pop(pev
, p
) && pev_get_val(pev
, p
, val
);
4048 /* set var 'name' a new value (creates the var if it doesn't exist) */
4049 static BOOL
pev_set_value(struct pevaluator
* pev
, const char* name
, DWORD_PTR val
)
4051 struct hash_table_iter hti
;
4054 hash_table_iter_init(&pev
->values
, &hti
, name
);
4055 while ((ptr
= hash_table_iter_up(&hti
)))
4057 if (!strcmp(CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->elt
.name
, name
))
4059 CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->value
= val
;
4065 struct zvalue
* zv
= pool_alloc(&pev
->pool
, sizeof(*zv
));
4066 if (!zv
) return PEV_ERROR(pev
, "set_value: out of memory");
4069 zv
->elt
.name
= pool_strdup(&pev
->pool
, name
);
4070 hash_table_add(&pev
->values
, &zv
->elt
);
4075 /* execute a binary operand from the two top most values on the stack.
4076 * puts result on top of the stack */
4077 static BOOL
pev_binop(struct pevaluator
* pev
, char op
)
4079 char res
[PEV_MAX_LEN
];
4080 DWORD_PTR v1
, v2
, c
;
4082 if (!pev_pop_val(pev
, &v1
) || !pev_pop_val(pev
, &v2
)) return FALSE
;
4085 case '+': c
= v1
+ v2
; break;
4086 case '-': c
= v1
- v2
; break;
4087 case '*': c
= v1
* v2
; break;
4088 case '/': c
= v1
/ v2
; break;
4089 case '%': c
= v1
% v2
; break;
4090 default: return PEV_ERROR1(pev
, "binop: unknown op (%c)", op
);
4092 snprintf(res
, sizeof(res
), "%Id", c
);
4097 /* pops top most operand, dereference it, on pushes the result on top of the stack */
4098 static BOOL
pev_deref(struct pevaluator
* pev
)
4100 char res
[PEV_MAX_LEN
];
4101 DWORD_PTR v1
, v2
= 0;
4103 if (!pev_pop_val(pev
, &v1
)) return FALSE
;
4104 if (!sw_read_mem(pev
->csw
, v1
, &v2
, pev
->csw
->cpu
->word_size
))
4105 return PEV_ERROR1(pev
, "deref: cannot read mem at %Ix\n", v1
);
4106 snprintf(res
, sizeof(res
), "%Id", v2
);
4111 /* assign value to variable (from two top most operands) */
4112 static BOOL
pev_assign(struct pevaluator
* pev
)
4114 char p2
[PEV_MAX_LEN
];
4117 if (!pev_pop_val(pev
, &v1
) || !pev_pop(pev
, p2
)) return FALSE
;
4118 if (p2
[0] != '$') return PEV_ERROR1(pev
, "assign: %s isn't a variable", p2
);
4119 pev_set_value(pev
, p2
, v1
);
4124 /* initializes the postfix evaluator */
4125 static void pev_init(struct pevaluator
* pev
, struct cpu_stack_walk
* csw
,
4126 PDB_FPO_DATA
* fpoext
, struct pdb_cmd_pair
* cpair
)
4129 pool_init(&pev
->pool
, 512);
4130 vector_init(&pev
->stack
, sizeof(char*), 8);
4132 hash_table_init(&pev
->pool
, &pev
->values
, 8);
4133 pev
->error
[0] = '\0';
4134 for (; cpair
->name
; cpair
++)
4135 pev_set_value(pev
, cpair
->name
, *cpair
->pvalue
);
4136 pev_set_value(pev
, ".raSearchStart", fpoext
->start
);
4137 pev_set_value(pev
, ".cbLocals", fpoext
->locals_size
);
4138 pev_set_value(pev
, ".cbParams", fpoext
->params_size
);
4139 pev_set_value(pev
, ".cbSavedRegs", fpoext
->savedregs_size
);
4142 static BOOL
pev_free(struct pevaluator
* pev
, struct pdb_cmd_pair
* cpair
)
4146 if (cpair
) for (; cpair
->name
; cpair
++)
4148 if (pev_get_val(pev
, cpair
->name
, &val
))
4149 *cpair
->pvalue
= val
;
4151 pool_destroy(&pev
->pool
);
4155 static BOOL
pdb_parse_cmd_string(struct cpu_stack_walk
* csw
, PDB_FPO_DATA
* fpoext
,
4156 const char* cmd
, struct pdb_cmd_pair
* cpair
)
4158 char token
[PEV_MAX_LEN
];
4162 struct pevaluator pev
;
4164 if (!cmd
) return FALSE
;
4165 pev_init(&pev
, csw
, fpoext
, cpair
);
4166 for (ptr
= cmd
; !over
; ptr
++)
4168 if (*ptr
== ' ' || (over
= *ptr
== '\0'))
4172 if (!strcmp(token
, "+") || !strcmp(token
, "-") || !strcmp(token
, "*") ||
4173 !strcmp(token
, "/") || !strcmp(token
, "%"))
4175 if (!pev_binop(&pev
, token
[0])) goto done
;
4177 else if (!strcmp(token
, "^"))
4179 if (!pev_deref(&pev
)) goto done
;
4181 else if (!strcmp(token
, "="))
4183 if (!pev_assign(&pev
)) goto done
;
4187 if (!pev_push(&pev
, token
)) goto done
;
4193 if (ptok
- token
>= PEV_MAX_LEN
- 1)
4195 PEV_ERROR1(&pev
, "parse: token too long (%s)", ptr
- (ptok
- token
));
4201 pev_free(&pev
, cpair
);
4204 FIXME("Couldn't evaluate %s => %s\n", wine_dbgstr_a(cmd
), pev
.error
);
4205 pev_free(&pev
, NULL
);
4209 BOOL
pdb_virtual_unwind(struct cpu_stack_walk
*csw
, DWORD_PTR ip
,
4210 union ctx
*context
, struct pdb_cmd_pair
*cpair
)
4212 struct module_pair pair
;
4213 struct pdb_module_info
* pdb_info
;
4214 PDB_FPO_DATA
* fpoext
;
4216 PDB_STRING_TABLE
* strbase
;
4219 if (!module_init_pair(&pair
, csw
->hProcess
, ip
)) return FALSE
;
4220 if (!pair
.effective
->format_info
[DFI_PDB
]) return FALSE
;
4221 pdb_info
= pair
.effective
->format_info
[DFI_PDB
]->u
.pdb_info
;
4222 TRACE("searching %Ix => %Ix\n", ip
, ip
- (DWORD_PTR
)pair
.effective
->module
.BaseOfImage
);
4223 ip
-= (DWORD_PTR
)pair
.effective
->module
.BaseOfImage
;
4225 strbase
= pdb_read_strings(&pdb_info
->pdb_files
[0]);
4226 if (!strbase
) return FALSE
;
4227 fpoext
= pdb_read_stream(&pdb_info
->pdb_files
[0], pdb_info
->pdb_files
[0].fpoext_stream
);
4228 size
= pdb_get_stream_size(&pdb_info
->pdb_files
[0], pdb_info
->pdb_files
[0].fpoext_stream
);
4229 if (fpoext
&& (size
% sizeof(*fpoext
)) == 0)
4231 size
/= sizeof(*fpoext
);
4232 for (i
= 0; i
< size
; i
++)
4234 if (fpoext
[i
].start
<= ip
&& ip
< fpoext
[i
].start
+ fpoext
[i
].func_size
)
4236 TRACE("\t%08x %08x %8x %8x %4x %4x %4x %08x %s\n",
4237 fpoext
[i
].start
, fpoext
[i
].func_size
, fpoext
[i
].locals_size
,
4238 fpoext
[i
].params_size
, fpoext
[i
].maxstack_size
, fpoext
[i
].prolog_size
,
4239 fpoext
[i
].savedregs_size
, fpoext
[i
].flags
,
4240 wine_dbgstr_a(pdb_get_string_table_entry(strbase
, fpoext
[i
].str_offset
)));
4241 ret
= pdb_parse_cmd_string(csw
, &fpoext
[i
],
4242 pdb_get_string_table_entry(strbase
, fpoext
[i
].str_offset
),
4255 /*========================================================================
4256 * Process CodeView debug information.
4259 #define MAKESIG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
4260 #define CODEVIEW_NB09_SIG MAKESIG('N','B','0','9')
4261 #define CODEVIEW_NB10_SIG MAKESIG('N','B','1','0')
4262 #define CODEVIEW_NB11_SIG MAKESIG('N','B','1','1')
4263 #define CODEVIEW_RSDS_SIG MAKESIG('R','S','D','S')
4265 static BOOL
codeview_process_info(const struct process
*pcs
,
4266 const struct msc_debug_info
*msc_dbg
)
4268 const DWORD
* signature
= (const DWORD
*)msc_dbg
->root
;
4271 TRACE("Processing signature %.4s\n", (const char*)signature
);
4275 case CODEVIEW_NB09_SIG
:
4276 case CODEVIEW_NB11_SIG
:
4278 const OMFSignature
* cv
= (const OMFSignature
*)msc_dbg
->root
;
4279 const OMFDirHeader
* hdr
= (const OMFDirHeader
*)(msc_dbg
->root
+ cv
->filepos
);
4280 const OMFDirEntry
* ent
;
4281 const OMFDirEntry
* prev
;
4282 const OMFDirEntry
* next
;
4285 codeview_init_basic_types(msc_dbg
->module
);
4287 for (i
= 0; i
< hdr
->cDir
; i
++)
4289 ent
= (const OMFDirEntry
*)((const BYTE
*)hdr
+ hdr
->cbDirHeader
+ i
* hdr
->cbDirEntry
);
4290 if (ent
->SubSection
== sstGlobalTypes
)
4292 const OMFGlobalTypes
* types
;
4293 struct codeview_type_parse ctp
;
4295 types
= (const OMFGlobalTypes
*)(msc_dbg
->root
+ ent
->lfo
);
4296 ctp
.module
= msc_dbg
->module
;
4297 ctp
.offset
= (const DWORD
*)(types
+ 1);
4298 memset(&ctp
.header
, 0, sizeof(ctp
.header
));
4299 ctp
.header
.first_index
= T_FIRSTDEFINABLETYPE
;
4300 ctp
.header
.last_index
= ctp
.header
.first_index
+ types
->cTypes
;
4301 ctp
.table
= (const BYTE
*)(ctp
.offset
+ types
->cTypes
);
4303 cv_current_module
= &cv_zmodules
[0];
4304 if (cv_current_module
->allowed
) FIXME("Already allowed??\n");
4305 cv_current_module
->allowed
= TRUE
;
4307 codeview_parse_type_table(&ctp
);
4312 ent
= (const OMFDirEntry
*)((const BYTE
*)hdr
+ hdr
->cbDirHeader
);
4313 for (i
= 0; i
< hdr
->cDir
; i
++, ent
= next
)
4315 next
= (i
== hdr
->cDir
-1) ? NULL
:
4316 (const OMFDirEntry
*)((const BYTE
*)ent
+ hdr
->cbDirEntry
);
4317 prev
= (i
== 0) ? NULL
:
4318 (const OMFDirEntry
*)((const BYTE
*)ent
- hdr
->cbDirEntry
);
4320 if (ent
->SubSection
== sstAlignSym
)
4322 codeview_snarf(msc_dbg
, msc_dbg
->root
+ ent
->lfo
, sizeof(DWORD
), ent
->cb
, NULL
, NULL
);
4325 * Check the next and previous entry. If either is a
4326 * sstSrcModule, it contains the line number info for
4329 * FIXME: This is not a general solution!
4331 if (next
&& next
->iMod
== ent
->iMod
&& next
->SubSection
== sstSrcModule
)
4332 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ next
->lfo
,
4335 if (prev
&& prev
->iMod
== ent
->iMod
&& prev
->SubSection
== sstSrcModule
)
4336 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ prev
->lfo
,
4342 msc_dbg
->module
->module
.SymType
= SymCv
;
4343 /* FIXME: we could have a finer grain here */
4344 msc_dbg
->module
->module
.LineNumbers
= TRUE
;
4345 msc_dbg
->module
->module
.GlobalSymbols
= TRUE
;
4346 msc_dbg
->module
->module
.TypeInfo
= TRUE
;
4347 msc_dbg
->module
->module
.SourceIndexed
= TRUE
;
4348 msc_dbg
->module
->module
.Publics
= TRUE
;
4349 codeview_clear_type_table();
4354 case CODEVIEW_NB10_SIG
:
4356 const CODEVIEW_PDB_DATA
* pdb
= (const CODEVIEW_PDB_DATA
*)msc_dbg
->root
;
4357 ret
= pdb_process_file(pcs
, msc_dbg
, pdb
->name
, NULL
, pdb
->timestamp
, pdb
->age
);
4360 case CODEVIEW_RSDS_SIG
:
4362 const OMFSignatureRSDS
* rsds
= (const OMFSignatureRSDS
*)msc_dbg
->root
;
4364 TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
4365 wine_dbgstr_guid(&rsds
->guid
), rsds
->age
, rsds
->name
);
4366 ret
= pdb_process_file(pcs
, msc_dbg
, rsds
->name
, &rsds
->guid
, 0, rsds
->age
);
4370 ERR("Unknown CODEVIEW signature %08lx in module %s\n",
4371 *signature
, debugstr_w(msc_dbg
->module
->modulename
));
4376 msc_dbg
->module
->module
.CVSig
= *signature
;
4377 memcpy(msc_dbg
->module
->module
.CVData
, msc_dbg
->root
,
4378 sizeof(msc_dbg
->module
->module
.CVData
));
4383 /*========================================================================
4384 * Process debug directory.
4386 BOOL
pe_load_debug_directory(const struct process
* pcs
, struct module
* module
,
4387 const BYTE
* mapping
,
4388 const IMAGE_SECTION_HEADER
* sectp
, DWORD nsect
,
4389 const IMAGE_DEBUG_DIRECTORY
* dbg
, int nDbg
)
4393 struct msc_debug_info msc_dbg
;
4395 msc_dbg
.module
= module
;
4396 msc_dbg
.nsect
= nsect
;
4397 msc_dbg
.sectp
= sectp
;
4399 msc_dbg
.omapp
= NULL
;
4405 /* First, watch out for OMAP data */
4406 for (i
= 0; i
< nDbg
; i
++)
4408 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_OMAP_FROM_SRC
)
4410 msc_dbg
.nomap
= dbg
[i
].SizeOfData
/ sizeof(OMAP
);
4411 msc_dbg
.omapp
= (const OMAP
*)(mapping
+ dbg
[i
].PointerToRawData
);
4416 /* Now, try to parse CodeView debug info */
4417 for (i
= 0; i
< nDbg
; i
++)
4419 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
4421 msc_dbg
.root
= mapping
+ dbg
[i
].PointerToRawData
;
4422 if ((ret
= codeview_process_info(pcs
, &msc_dbg
))) goto done
;
4426 /* If not found, try to parse COFF debug info */
4427 for (i
= 0; i
< nDbg
; i
++)
4429 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_COFF
)
4431 msc_dbg
.root
= mapping
+ dbg
[i
].PointerToRawData
;
4432 if ((ret
= coff_process_info(&msc_dbg
))) goto done
;
4436 /* FIXME: this should be supported... this is the debug information for
4437 * functions compiled without a frame pointer (FPO = frame pointer omission)
4438 * the associated data helps finding out the relevant information
4440 for (i
= 0; i
< nDbg
; i
++)
4441 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_FPO
)
4442 FIXME("This guy has FPO information\n");
4446 #define FRAME_TRAP 1
4449 typedef struct _FPO_DATA
4451 DWORD ulOffStart
; /* offset 1st byte of function code */
4452 DWORD cbProcSize
; /* # bytes in function */
4453 DWORD cdwLocals
; /* # bytes in locals/4 */
4454 WORD cdwParams
; /* # bytes in params/4 */
4456 WORD cbProlog
: 8; /* # bytes in prolog */
4457 WORD cbRegs
: 3; /* # regs saved */
4458 WORD fHasSEH
: 1; /* TRUE if SEH in func */
4459 WORD fUseBP
: 1; /* TRUE if EBP has been allocated */
4460 WORD reserved
: 1; /* reserved for future use */
4461 WORD cbFrame
: 2; /* frame type */
4468 ERR("Got a page fault while loading symbols\n");
4473 /* we haven't found yet any debug information, fallback to unmatched pdb */
4474 if (module
->module
.SymType
== SymDeferred
)
4476 SYMSRV_INDEX_INFOW info
= {.sizeofstruct
= sizeof(info
)};
4477 char buffer
[MAX_PATH
];
4481 WideCharToMultiByte(CP_ACP
, 0, module
->module
.LoadedImageName
, -1, buffer
, ARRAY_SIZE(buffer
), 0, NULL
);
4482 ext
= strrchr(buffer
, '.');
4483 if (ext
) strcpy(ext
+ 1, "pdb"); else strcat(buffer
, ".pdb");
4484 options
= SymGetOptions();
4485 SymSetOptions(options
| SYMOPT_LOAD_ANYTHING
);
4486 ret
= pdb_process_file(pcs
, &msc_dbg
, buffer
, &null_guid
, 0, 0);
4487 SymSetOptions(options
);
4488 if (!ret
&& module
->dont_load_symbols
)
4489 module
->module
.TimeDateStamp
= 0;
4495 DWORD
msc_get_file_indexinfo(void* image
, const IMAGE_DEBUG_DIRECTORY
* debug_dir
, DWORD num_dir
, SYMSRV_INDEX_INFOW
* info
)
4498 unsigned num_misc_records
= 0;
4501 memset(&info
->guid
, 0, sizeof(info
->guid
));
4503 info
->dbgfile
[0] = L
'\0';
4504 info
->pdbfile
[0] = L
'\0';
4506 for (i
= 0; i
< num_dir
; i
++)
4508 if (debug_dir
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
4510 const CODEVIEW_PDB_DATA
* data
= (const CODEVIEW_PDB_DATA
*)((char*)image
+ debug_dir
[i
].PointerToRawData
);
4511 const OMFSignatureRSDS
* rsds_data
= (const OMFSignatureRSDS
*)data
;
4512 if (!memcmp(data
->Signature
, "NB10", 4))
4514 info
->age
= data
->age
;
4515 info
->sig
= data
->timestamp
;
4516 MultiByteToWideChar(CP_ACP
, 0, data
->name
, -1, info
->pdbfile
, ARRAY_SIZE(info
->pdbfile
));
4518 if (!memcmp(rsds_data
->Signature
, "RSDS", 4))
4520 info
->age
= rsds_data
->age
;
4521 info
->guid
= rsds_data
->guid
;
4522 MultiByteToWideChar(CP_ACP
, 0, rsds_data
->name
, -1, info
->pdbfile
, ARRAY_SIZE(info
->pdbfile
));
4525 else if (debug_dir
[i
].Type
== IMAGE_DEBUG_TYPE_MISC
&& info
->stripped
)
4527 const IMAGE_DEBUG_MISC
* misc
= (const IMAGE_DEBUG_MISC
*)
4528 ((const char*)image
+ debug_dir
[i
].PointerToRawData
);
4530 wcscpy(info
->dbgfile
, (WCHAR
*)misc
->Data
);
4532 MultiByteToWideChar(CP_ACP
, 0, (const char*)misc
->Data
, -1, info
->dbgfile
, ARRAY_SIZE(info
->dbgfile
));
4536 return info
->stripped
&& !num_misc_records
? ERROR_BAD_EXE_FORMAT
: ERROR_SUCCESS
;
4539 DWORD
dbg_get_file_indexinfo(void* image
, DWORD size
, SYMSRV_INDEX_INFOW
* info
)
4541 const IMAGE_SEPARATE_DEBUG_HEADER
*header
;
4542 DWORD num_directories
;
4544 if (size
< sizeof(*header
)) return ERROR_BAD_EXE_FORMAT
;
4546 if (header
->Signature
!= 0x4944 /* DI */ ||
4547 size
< sizeof(*header
) + header
->NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
) + header
->ExportedNamesSize
+ header
->DebugDirectorySize
)
4548 return ERROR_BAD_EXE_FORMAT
;
4550 /* header is followed by:
4551 * - header->NumberOfSections of IMAGE_SECTION_HEADER
4552 * - header->ExportedNameSize
4553 * - then num_directories of IMAGE_DEBUG_DIRECTORY
4555 num_directories
= header
->DebugDirectorySize
/ sizeof(IMAGE_DEBUG_DIRECTORY
);
4557 if (!num_directories
) return ERROR_BAD_EXE_FORMAT
;
4560 memset(&info
->guid
, 0, sizeof(info
->guid
));
4562 info
->dbgfile
[0] = L
'\0';
4563 info
->pdbfile
[0] = L
'\0';
4564 info
->size
= header
->SizeOfImage
;
4565 /* seems to use header's timestamp, not debug_directory one */
4566 info
->timestamp
= header
->TimeDateStamp
;
4567 info
->stripped
= FALSE
; /* FIXME */
4569 return ERROR_SUCCESS
;