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 struct pdb_stream_name
64 struct pdb_stream_name
* stream_dict
;
65 unsigned fpoext_stream
;
71 struct PDB_JG_TOC
* toc
;
76 struct PDB_DS_TOC
* toc
;
81 /* FIXME: don't make it static */
82 #define CV_MAX_MODULES 32
83 struct pdb_module_info
85 unsigned used_subfiles
;
86 struct pdb_file_info pdb_files
[CV_MAX_MODULES
];
89 #define loc_cv_local_range (loc_user + 0) /* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */
91 struct cv_module_snarf
93 const struct codeview_type_parse
* ipi_ctp
;
94 const struct CV_DebugSSubsectionHeader_t
* dbgsubsect
;
95 unsigned dbgsubsect_size
;
96 const PDB_STRING_TABLE
* strimage
;
99 /*========================================================================
100 * Debug file access helper routines
103 static void dump(const void* ptr
, unsigned len
)
107 const char* hexof
= "0123456789abcdef";
110 for (i
= 0; i
< len
; i
+= 16)
112 sprintf(msg
, "%08x: ", i
);
113 memset(msg
+ 10, ' ', 3 * 16 + 1 + 16);
114 for (j
= 0; j
< min(16, len
- i
); j
++)
116 msg
[10 + 3 * j
+ 0] = hexof
[x
[i
+ j
] >> 4];
117 msg
[10 + 3 * j
+ 1] = hexof
[x
[i
+ j
] & 15];
118 msg
[10 + 3 * j
+ 2] = ' ';
119 msg
[10 + 3 * 16 + 1 + j
] = (x
[i
+ j
] >= 0x20 && x
[i
+ j
] < 0x7f) ?
122 msg
[10 + 3 * 16] = ' ';
123 msg
[10 + 3 * 16 + 1 + 16] = '\0';
128 /*========================================================================
129 * Process CodeView type information.
132 static struct symt
* cv_basic_types
[T_MAXPREDEFINEDTYPE
];
134 struct cv_defined_module
137 unsigned int first_type_index
;
138 unsigned int last_type_index
;
139 struct symt
** defined_types
;
141 /* FIXME: don't make it static */
142 #define CV_MAX_MODULES 32
143 static struct cv_defined_module cv_zmodules
[CV_MAX_MODULES
];
144 static struct cv_defined_module
*cv_current_module
;
146 static void codeview_init_basic_types(struct module
* module
)
148 unsigned ptrsz
= module
->cpu
->word_size
;
151 * These are the common builtin types that are used by VC++.
153 cv_basic_types
[T_NOTYPE
] = NULL
;
154 cv_basic_types
[T_ABS
] = NULL
;
155 cv_basic_types
[T_VOID
] = &symt_get_basic(btVoid
, 0)->symt
; /* void */
156 cv_basic_types
[T_CHAR
] = &symt_get_basic(btInt
, 1)->symt
; /* signed char (and char in C) */
157 cv_basic_types
[T_SHORT
] = &symt_get_basic(btInt
, 2)->symt
; /* short int */
158 cv_basic_types
[T_LONG
] = &symt_get_basic(btLong
, 4)->symt
; /* long int */
159 cv_basic_types
[T_QUAD
] = &symt_get_basic(btInt
, 8)->symt
; /* long long int */
160 cv_basic_types
[T_UCHAR
] = &symt_get_basic(btUInt
, 1)->symt
; /* unsigned char */
161 cv_basic_types
[T_USHORT
] = &symt_get_basic(btUInt
, 2)->symt
; /* unsigned short */
162 cv_basic_types
[T_ULONG
] = &symt_get_basic(btULong
, 4)->symt
; /* unsigned long */
163 cv_basic_types
[T_UQUAD
] = &symt_get_basic(btUInt
, 8)->symt
; /* unsigned long long */
164 cv_basic_types
[T_BOOL08
] = &symt_get_basic(btBool
, 1)->symt
; /* BOOL08 */
165 cv_basic_types
[T_BOOL16
] = &symt_get_basic(btBool
, 2)->symt
; /* BOOL16 */
166 cv_basic_types
[T_BOOL32
] = &symt_get_basic(btBool
, 4)->symt
; /* BOOL32 */
167 cv_basic_types
[T_BOOL64
] = &symt_get_basic(btBool
, 8)->symt
; /* BOOL64 */
168 cv_basic_types
[T_REAL32
] = &symt_get_basic(btFloat
, 4)->symt
; /* float */
169 cv_basic_types
[T_REAL64
] = &symt_get_basic(btFloat
, 8)->symt
; /* double */
170 cv_basic_types
[T_REAL80
] = &symt_get_basic(btFloat
, 10)->symt
; /* long double */
171 cv_basic_types
[T_RCHAR
] = &symt_get_basic(btChar
, 1)->symt
; /* "real" char (char in C++) */
172 cv_basic_types
[T_WCHAR
] = &symt_get_basic(btWChar
, 2)->symt
; /* char8_t */
173 cv_basic_types
[T_CHAR16
] = &symt_get_basic(btChar16
, 2)->symt
; /* char16_t */
174 cv_basic_types
[T_CHAR32
] = &symt_get_basic(btChar32
, 4)->symt
; /* char32_t */
175 cv_basic_types
[T_CHAR8
] = &symt_get_basic(btChar8
, 1)->symt
; /* char8_t */
176 cv_basic_types
[T_INT2
] = &symt_get_basic(btInt
, 2)->symt
; /* INT2 */
177 cv_basic_types
[T_UINT2
] = &symt_get_basic(btUInt
, 2)->symt
; /* UINT2 */
178 cv_basic_types
[T_INT4
] = &symt_get_basic(btInt
, 4)->symt
; /* INT4 */
179 cv_basic_types
[T_UINT4
] = &symt_get_basic(btUInt
, 4)->symt
; /* UINT4 */
180 cv_basic_types
[T_INT8
] = &symt_get_basic(btInt
, 8)->symt
; /* INT8 */
181 cv_basic_types
[T_UINT8
] = &symt_get_basic(btUInt
, 8)->symt
; /* UINT8 */
182 cv_basic_types
[T_HRESULT
]= &symt_get_basic(btUInt
, 4)->symt
; /* HRESULT */
184 cv_basic_types
[T_32PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], 4)->symt
;
185 cv_basic_types
[T_32PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], 4)->symt
;
186 cv_basic_types
[T_32PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], 4)->symt
;
187 cv_basic_types
[T_32PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], 4)->symt
;
188 cv_basic_types
[T_32PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], 4)->symt
;
189 cv_basic_types
[T_32PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], 4)->symt
;
190 cv_basic_types
[T_32PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], 4)->symt
;
191 cv_basic_types
[T_32PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], 4)->symt
;
192 cv_basic_types
[T_32PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], 4)->symt
;
193 cv_basic_types
[T_32PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], 4)->symt
;
194 cv_basic_types
[T_32PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], 4)->symt
;
195 cv_basic_types
[T_32PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], 4)->symt
;
196 cv_basic_types
[T_32PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], 4)->symt
;
197 cv_basic_types
[T_32PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], 4)->symt
;
198 cv_basic_types
[T_32PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], 4)->symt
;
199 cv_basic_types
[T_32PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], 4)->symt
;
200 cv_basic_types
[T_32PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], 4)->symt
;
201 cv_basic_types
[T_32PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], 4)->symt
;
202 cv_basic_types
[T_32PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], 4)->symt
;
203 cv_basic_types
[T_32PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], 4)->symt
;
204 cv_basic_types
[T_32PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], 4)->symt
;
205 cv_basic_types
[T_32PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], 4)->symt
;
206 cv_basic_types
[T_32PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], 4)->symt
;
207 cv_basic_types
[T_32PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], 4)->symt
;
208 cv_basic_types
[T_32PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], 4)->symt
;
209 cv_basic_types
[T_32PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], 4)->symt
;
210 cv_basic_types
[T_32PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], 4)->symt
;
211 cv_basic_types
[T_32PHRESULT
]= &symt_new_pointer(module
, cv_basic_types
[T_HRESULT
], 4)->symt
;
213 cv_basic_types
[T_64PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], 8)->symt
;
214 cv_basic_types
[T_64PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], 8)->symt
;
215 cv_basic_types
[T_64PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], 8)->symt
;
216 cv_basic_types
[T_64PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], 8)->symt
;
217 cv_basic_types
[T_64PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], 8)->symt
;
218 cv_basic_types
[T_64PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], 8)->symt
;
219 cv_basic_types
[T_64PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], 8)->symt
;
220 cv_basic_types
[T_64PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], 8)->symt
;
221 cv_basic_types
[T_64PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], 8)->symt
;
222 cv_basic_types
[T_64PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], 8)->symt
;
223 cv_basic_types
[T_64PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], 8)->symt
;
224 cv_basic_types
[T_64PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], 8)->symt
;
225 cv_basic_types
[T_64PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], 8)->symt
;
226 cv_basic_types
[T_64PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], 8)->symt
;
227 cv_basic_types
[T_64PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], 8)->symt
;
228 cv_basic_types
[T_64PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], 8)->symt
;
229 cv_basic_types
[T_64PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], 8)->symt
;
230 cv_basic_types
[T_64PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], 8)->symt
;
231 cv_basic_types
[T_64PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], 8)->symt
;
232 cv_basic_types
[T_64PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], 8)->symt
;
233 cv_basic_types
[T_64PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], 8)->symt
;
234 cv_basic_types
[T_64PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], 8)->symt
;
235 cv_basic_types
[T_64PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], 8)->symt
;
236 cv_basic_types
[T_64PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], 8)->symt
;
237 cv_basic_types
[T_64PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], 8)->symt
;
238 cv_basic_types
[T_64PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], 8)->symt
;
239 cv_basic_types
[T_64PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], 8)->symt
;
240 cv_basic_types
[T_64PHRESULT
]= &symt_new_pointer(module
, cv_basic_types
[T_HRESULT
], 8)->symt
;
242 cv_basic_types
[T_PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], ptrsz
)->symt
;
243 cv_basic_types
[T_PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], ptrsz
)->symt
;
244 cv_basic_types
[T_PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], ptrsz
)->symt
;
245 cv_basic_types
[T_PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], ptrsz
)->symt
;
246 cv_basic_types
[T_PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], ptrsz
)->symt
;
247 cv_basic_types
[T_PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], ptrsz
)->symt
;
248 cv_basic_types
[T_PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], ptrsz
)->symt
;
249 cv_basic_types
[T_PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], ptrsz
)->symt
;
250 cv_basic_types
[T_PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], ptrsz
)->symt
;
251 cv_basic_types
[T_PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], ptrsz
)->symt
;
252 cv_basic_types
[T_PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], ptrsz
)->symt
;
253 cv_basic_types
[T_PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], ptrsz
)->symt
;
254 cv_basic_types
[T_PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], ptrsz
)->symt
;
255 cv_basic_types
[T_PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], ptrsz
)->symt
;
256 cv_basic_types
[T_PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], ptrsz
)->symt
;
257 cv_basic_types
[T_PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], ptrsz
)->symt
;
258 cv_basic_types
[T_PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], ptrsz
)->symt
;
259 cv_basic_types
[T_PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], ptrsz
)->symt
;
260 cv_basic_types
[T_PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], ptrsz
)->symt
;
261 cv_basic_types
[T_PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], ptrsz
)->symt
;
262 cv_basic_types
[T_PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], ptrsz
)->symt
;
263 cv_basic_types
[T_PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], ptrsz
)->symt
;
264 cv_basic_types
[T_PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], ptrsz
)->symt
;
265 cv_basic_types
[T_PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], ptrsz
)->symt
;
266 cv_basic_types
[T_PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], ptrsz
)->symt
;
267 cv_basic_types
[T_PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], ptrsz
)->symt
;
268 cv_basic_types
[T_PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], ptrsz
)->symt
;
271 static int leaf_as_variant(VARIANT
* v
, const unsigned short int* leaf
)
273 unsigned short int type
= *leaf
++;
276 if (type
< LF_NUMERIC
)
288 V_I1(v
) = *(const char*)leaf
;
294 V_I2(v
) = *(const short*)leaf
;
306 V_I4(v
) = *(const int*)leaf
;
312 V_UI4(v
) = *(const unsigned int*)leaf
;
318 V_I8(v
) = *(const long long int*)leaf
;
324 V_UI8(v
) = *(const long long unsigned int*)leaf
;
330 V_R4(v
) = *(const float*)leaf
;
334 FIXME("Unsupported numeric leaf type %04x\n", type
);
336 V_VT(v
) = VT_EMPTY
; /* FIXME */
342 V_R8(v
) = *(const double*)leaf
;
346 FIXME("Unsupported numeric leaf type %04x\n", type
);
348 V_VT(v
) = VT_EMPTY
; /* FIXME */
352 FIXME("Unsupported numeric leaf type %04x\n", type
);
354 V_VT(v
) = VT_EMPTY
; /* FIXME */
358 FIXME("Unsupported numeric leaf type %04x\n", type
);
360 V_VT(v
) = VT_EMPTY
; /* FIXME */
364 FIXME("Unsupported numeric leaf type %04x\n", type
);
366 V_VT(v
) = VT_EMPTY
; /* FIXME */
370 FIXME("Unsupported numeric leaf type %04x\n", type
);
375 FIXME("Unsupported numeric leaf type %04x\n", type
);
377 V_VT(v
) = VT_EMPTY
; /* FIXME */
381 FIXME("Unsupported numeric leaf type %04x\n", type
);
383 V_VT(v
) = VT_EMPTY
; /* FIXME */
387 FIXME("Unknown numeric leaf type %04x\n", type
);
388 V_VT(v
) = VT_EMPTY
; /* FIXME */
396 static int numeric_leaf(int* value
, const unsigned short int* leaf
)
398 unsigned short int type
= *leaf
++;
401 if (type
< LF_NUMERIC
)
411 *value
= *(const char*)leaf
;
416 *value
= *(const short*)leaf
;
426 *value
= *(const int*)leaf
;
431 *value
= *(const unsigned int*)leaf
;
436 FIXME("Unsupported numeric leaf type %04x\n", type
);
438 *value
= 0; /* FIXME */
442 FIXME("Unsupported numeric leaf type %04x\n", type
);
444 *value
= 0; /* FIXME */
448 FIXME("Unsupported numeric leaf type %04x\n", type
);
450 *value
= 0; /* FIXME */
454 FIXME("Unsupported numeric leaf type %04x\n", type
);
456 *value
= 0; /* FIXME */
460 FIXME("Unsupported numeric leaf type %04x\n", type
);
462 *value
= 0; /* FIXME */
466 FIXME("Unsupported numeric leaf type %04x\n", type
);
468 *value
= 0; /* FIXME */
472 FIXME("Unsupported numeric leaf type %04x\n", type
);
474 *value
= 0; /* FIXME */
478 FIXME("Unsupported numeric leaf type %04x\n", type
);
480 *value
= 0; /* FIXME */
484 FIXME("Unsupported numeric leaf type %04x\n", type
);
486 *value
= 0; /* FIXME */
490 FIXME("Unsupported numeric leaf type %04x\n", type
);
492 *value
= 0; /* FIXME */
496 FIXME("Unsupported numeric leaf type %04x\n", type
);
498 *value
= 0; /* FIXME */
502 FIXME("Unknown numeric leaf type %04x\n", type
);
511 /* convert a pascal string (as stored in debug information) into
512 * a C string (null terminated).
514 static const char* terminate_string(const struct p_string
* p_name
)
516 static char symname
[256];
518 memcpy(symname
, p_name
->name
, p_name
->namelen
);
519 symname
[p_name
->namelen
] = '\0';
521 return (!*symname
|| strcmp(symname
, "__unnamed") == 0) ? NULL
: symname
;
524 static struct symt
* codeview_get_type(unsigned int typeno
, BOOL quiet
)
526 struct symt
* symt
= NULL
;
529 * Convert Codeview type numbers into something we can grok internally.
530 * Numbers < T_MAXPREDEFINEDTYPE all fixed builtin types.
531 * Numbers from T_FIRSTDEFINABLETYPE and up are all user defined (structs, etc).
533 if (typeno
< T_MAXPREDEFINEDTYPE
)
534 symt
= cv_basic_types
[typeno
];
535 else if (typeno
>= T_FIRSTDEFINABLETYPE
)
537 unsigned mod_index
= typeno
>> 24;
538 unsigned mod_typeno
= typeno
& 0x00FFFFFF;
539 struct cv_defined_module
* mod
;
541 mod
= (mod_index
== 0) ? cv_current_module
: &cv_zmodules
[mod_index
];
543 if (mod_index
>= CV_MAX_MODULES
|| !mod
->allowed
)
544 FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index
, typeno
);
547 if (mod_typeno
>= mod
->first_type_index
&& mod_typeno
< mod
->last_type_index
)
548 symt
= mod
->defined_types
[mod_typeno
- mod
->first_type_index
];
551 if (!quiet
&& !symt
&& typeno
) FIXME("Returning NULL symt for type-id %x\n", typeno
);
558 struct hash_link
* next
;
561 struct codeview_type_parse
563 struct module
* module
;
566 const DWORD
* offset
; /* typeindex => offset in 'table' */
567 BYTE
* hash_stream
; /* content of stream header.hash_file */
568 struct hash_link
** hash
; /* hash_table (deserialized from PDB hash table) */
569 struct hash_link
* alloc_hash
; /* allocated hash_link (id => hash_link) */
572 static inline const void* codeview_jump_to_type(const struct codeview_type_parse
* ctp
, DWORD idx
)
574 return (idx
>= ctp
->header
.first_index
&& idx
< ctp
->header
.last_index
) ?
575 ctp
->table
+ ctp
->offset
[idx
- ctp
->header
.first_index
] : NULL
;
578 static int codeview_add_type(unsigned int typeno
, struct symt
* dt
)
581 if (!cv_current_module
)
583 FIXME("Adding %x to non allowed module\n", typeno
);
586 if ((typeno
>> 24) != 0)
587 FIXME("No module index while inserting type-id assumption is wrong %x\n",
589 if (typeno
< cv_current_module
->first_type_index
|| typeno
>= cv_current_module
->last_type_index
)
591 FIXME("Type number %x out of bounds [%x, %x)\n",
592 typeno
, cv_current_module
->first_type_index
, typeno
>= cv_current_module
->last_type_index
);
595 idx
= typeno
- cv_current_module
->first_type_index
;
596 if (cv_current_module
->defined_types
[idx
])
598 if (cv_current_module
->defined_types
[idx
] != dt
)
599 FIXME("Overwriting at %x\n", typeno
);
601 cv_current_module
->defined_types
[idx
] = dt
;
605 static void codeview_clear_type_table(void)
609 for (i
= 0; i
< CV_MAX_MODULES
; i
++)
611 if (cv_zmodules
[i
].allowed
)
612 free(cv_zmodules
[i
].defined_types
);
613 cv_zmodules
[i
].allowed
= FALSE
;
614 cv_zmodules
[i
].defined_types
= NULL
;
615 cv_zmodules
[i
].first_type_index
= 0;
616 cv_zmodules
[i
].last_type_index
= 0;
618 cv_current_module
= NULL
;
621 static struct symt
* codeview_parse_one_type(struct codeview_type_parse
* ctp
,
623 const union codeview_type
* type
);
625 static struct symt
* codeview_fetch_type(struct codeview_type_parse
* ctp
,
629 const union codeview_type
* p
;
631 if (!typeno
) return NULL
;
632 if ((symt
= codeview_get_type(typeno
, TRUE
))) return symt
;
634 if ((p
= codeview_jump_to_type(ctp
, typeno
)))
635 symt
= codeview_parse_one_type(ctp
, typeno
, p
);
636 if (!symt
) FIXME("Couldn't load type %x\n", typeno
);
640 static UINT32
codeview_compute_hash(const char* ptr
, unsigned len
)
642 const char* last
= ptr
+ len
;
645 while (ptr
+ sizeof(UINT32
) <= last
)
647 ret
^= *(UINT32
*)ptr
;
648 ptr
+= sizeof(UINT32
);
650 if (ptr
+ sizeof(UINT16
) <= last
)
652 ret
^= *(UINT16
*)ptr
;
653 ptr
+= sizeof(UINT16
);
655 if (ptr
+ sizeof(BYTE
) <= last
)
659 return ret
^ (ret
>> 16);
662 /* We call 'forwardable' a type which can have a forward declaration, and we need to merge
663 * (when they both exist) the type record of the forward declaration and the type record
664 * of the full definition into a single symt.
666 static BOOL
codeview_is_forwardable_type(const union codeview_type
* type
)
668 switch (type
->generic
.id
)
676 case LF_STRUCTURE_V1
:
677 case LF_STRUCTURE_V2
:
678 case LF_STRUCTURE_V3
:
688 static BOOL
codeview_type_is_forward(const union codeview_type
* cvtype
)
690 cv_property_t property
;
692 switch (cvtype
->generic
.id
)
694 case LF_STRUCTURE_V1
:
695 case LF_CLASS_V1
: property
= cvtype
->struct_v1
.property
; break;
696 case LF_STRUCTURE_V2
:
697 case LF_CLASS_V2
: property
= cvtype
->struct_v2
.property
; break;
698 case LF_STRUCTURE_V3
:
699 case LF_CLASS_V3
: property
= cvtype
->struct_v3
.property
; break;
700 case LF_UNION_V1
: property
= cvtype
->union_v1
.property
; break;
701 case LF_UNION_V2
: property
= cvtype
->union_v2
.property
; break;
702 case LF_UNION_V3
: property
= cvtype
->union_v3
.property
; break;
703 case LF_ENUM_V1
: property
= cvtype
->enumeration_v1
.property
; break;
704 case LF_ENUM_V2
: property
= cvtype
->enumeration_v2
.property
; break;
705 case LF_ENUM_V3
: property
= cvtype
->enumeration_v3
.property
; break;
709 return property
.is_forward_defn
;
712 static BOOL
codeview_type_extract_name(const union codeview_type
* cvtype
,
713 const char** name
, unsigned* len
, const char** decorated_name
)
716 const struct p_string
* p_name
= NULL
;
717 const char* c_name
= NULL
;
718 BOOL decorated
= FALSE
;
720 switch (cvtype
->generic
.id
)
722 case LF_STRUCTURE_V1
:
724 leaf_len
= numeric_leaf(&value
, &cvtype
->struct_v1
.structlen
);
725 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->struct_v1
.structlen
+ leaf_len
);
727 case LF_STRUCTURE_V2
:
729 leaf_len
= numeric_leaf(&value
, &cvtype
->struct_v2
.structlen
);
730 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->struct_v2
.structlen
+ leaf_len
);
732 case LF_STRUCTURE_V3
:
734 leaf_len
= numeric_leaf(&value
, &cvtype
->struct_v3
.structlen
);
735 c_name
= (const char*)&cvtype
->struct_v3
.structlen
+ leaf_len
;
736 decorated
= cvtype
->struct_v3
.property
.has_decorated_name
;
739 leaf_len
= numeric_leaf(&value
, &cvtype
->union_v1
.un_len
);
740 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->union_v1
.un_len
+ leaf_len
);
743 leaf_len
= numeric_leaf(&value
, &cvtype
->union_v2
.un_len
);
744 p_name
= (const struct p_string
*)((const unsigned char*)&cvtype
->union_v2
.un_len
+ leaf_len
);
747 leaf_len
= numeric_leaf(&value
, &cvtype
->union_v3
.un_len
);
748 c_name
= (const char*)&cvtype
->union_v3
.un_len
+ leaf_len
;
749 decorated
= cvtype
->union_v3
.property
.has_decorated_name
;
752 p_name
= &cvtype
->enumeration_v1
.p_name
;
755 p_name
= &cvtype
->enumeration_v2
.p_name
;
758 c_name
= cvtype
->enumeration_v3
.name
;
759 decorated
= cvtype
->union_v3
.property
.has_decorated_name
;
766 *name
= p_name
->name
;
767 *len
= p_name
->namelen
;
768 *decorated_name
= NULL
;
774 *len
= strlen(c_name
);
775 *decorated_name
= decorated
? (c_name
+ *len
+ 1) : NULL
;
781 static unsigned pdb_read_hash_value(const struct codeview_type_parse
* ctp
, unsigned idx
)
783 const void* where
= ctp
->hash_stream
+ ctp
->header
.hash_offset
+ (idx
- ctp
->header
.first_index
) * ctp
->header
.hash_value_size
;
784 switch (ctp
->header
.hash_value_size
)
786 case 2: return *(unsigned short*)where
;
787 case 4: return *(unsigned*)where
;
792 static BOOL
codeview_resolve_forward_type(struct codeview_type_parse
* ctp
, const union codeview_type
* cvref
,
793 unsigned reftype
, unsigned *impl_type
)
795 const union codeview_type
* cvdecl
;
796 struct hash_link
* hl
;
798 const char* decoratedref
;
802 /* Unfortunately, hash of forward defs are computed on the whole type record, not its name
803 * (unlike hash of UDT & enum implementations which is based primarily on the name... sigh)
804 * So compute the hash of the expected implementation.
806 if (!codeview_type_extract_name(cvref
, &nameref
, &lenref
, &decoratedref
)) return FALSE
;
807 hash
= codeview_compute_hash(nameref
, lenref
) % ctp
->header
.hash_num_buckets
;
809 for (hl
= ctp
->hash
[hash
]; hl
; hl
= hl
->next
)
811 if (hl
->id
== reftype
) continue;
812 cvdecl
= codeview_jump_to_type(ctp
, hl
->id
);
813 if (cvdecl
&& !codeview_type_is_forward(cvdecl
) && cvref
->generic
.id
== cvdecl
->generic
.id
)
815 const char* namedecl
;
816 const char* decorateddecl
;
819 if (codeview_type_extract_name(cvdecl
, &namedecl
, &lendecl
, &decorateddecl
) &&
820 ((decoratedref
&& decorateddecl
&& !strcmp(decoratedref
, decorateddecl
)) ||
821 (!decoratedref
&& !decorateddecl
&& lenref
== lendecl
&& !memcmp(nameref
, namedecl
, lenref
))))
823 TRACE("mapping forward type %.*s (%s) %x into %x\n", lenref
, nameref
, debugstr_a(decoratedref
), reftype
, hl
->id
);
832 static struct symt
* codeview_add_type_pointer(struct codeview_type_parse
* ctp
,
833 unsigned int pointee_type
)
835 struct symt
* pointee
;
837 pointee
= codeview_fetch_type(ctp
, pointee_type
);
838 if (!pointee
) return NULL
;
839 return &symt_new_pointer(ctp
->module
, pointee
, ctp
->module
->cpu
->word_size
)->symt
;
842 static struct symt
* codeview_add_type_array(struct codeview_type_parse
* ctp
,
844 unsigned int elemtype
,
845 unsigned int indextype
,
846 unsigned int arr_len
)
848 struct symt
* elem
= codeview_fetch_type(ctp
, elemtype
);
849 struct symt
* index
= codeview_fetch_type(ctp
, indextype
);
853 if (symt_get_info(ctp
->module
, elem
, TI_GET_LENGTH
, &elem_size
) && elem_size
)
855 if (arr_len
% (DWORD
)elem_size
)
856 FIXME("array size should be a multiple of element size %u %I64u\n", arr_len
, elem_size
);
857 count
= arr_len
/ (unsigned)elem_size
;
859 return &symt_new_array(ctp
->module
, 0, count
, elem
, index
)->symt
;
862 static BOOL
codeview_add_type_enum_field_list(struct codeview_type_parse
* ctp
,
863 struct symt_enum
* symt
,
866 const union codeview_reftype
* ref_type
;
867 const unsigned char* ptr
;
868 const unsigned char* last
;
869 const union codeview_fieldtype
* type
;
871 if (!typeno
) return TRUE
;
872 if (!(ref_type
= codeview_jump_to_type(ctp
, typeno
))) return FALSE
;
873 ptr
= ref_type
->fieldlist
.list
;
874 last
= (const BYTE
*)ref_type
+ ref_type
->generic
.len
+ 2;
878 if (*ptr
>= 0xf0) /* LF_PAD... */
884 type
= (const union codeview_fieldtype
*)ptr
;
886 switch (type
->generic
.id
)
888 case LF_ENUMERATE_V1
:
890 int value
, vlen
= numeric_leaf(&value
, &type
->enumerate_v1
.value
);
891 const struct p_string
* p_name
= (const struct p_string
*)((const unsigned char*)&type
->enumerate_v1
.value
+ vlen
);
893 symt_add_enum_element(ctp
->module
, symt
, terminate_string(p_name
), value
);
894 ptr
+= 2 + 2 + vlen
+ (1 + p_name
->namelen
);
897 case LF_ENUMERATE_V3
:
899 int value
, vlen
= numeric_leaf(&value
, &type
->enumerate_v3
.value
);
900 const char* name
= (const char*)&type
->enumerate_v3
.value
+ vlen
;
902 symt_add_enum_element(ctp
->module
, symt
, name
, value
);
903 ptr
+= 2 + 2 + vlen
+ (1 + strlen(name
));
908 if (!codeview_add_type_enum_field_list(ctp
, symt
, type
->index_v1
.ref
))
914 if (!codeview_add_type_enum_field_list(ctp
, symt
, type
->index_v2
.ref
))
920 FIXME("Unsupported type %04x in ENUM field list\n", type
->generic
.id
);
927 static void codeview_add_udt_element(struct codeview_type_parse
* ctp
,
928 struct symt_udt
* symt
, const char* name
,
929 int value
, unsigned type
)
931 struct symt
* subtype
;
932 const union codeview_reftype
*cv_type
;
934 if ((cv_type
= codeview_jump_to_type(ctp
, type
)))
936 switch (cv_type
->generic
.id
)
939 symt_add_udt_element(ctp
->module
, symt
, name
,
940 codeview_fetch_type(ctp
, cv_type
->bitfield_v1
.type
),
941 value
, cv_type
->bitfield_v1
.bitoff
,
942 cv_type
->bitfield_v1
.nbits
);
945 symt_add_udt_element(ctp
->module
, symt
, name
,
946 codeview_fetch_type(ctp
, cv_type
->bitfield_v2
.type
),
947 value
, cv_type
->bitfield_v2
.bitoff
,
948 cv_type
->bitfield_v2
.nbits
);
952 subtype
= codeview_fetch_type(ctp
, type
);
956 DWORD64 elem_size
= 0;
957 symt_get_info(ctp
->module
, subtype
, TI_GET_LENGTH
, &elem_size
);
958 symt_add_udt_element(ctp
->module
, symt
, name
, subtype
, value
, 0, 0);
962 static int codeview_add_type_struct_field_list(struct codeview_type_parse
* ctp
,
963 struct symt_udt
* symt
,
964 unsigned fieldlistno
)
966 const unsigned char* ptr
;
967 const unsigned char* last
;
969 const struct p_string
* p_name
;
971 const union codeview_reftype
*type_ref
;
972 const union codeview_fieldtype
* type
;
974 if (!fieldlistno
) return TRUE
;
975 type_ref
= codeview_jump_to_type(ctp
, fieldlistno
);
976 ptr
= type_ref
->fieldlist
.list
;
977 last
= (const BYTE
*)type_ref
+ type_ref
->generic
.len
+ 2;
981 if (*ptr
>= 0xf0) /* LF_PAD... */
987 type
= (const union codeview_fieldtype
*)ptr
;
989 switch (type
->generic
.id
)
992 leaf_len
= numeric_leaf(&value
, &type
->bclass_v1
.offset
);
994 /* FIXME: ignored for now */
996 ptr
+= 2 + 2 + 2 + leaf_len
;
1000 leaf_len
= numeric_leaf(&value
, &type
->bclass_v2
.offset
);
1002 /* FIXME: ignored for now */
1004 ptr
+= 2 + 2 + 4 + leaf_len
;
1008 case LF_IVBCLASS_V1
:
1010 const unsigned short int* p_vboff
;
1012 leaf_len
= numeric_leaf(&value
, &type
->vbclass_v1
.vbpoff
);
1013 p_vboff
= (const unsigned short int*)((const char*)&type
->vbclass_v1
.vbpoff
+ leaf_len
);
1014 vplen
= numeric_leaf(&vpoff
, p_vboff
);
1016 /* FIXME: ignored for now */
1018 ptr
+= 2 + 2 + 2 + 2 + leaf_len
+ vplen
;
1023 case LF_IVBCLASS_V2
:
1025 const unsigned short int* p_vboff
;
1027 leaf_len
= numeric_leaf(&value
, &type
->vbclass_v2
.vbpoff
);
1028 p_vboff
= (const unsigned short int*)((const char*)&type
->vbclass_v2
.vbpoff
+ leaf_len
);
1029 vplen
= numeric_leaf(&vpoff
, p_vboff
);
1031 /* FIXME: ignored for now */
1033 ptr
+= 2 + 2 + 4 + 4 + leaf_len
+ vplen
;
1038 leaf_len
= numeric_leaf(&value
, &type
->member_v1
.offset
);
1039 p_name
= (const struct p_string
*)((const char*)&type
->member_v1
.offset
+ leaf_len
);
1041 codeview_add_udt_element(ctp
, symt
, terminate_string(p_name
), value
,
1042 type
->member_v1
.type
);
1044 ptr
+= 2 + 2 + 2 + leaf_len
+ (1 + p_name
->namelen
);
1048 leaf_len
= numeric_leaf(&value
, &type
->member_v2
.offset
);
1049 p_name
= (const struct p_string
*)((const unsigned char*)&type
->member_v2
.offset
+ leaf_len
);
1051 codeview_add_udt_element(ctp
, symt
, terminate_string(p_name
), value
,
1052 type
->member_v2
.type
);
1054 ptr
+= 2 + 2 + 4 + leaf_len
+ (1 + p_name
->namelen
);
1058 leaf_len
= numeric_leaf(&value
, &type
->member_v3
.offset
);
1059 c_name
= (const char*)&type
->member_v3
.offset
+ leaf_len
;
1061 codeview_add_udt_element(ctp
, symt
, c_name
, value
, type
->member_v3
.type
);
1063 ptr
+= 2 + 2 + 4 + leaf_len
+ (strlen(c_name
) + 1);
1066 case LF_STMEMBER_V1
:
1067 /* FIXME: ignored for now */
1068 ptr
+= 2 + 2 + 2 + (1 + type
->stmember_v1
.p_name
.namelen
);
1071 case LF_STMEMBER_V2
:
1072 /* FIXME: ignored for now */
1073 ptr
+= 2 + 4 + 2 + (1 + type
->stmember_v2
.p_name
.namelen
);
1076 case LF_STMEMBER_V3
:
1077 /* FIXME: ignored for now */
1078 ptr
+= 2 + 4 + 2 + (strlen(type
->stmember_v3
.name
) + 1);
1082 /* FIXME: ignored for now */
1083 ptr
+= 2 + 2 + 2 + (1 + type
->method_v1
.p_name
.namelen
);
1087 /* FIXME: ignored for now */
1088 ptr
+= 2 + 2 + 4 + (1 + type
->method_v2
.p_name
.namelen
);
1092 /* FIXME: ignored for now */
1093 ptr
+= 2 + 2 + 4 + (strlen(type
->method_v3
.name
) + 1);
1096 case LF_NESTTYPE_V1
:
1097 /* FIXME: ignored for now */
1098 ptr
+= 2 + 2 + (1 + type
->nesttype_v1
.p_name
.namelen
);
1101 case LF_NESTTYPE_V2
:
1102 /* FIXME: ignored for now */
1103 ptr
+= 2 + 2 + 4 + (1 + type
->nesttype_v2
.p_name
.namelen
);
1106 case LF_NESTTYPE_V3
:
1107 /* FIXME: ignored for now */
1108 ptr
+= 2 + 2 + 4 + (strlen(type
->nesttype_v3
.name
) + 1);
1111 case LF_VFUNCTAB_V1
:
1112 /* FIXME: ignored for now */
1116 case LF_VFUNCTAB_V2
:
1117 /* FIXME: ignored for now */
1121 case LF_ONEMETHOD_V1
:
1122 /* FIXME: ignored for now */
1123 switch ((type
->onemethod_v1
.attribute
>> 2) & 7)
1125 case 4: case 6: /* (pure) introducing virtual method */
1126 ptr
+= 2 + 2 + 2 + 4 + (1 + type
->onemethod_virt_v1
.p_name
.namelen
);
1130 ptr
+= 2 + 2 + 2 + (1 + type
->onemethod_v1
.p_name
.namelen
);
1135 case LF_ONEMETHOD_V2
:
1136 /* FIXME: ignored for now */
1137 switch ((type
->onemethod_v2
.attribute
>> 2) & 7)
1139 case 4: case 6: /* (pure) introducing virtual method */
1140 ptr
+= 2 + 2 + 4 + 4 + (1 + type
->onemethod_virt_v2
.p_name
.namelen
);
1144 ptr
+= 2 + 2 + 4 + (1 + type
->onemethod_v2
.p_name
.namelen
);
1149 case LF_ONEMETHOD_V3
:
1150 /* FIXME: ignored for now */
1151 switch ((type
->onemethod_v3
.attribute
>> 2) & 7)
1153 case 4: case 6: /* (pure) introducing virtual method */
1154 ptr
+= 2 + 2 + 4 + 4 + (strlen(type
->onemethod_virt_v3
.name
) + 1);
1158 ptr
+= 2 + 2 + 4 + (strlen(type
->onemethod_v3
.name
) + 1);
1164 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v1
.ref
))
1170 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v2
.ref
))
1176 FIXME("Unsupported type %04x in STRUCT field list\n", type
->generic
.id
);
1184 static struct symt
* codeview_new_func_signature(struct codeview_type_parse
* ctp
,
1185 enum CV_call_e call_conv
)
1187 struct symt_function_signature
* sym
;
1189 sym
= symt_new_function_signature(ctp
->module
, NULL
, call_conv
);
1193 static void codeview_add_func_signature_args(struct codeview_type_parse
* ctp
,
1194 struct symt_function_signature
* sym
,
1198 const union codeview_reftype
* reftype
;
1200 sym
->rettype
= codeview_fetch_type(ctp
, ret_type
);
1201 if (args_list
&& (reftype
= codeview_jump_to_type(ctp
, args_list
)))
1204 switch (reftype
->generic
.id
)
1207 for (i
= 0; i
< reftype
->arglist_v1
.num
; i
++)
1208 symt_add_function_signature_parameter(ctp
->module
, sym
,
1209 codeview_fetch_type(ctp
, reftype
->arglist_v1
.args
[i
]));
1212 for (i
= 0; i
< reftype
->arglist_v2
.num
; i
++)
1213 symt_add_function_signature_parameter(ctp
->module
, sym
,
1214 codeview_fetch_type(ctp
, reftype
->arglist_v2
.args
[i
]));
1217 FIXME("Unexpected leaf %x for signature's pmt\n", reftype
->generic
.id
);
1222 static struct symt
* codeview_parse_one_type(struct codeview_type_parse
* ctp
,
1224 const union codeview_type
* type
)
1226 struct symt
* symt
= NULL
;
1227 int value
, leaf_len
;
1228 const struct p_string
* p_name
;
1231 switch (type
->generic
.id
)
1233 case LF_MODIFIER_V1
:
1234 /* FIXME: we don't handle modifiers,
1235 * but read previous type on the curr_type
1237 WARN("Modifier on %x: %s%s%s%s\n",
1238 type
->modifier_v1
.type
,
1239 type
->modifier_v1
.attribute
& 0x01 ? "const " : "",
1240 type
->modifier_v1
.attribute
& 0x02 ? "volatile " : "",
1241 type
->modifier_v1
.attribute
& 0x04 ? "unaligned " : "",
1242 type
->modifier_v1
.attribute
& ~0x07 ? "unknown " : "");
1243 symt
= codeview_fetch_type(ctp
, type
->modifier_v1
.type
);
1245 case LF_MODIFIER_V2
:
1246 /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
1247 WARN("Modifier on %x: %s%s%s%s\n",
1248 type
->modifier_v2
.type
,
1249 type
->modifier_v2
.attribute
& 0x01 ? "const " : "",
1250 type
->modifier_v2
.attribute
& 0x02 ? "volatile " : "",
1251 type
->modifier_v2
.attribute
& 0x04 ? "unaligned " : "",
1252 type
->modifier_v2
.attribute
& ~0x07 ? "unknown " : "");
1253 symt
= codeview_fetch_type(ctp
, type
->modifier_v2
.type
);
1257 symt
= codeview_add_type_pointer(ctp
, type
->pointer_v1
.datatype
);
1260 symt
= codeview_add_type_pointer(ctp
, type
->pointer_v2
.datatype
);
1264 leaf_len
= numeric_leaf(&value
, &type
->array_v1
.arrlen
);
1265 p_name
= (const struct p_string
*)((const unsigned char*)&type
->array_v1
.arrlen
+ leaf_len
);
1266 symt
= codeview_add_type_array(ctp
, terminate_string(p_name
),
1267 type
->array_v1
.elemtype
,
1268 type
->array_v1
.idxtype
, value
);
1271 leaf_len
= numeric_leaf(&value
, &type
->array_v2
.arrlen
);
1272 p_name
= (const struct p_string
*)((const unsigned char*)&type
->array_v2
.arrlen
+ leaf_len
);
1274 symt
= codeview_add_type_array(ctp
, terminate_string(p_name
),
1275 type
->array_v2
.elemtype
,
1276 type
->array_v2
.idxtype
, value
);
1279 leaf_len
= numeric_leaf(&value
, &type
->array_v3
.arrlen
);
1280 c_name
= (const char*)&type
->array_v3
.arrlen
+ leaf_len
;
1282 symt
= codeview_add_type_array(ctp
, c_name
,
1283 type
->array_v3
.elemtype
,
1284 type
->array_v3
.idxtype
, value
);
1287 case LF_STRUCTURE_V1
:
1289 if (!type
->struct_v1
.property
.is_forward_defn
)
1290 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1291 type
->struct_v1
.fieldlist
);
1294 case LF_STRUCTURE_V2
:
1296 if (!type
->struct_v2
.property
.is_forward_defn
)
1297 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1298 type
->struct_v2
.fieldlist
);
1301 case LF_STRUCTURE_V3
:
1303 if (!type
->struct_v3
.property
.is_forward_defn
)
1304 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1305 type
->struct_v3
.fieldlist
);
1309 if (!type
->union_v1
.property
.is_forward_defn
)
1310 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1311 type
->union_v1
.fieldlist
);
1315 if (!type
->union_v2
.property
.is_forward_defn
)
1316 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1317 type
->union_v2
.fieldlist
);
1321 if (!type
->union_v3
.property
.is_forward_defn
)
1322 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)codeview_get_type(curr_type
, TRUE
),
1323 type
->union_v3
.fieldlist
);
1328 struct symt_enum
* senum
= (struct symt_enum
*)codeview_get_type(curr_type
, TRUE
);
1329 senum
->base_type
= codeview_fetch_type(ctp
, type
->enumeration_v1
.type
);
1330 codeview_add_type_enum_field_list(ctp
, senum
, type
->enumeration_v1
.fieldlist
);
1336 struct symt_enum
* senum
= (struct symt_enum
*)codeview_get_type(curr_type
, TRUE
);
1337 senum
->base_type
= codeview_fetch_type(ctp
, type
->enumeration_v2
.type
);
1338 codeview_add_type_enum_field_list(ctp
, senum
, type
->enumeration_v2
.fieldlist
);
1344 struct symt_enum
* senum
= (struct symt_enum
*)codeview_get_type(curr_type
, TRUE
);
1345 senum
->base_type
= codeview_fetch_type(ctp
, type
->enumeration_v3
.type
);
1346 codeview_add_type_enum_field_list(ctp
, senum
, type
->enumeration_v3
.fieldlist
);
1350 case LF_PROCEDURE_V1
:
1351 symt
= codeview_new_func_signature(ctp
, type
->procedure_v1
.callconv
);
1352 codeview_add_func_signature_args(ctp
,
1353 (struct symt_function_signature
*)symt
,
1354 type
->procedure_v1
.rvtype
,
1355 type
->procedure_v1
.arglist
);
1357 case LF_PROCEDURE_V2
:
1358 symt
= codeview_new_func_signature(ctp
,type
->procedure_v2
.callconv
);
1359 codeview_add_func_signature_args(ctp
,
1360 (struct symt_function_signature
*)symt
,
1361 type
->procedure_v2
.rvtype
,
1362 type
->procedure_v2
.arglist
);
1365 case LF_MFUNCTION_V1
:
1366 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1367 * nor class information, this would just do for now
1369 symt
= codeview_new_func_signature(ctp
, type
->mfunction_v1
.callconv
);
1370 codeview_add_func_signature_args(ctp
,
1371 (struct symt_function_signature
*)symt
,
1372 type
->mfunction_v1
.rvtype
,
1373 type
->mfunction_v1
.arglist
);
1375 case LF_MFUNCTION_V2
:
1376 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1377 * nor class information, this would just do for now
1379 symt
= codeview_new_func_signature(ctp
, type
->mfunction_v2
.callconv
);
1380 codeview_add_func_signature_args(ctp
,
1381 (struct symt_function_signature
*)symt
,
1382 type
->mfunction_v2
.rvtype
,
1383 type
->mfunction_v2
.arglist
);
1387 /* this is an ugly hack... FIXME when we have C++ support */
1390 snprintf(buf
, sizeof(buf
), "__internal_vt_shape_%x\n", curr_type
);
1391 symt
= &symt_new_udt(ctp
->module
, buf
, 0, UdtStruct
)->symt
;
1395 FIXME("Unsupported type-id leaf %x\n", type
->generic
.id
);
1396 dump(type
, 2 + type
->generic
.len
);
1399 return symt
&& codeview_add_type(curr_type
, symt
) ? symt
: NULL
;
1402 static struct symt
* codeview_load_forwardable_type(struct codeview_type_parse
* ctp
,
1403 const union codeview_type
* type
)
1406 int value
, leaf_len
;
1407 const struct p_string
* p_name
;
1410 switch (type
->generic
.id
)
1412 case LF_STRUCTURE_V1
:
1414 leaf_len
= numeric_leaf(&value
, &type
->struct_v1
.structlen
);
1415 p_name
= (const struct p_string
*)((const unsigned char*)&type
->struct_v1
.structlen
+ leaf_len
);
1416 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
,
1417 type
->generic
.id
== LF_CLASS_V1
? UdtClass
: UdtStruct
)->symt
;
1420 case LF_STRUCTURE_V2
:
1422 leaf_len
= numeric_leaf(&value
, &type
->struct_v2
.structlen
);
1423 p_name
= (const struct p_string
*)((const unsigned char*)&type
->struct_v2
.structlen
+ leaf_len
);
1424 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
,
1425 type
->generic
.id
== LF_CLASS_V2
? UdtClass
: UdtStruct
)->symt
;
1428 case LF_STRUCTURE_V3
:
1430 leaf_len
= numeric_leaf(&value
, &type
->struct_v3
.structlen
);
1431 c_name
= (const char*)&type
->struct_v3
.structlen
+ leaf_len
;
1432 symt
= &symt_new_udt(ctp
->module
, c_name
, value
,
1433 type
->generic
.id
== LF_CLASS_V3
? UdtClass
: UdtStruct
)->symt
;
1437 leaf_len
= numeric_leaf(&value
, &type
->union_v1
.un_len
);
1438 p_name
= (const struct p_string
*)((const unsigned char*)&type
->union_v1
.un_len
+ leaf_len
);
1439 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
, UdtUnion
)->symt
;
1443 leaf_len
= numeric_leaf(&value
, &type
->union_v2
.un_len
);
1444 p_name
= (const struct p_string
*)((const unsigned char*)&type
->union_v2
.un_len
+ leaf_len
);
1445 symt
= &symt_new_udt(ctp
->module
, terminate_string(p_name
), value
, UdtUnion
)->symt
;
1449 leaf_len
= numeric_leaf(&value
, &type
->union_v3
.un_len
);
1450 c_name
= (const char*)&type
->union_v3
.un_len
+ leaf_len
;
1451 symt
= &symt_new_udt(ctp
->module
, c_name
, value
, UdtUnion
)->symt
;
1455 symt
= &symt_new_enum(ctp
->module
, terminate_string(&type
->enumeration_v1
.p_name
), NULL
)->symt
;
1459 symt
= &symt_new_enum(ctp
->module
, terminate_string(&type
->enumeration_v2
.p_name
), NULL
)->symt
;
1463 symt
= &symt_new_enum(ctp
->module
, type
->enumeration_v3
.name
, NULL
)->symt
;
1466 default: symt
= NULL
;
1471 static inline BOOL
codeview_is_top_level_type(const union codeview_type
* type
)
1473 /* type records we're interested in are the ones referenced by symbols
1474 * The known ranges are (X mark the ones we want):
1475 * X 0000-0016 for V1 types
1476 * 0200-020c for V1 types referenced by other types
1477 * 0400-040f for V1 types (complex lists & sets)
1478 * X 1000-100f for V2 types
1479 * 1200-120c for V2 types referenced by other types
1480 * 1400-140f for V1 types (complex lists & sets)
1481 * X 1500-150d for V3 types
1482 * 8000-8010 for numeric leafes
1484 return !(type
->generic
.id
& 0x8600) || (type
->generic
.id
& 0x0100);
1487 static BOOL
codeview_parse_type_table(struct codeview_type_parse
* ctp
)
1489 unsigned int i
, curr_type
;
1490 const union codeview_type
* type
;
1492 cv_current_module
->first_type_index
= ctp
->header
.first_index
;
1493 cv_current_module
->last_type_index
= ctp
->header
.last_index
;
1494 cv_current_module
->defined_types
= calloc(ctp
->header
.last_index
- ctp
->header
.first_index
,
1495 sizeof(*cv_current_module
->defined_types
));
1497 /* pass I: + load implementation of forwardable types, but without their content
1498 * + merge forward declarations with their implementations (when the later exists)
1499 * + do it in the order generated from PDB hash table to preserve that order
1500 * (several versions coming from different compilations can exist in the PDB file,
1501 * and using PDB order ensures that we use the relevant one.
1502 * (needed for forward resolution and type lookup by name)
1503 * (dbghelp hash table inserts new elements at the end of bucket's list)
1504 * Note: for a given type, we must handle:
1505 * - only an implementation type record
1506 * - only a forward type record (eg using struct foo* without struct foo being defined)
1507 * - a forward type record and on an implementation type record: this is the most common, but
1508 * depending on hash values, we cannot tell which on will show up first
1510 for (i
= 0; i
< ctp
->header
.hash_num_buckets
; i
++)
1512 struct hash_link
* hl
;
1513 for (hl
= ctp
->hash
[i
]; hl
; hl
= hl
->next
)
1516 type
= codeview_jump_to_type(ctp
, hl
->id
);
1517 if (!codeview_is_top_level_type(type
)) continue;
1518 if (codeview_type_is_forward(type
))
1521 /* make the forward declaration point to the implementation (if any) */
1522 if (codeview_resolve_forward_type(ctp
, type
, hl
->id
, &impl_type
))
1524 /* impl already loaded? */
1525 if (!(symt
= codeview_get_type(impl_type
, TRUE
)))
1528 if ((symt
= codeview_load_forwardable_type(ctp
, codeview_jump_to_type(ctp
, impl_type
))))
1529 codeview_add_type(impl_type
, symt
);
1531 FIXME("forward def of %x => %x, unable to load impl\n", hl
->id
, impl_type
);
1535 /* forward type definition without implementation, create empty type */
1536 symt
= codeview_load_forwardable_type(ctp
, type
);
1540 /* if not already loaded (from previous forward declaration), load it */
1541 if (!(symt
= codeview_get_type(hl
->id
, TRUE
)))
1542 symt
= codeview_load_forwardable_type(ctp
, type
);
1544 codeview_add_type(hl
->id
, symt
);
1547 /* pass II: + non forwardable types: load them, but since they can be indirectly
1548 * loaded (from another type), but don't load them twice
1549 * + forwardable types: load their content
1551 for (curr_type
= ctp
->header
.first_index
; curr_type
< ctp
->header
.last_index
; curr_type
++)
1553 type
= codeview_jump_to_type(ctp
, curr_type
);
1554 if (codeview_is_top_level_type(type
) &&
1555 (!codeview_get_type(curr_type
, TRUE
) || codeview_is_forwardable_type(type
)))
1556 codeview_parse_one_type(ctp
, curr_type
, type
);
1562 /*========================================================================
1563 * Process CodeView line number information.
1565 static ULONG_PTR
codeview_get_address(const struct msc_debug_info
* msc_dbg
,
1566 unsigned seg
, unsigned offset
);
1568 static void codeview_snarf_linetab(const struct msc_debug_info
* msc_dbg
, const BYTE
* linetab
,
1569 int size
, BOOL pascal_str
)
1571 const BYTE
* ptr
= linetab
;
1575 const unsigned int* filetab
;
1576 const unsigned int* lt_ptr
;
1577 const unsigned short* linenos
;
1578 const struct startend
* start
;
1580 ULONG_PTR addr
, func_addr0
;
1581 struct symt_function
* func
;
1582 const struct codeview_linetab_block
* ltb
;
1584 nfile
= *(const short*)linetab
;
1585 filetab
= (const unsigned int*)(linetab
+ 2 * sizeof(short));
1587 for (i
= 0; i
< nfile
; i
++)
1589 ptr
= linetab
+ filetab
[i
];
1590 nseg
= *(const short*)ptr
;
1591 lt_ptr
= (const unsigned int*)(ptr
+ 2 * sizeof(short));
1592 start
= (const struct startend
*)(lt_ptr
+ nseg
);
1595 * Now snarf the filename for all of the segments for this file.
1598 source
= source_new(msc_dbg
->module
, NULL
, terminate_string((const struct p_string
*)(start
+ nseg
)));
1600 source
= source_new(msc_dbg
->module
, NULL
, (const char*)(start
+ nseg
));
1602 for (j
= 0; j
< nseg
; j
++)
1604 ltb
= (const struct codeview_linetab_block
*)(linetab
+ *lt_ptr
++);
1605 linenos
= (const unsigned short*)<b
->offsets
[ltb
->num_lines
];
1606 func_addr0
= codeview_get_address(msc_dbg
, ltb
->seg
, start
[j
].start
);
1607 if (!func_addr0
) continue;
1608 for (func
= NULL
, k
= 0; k
< ltb
->num_lines
; k
++)
1610 /* now locate function (if any) */
1611 addr
= func_addr0
+ ltb
->offsets
[k
] - start
[j
].start
;
1612 /* unfortunately, we can have several functions in the same block, if there's no
1613 * gap between them... find the new function if needed
1615 if (!func
|| addr
>= func
->ranges
[0].high
)
1617 func
= (struct symt_function
*)symt_find_symbol_at(msc_dbg
->module
, addr
);
1618 /* FIXME: at least labels support line numbers */
1619 if (!symt_check_tag(&func
->symt
, SymTagFunction
) && !symt_check_tag(&func
->symt
, SymTagInlineSite
))
1621 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1622 ltb
->seg
, ltb
->offsets
[k
], addr
, func
? func
->symt
.tag
: -1);
1627 symt_add_func_line(msc_dbg
->module
, func
, source
, linenos
[k
], addr
);
1633 static const char* pdb_get_string_table_entry(const PDB_STRING_TABLE
* table
, unsigned offset
);
1635 static void codeview_snarf_linetab2(const struct msc_debug_info
* msc_dbg
, const struct cv_module_snarf
* cvmod
)
1638 const void* hdr_last
= (const char*)cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
;
1639 const struct CV_DebugSSubsectionHeader_t
* hdr
;
1640 const struct CV_DebugSSubsectionHeader_t
* hdr_next
;
1641 const struct CV_DebugSSubsectionHeader_t
* hdr_files
= NULL
;
1642 const struct CV_DebugSLinesHeader_t
* lines_hdr
;
1643 const struct CV_DebugSLinesFileBlockHeader_t
* files_hdr
;
1644 const struct CV_Line_t
* lines
;
1645 const struct CV_Checksum_t
* chksms
;
1647 struct symt_function
* func
;
1649 /* locate DEBUG_S_FILECHKSMS (if any) */
1650 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, hdr_last
); hdr
= CV_RECORD_GAP(hdr
, hdr
->cbLen
))
1652 if (hdr
->type
== DEBUG_S_FILECHKSMS
)
1660 TRACE("No DEBUG_S_FILECHKSMS found\n");
1664 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, hdr_last
); hdr
= hdr_next
)
1666 hdr_next
= CV_RECORD_GAP(hdr
, hdr
->cbLen
);
1667 if (!(hdr
->type
& DEBUG_S_IGNORE
))
1669 ULONG_PTR lineblk_base
;
1670 /* FIXME: should also check that whole lines_blk fits in linetab + size */
1674 lines_hdr
= CV_RECORD_AFTER(hdr
);
1675 files_hdr
= CV_RECORD_AFTER(lines_hdr
);
1676 /* Skip blocks that are too small - Intel C Compiler generates these. */
1677 if (!CV_IS_INSIDE(files_hdr
, hdr_next
)) break;
1678 TRACE("block from %04x:%08x #%x\n",
1679 lines_hdr
->segCon
, lines_hdr
->offCon
, lines_hdr
->cbCon
);
1680 chksms
= CV_RECORD_GAP(hdr_files
, files_hdr
->offFile
);
1681 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
)))
1683 WARN("Corrupt PDB file: offset in CHKSMS subsection is invalid\n");
1686 source
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
1687 lineblk_base
= codeview_get_address(msc_dbg
, lines_hdr
->segCon
, lines_hdr
->offCon
);
1688 lines
= CV_RECORD_AFTER(files_hdr
);
1689 for (i
= 0; i
< files_hdr
->nLines
; i
++)
1691 func
= (struct symt_function
*)symt_find_symbol_at(msc_dbg
->module
, lineblk_base
+ lines
[i
].offset
);
1692 /* FIXME: at least labels support line numbers */
1693 if (!symt_check_tag(&func
->symt
, SymTagFunction
) && !symt_check_tag(&func
->symt
, SymTagInlineSite
))
1695 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1696 lines_hdr
->segCon
, lines_hdr
->offCon
+ lines
[i
].offset
, lineblk_base
+ lines
[i
].offset
, func
? func
->symt
.tag
: -1);
1699 symt_add_func_line(msc_dbg
->module
, func
, source
,
1700 lines
[i
].linenumStart
, lineblk_base
+ lines
[i
].offset
);
1703 case DEBUG_S_FILECHKSMS
: /* skip */
1713 /*========================================================================
1714 * Process CodeView symbol information.
1717 static unsigned int codeview_map_offset(const struct msc_debug_info
* msc_dbg
,
1718 unsigned int offset
)
1720 int nomap
= msc_dbg
->nomap
;
1721 const OMAP
* omapp
= msc_dbg
->omapp
;
1724 if (!nomap
|| !omapp
) return offset
;
1726 /* FIXME: use binary search */
1727 for (i
= 0; i
< nomap
- 1; i
++)
1728 if (omapp
[i
].rva
<= offset
&& omapp
[i
+1].rva
> offset
)
1729 return !omapp
[i
].rvaTo
? 0 : omapp
[i
].rvaTo
+ (offset
- omapp
[i
].rva
);
1734 static ULONG_PTR
codeview_get_address(const struct msc_debug_info
* msc_dbg
,
1735 unsigned seg
, unsigned offset
)
1737 int nsect
= msc_dbg
->nsect
;
1738 const IMAGE_SECTION_HEADER
* sectp
= msc_dbg
->sectp
;
1740 if (!seg
|| seg
> nsect
) return 0;
1741 return msc_dbg
->module
->module
.BaseOfImage
+
1742 codeview_map_offset(msc_dbg
, sectp
[seg
-1].VirtualAddress
+ offset
);
1745 static BOOL
func_has_local(struct symt_function
* func
, const char* name
)
1749 for (i
= 0; i
< func
->vchildren
.num_elts
; ++i
)
1751 struct symt
* p
= *(struct symt
**)vector_at(&func
->vchildren
, i
);
1752 if (symt_check_tag(p
, SymTagData
) && !strcmp(((struct symt_data
*)p
)->hash_elt
.name
, name
))
1758 static const union codeview_symbol
* get_next_sym(const union codeview_symbol
* sym
)
1760 return (const union codeview_symbol
*)((const char*)sym
+ sym
->generic
.len
+ 2);
1763 static inline void codeview_add_variable(const struct msc_debug_info
* msc_dbg
,
1764 struct symt_compiland
* compiland
,
1765 struct symt_function
* func
,
1766 struct symt_block
* block
,
1768 unsigned segment
, unsigned offset
,
1769 unsigned symtype
, BOOL is_local
, BOOL in_tls
, BOOL dontcheck
)
1773 struct location loc
;
1775 loc
.kind
= in_tls
? loc_tlsrel
: loc_absolute
;
1777 loc
.offset
= in_tls
? offset
: codeview_get_address(msc_dbg
, segment
, offset
);
1780 if (!is_local
|| in_tls
) WARN("Unsupported construct\n");
1781 symt_add_func_local(msc_dbg
->module
, func
, DataIsStaticLocal
, &loc
, block
,
1782 codeview_get_type(symtype
, FALSE
), name
);
1785 if (!dontcheck
&& !in_tls
)
1787 /* Check that we don't add twice the same variable */
1788 struct hash_table_iter hti
;
1790 struct symt_ht
* sym
;
1792 hash_table_iter_init(&msc_dbg
->module
->ht_symbols
, &hti
, name
);
1793 while ((ptr
= hash_table_iter_up(&hti
)))
1795 sym
= CONTAINING_RECORD(ptr
, struct symt_ht
, hash_elt
);
1796 if (symt_check_tag(&sym
->symt
, SymTagData
) && !strcmp(sym
->hash_elt
.name
, name
))
1798 struct symt_data
* symdata
= (struct symt_data
*)&sym
->symt
;
1799 if (symdata
->kind
== (is_local
? DataIsFileStatic
: DataIsGlobal
) &&
1800 symdata
->u
.var
.kind
== loc
.kind
&&
1801 symdata
->u
.var
.offset
== loc
.offset
&&
1802 symdata
->container
== &compiland
->symt
)
1804 /* We don't compare types yet... Unfortunately, they are not
1805 * always the same typeid... it'd require full type equivalence
1806 * (eg: we've seen 'int* foo' <> 'int[4] foo')
1813 if (is_local
^ (compiland
!= NULL
)) FIXME("Unsupported construct\n");
1814 symt_new_global_variable(msc_dbg
->module
, compiland
, name
, is_local
, loc
, 0,
1815 codeview_get_type(symtype
, FALSE
));
1819 struct cv_local_info
1821 unsigned short kind
; /* the S_DEFRANGE* */
1822 unsigned short ngaps
; /* number of gaps */
1824 unsigned short rangelen
; /* after start */
1827 struct cv_addr_gap gaps
[0];
1830 static const struct cv_addr_gap
* codeview_get_gaps(const union codeview_symbol
* symrange
)
1832 const struct cv_addr_gap
* gap
;
1833 switch (symrange
->generic
.id
)
1835 case S_DEFRANGE
: gap
= symrange
->defrange_v3
.gaps
; break;
1836 case S_DEFRANGE_SUBFIELD
: gap
= symrange
->defrange_subfield_v3
.gaps
; break;
1837 case S_DEFRANGE_REGISTER
: gap
= symrange
->defrange_register_v3
.gaps
; break;
1838 case S_DEFRANGE_FRAMEPOINTER_REL
: gap
= symrange
->defrange_frameptrrel_v3
.gaps
; break;
1839 case S_DEFRANGE_SUBFIELD_REGISTER
: gap
= symrange
->defrange_subfield_register_v3
.gaps
; break;
1840 case S_DEFRANGE_REGISTER_REL
: gap
= symrange
->defrange_registerrel_v3
.gaps
; break;
1841 /* no gaps for that one */
1842 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
1843 default: return NULL
;
1845 return gap
!= (const struct cv_addr_gap
*)get_next_sym(symrange
) ? gap
: NULL
;
1848 static void codeview_xform_range(const struct msc_debug_info
* msc_dbg
,
1849 struct cv_local_info
* locinfo
,
1850 const struct cv_addr_range
* adrange
)
1852 locinfo
->start
= codeview_get_address(msc_dbg
, adrange
->isectStart
, adrange
->offStart
);
1853 locinfo
->rangelen
= adrange
->cbRange
;
1856 static unsigned codeview_defrange_length(const union codeview_symbol
* sym
)
1858 const union codeview_symbol
* first_symrange
= get_next_sym(sym
);
1859 const union codeview_symbol
* symrange
;
1861 for (symrange
= first_symrange
;
1862 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1863 symrange
= get_next_sym(symrange
)) {}
1864 return (const char*)symrange
- (const char*)first_symrange
;
1867 static unsigned codeview_transform_defrange(const struct msc_debug_info
* msc_dbg
,
1868 struct symt_function
* curr_func
,
1869 const union codeview_symbol
* sym
,
1870 struct location
* loc
)
1872 const union codeview_symbol
* first_symrange
= get_next_sym(sym
);
1873 const union codeview_symbol
* symrange
;
1874 const struct cv_addr_gap
* gap
;
1875 unsigned len
, alloc
= sizeof(DWORD
); /* for terminating kind = 0 */
1878 /* we need to transform the cv_addr_range into cv_local_info */
1879 for (symrange
= first_symrange
;
1880 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1881 symrange
= get_next_sym(symrange
))
1883 gap
= codeview_get_gaps(symrange
);
1884 alloc
+= sizeof(struct cv_local_info
) +
1885 (gap
? (const char*)get_next_sym(symrange
) - (const char*)gap
: 0);
1887 /* total length of all S_DEFRANGE* records (in bytes) following S_LOCAL */
1888 len
= (const char*)symrange
- (const char*)first_symrange
;
1890 ptr
= pool_alloc(&msc_dbg
->module
->pool
, alloc
);
1893 struct cv_local_info
* locinfo
= (struct cv_local_info
*)ptr
;
1895 loc
->kind
= loc_cv_local_range
;
1896 loc
->offset
= (DWORD_PTR
)ptr
;
1897 /* transform the cv_addr_range into cv_local_info */
1898 for (symrange
= first_symrange
;
1899 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1900 symrange
= get_next_sym(symrange
))
1902 locinfo
->kind
= symrange
->generic
.id
;
1903 switch (symrange
->generic
.id
)
1906 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_v3
.range
);
1907 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1909 case S_DEFRANGE_SUBFIELD
:
1910 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_subfield_v3
.range
);
1911 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1913 case S_DEFRANGE_REGISTER
:
1914 locinfo
->reg
= symrange
->defrange_register_v3
.reg
;
1915 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_register_v3
.range
);
1917 case S_DEFRANGE_FRAMEPOINTER_REL
:
1918 locinfo
->offset
= symrange
->defrange_frameptrrel_v3
.offFramePointer
;
1919 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_frameptrrel_v3
.range
);
1921 case S_DEFRANGE_SUBFIELD_REGISTER
:
1922 locinfo
->reg
= symrange
->defrange_subfield_register_v3
.reg
;
1923 locinfo
->offset
= symrange
->defrange_subfield_register_v3
.offParent
;
1924 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_subfield_register_v3
.range
);
1926 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
1927 locinfo
->offset
= symrange
->defrange_frameptr_relfullscope_v3
.offFramePointer
;
1928 locinfo
->start
= curr_func
->ranges
[0].low
;
1929 locinfo
->rangelen
= addr_range_size(&curr_func
->ranges
[0]);
1931 case S_DEFRANGE_REGISTER_REL
:
1932 locinfo
->reg
= symrange
->defrange_registerrel_v3
.baseReg
;
1933 locinfo
->offset
= symrange
->defrange_registerrel_v3
.offBasePointer
;
1934 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_registerrel_v3
.range
);
1939 gap
= codeview_get_gaps(symrange
);
1942 unsigned gaplen
= (const char*)get_next_sym(symrange
) - (const char*)gap
;
1943 locinfo
->ngaps
= gaplen
/ sizeof(*gap
);
1944 memcpy(locinfo
->gaps
, gap
, gaplen
);
1945 locinfo
= (struct cv_local_info
*)((char*)(locinfo
+ 1) + gaplen
);
1953 *(DWORD
*)locinfo
= 0; /* store terminating kind == 0 */
1957 loc
->kind
= loc_error
;
1958 loc
->reg
= loc_err_internal
;
1963 static unsigned codeview_binannot_uncompress(const unsigned char** pptr
)
1965 unsigned res
= (unsigned)(-1);
1966 const unsigned char* ptr
= *pptr
;
1968 if ((*ptr
& 0x80) == 0x00)
1969 res
= (unsigned)(*ptr
++);
1970 else if ((*ptr
& 0xC0) == 0x80)
1972 res
= (unsigned)((*ptr
++ & 0x3f) << 8);
1975 else if ((*ptr
& 0xE0) == 0xC0)
1977 res
= (*ptr
++ & 0x1f) << 24;
1978 res
|= *ptr
++ << 16;
1982 else res
= (unsigned)(-1);
1989 const unsigned char* annot
; /* current pointer */
1990 const unsigned char* last_annot
; /* end of binary annotation stream (first byte after) */
1991 unsigned opcode
; /* last decoded opcode */
1992 unsigned arg1
, arg2
;
1995 static BOOL
codeview_advance_binannot(struct cv_binannot
* cvba
)
1997 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
1998 cvba
->opcode
= codeview_binannot_uncompress(&cvba
->annot
);
1999 if (cvba
->opcode
<= BA_OP_Invalid
|| cvba
->opcode
> BA_OP_ChangeColumnEnd
) return FALSE
;
2000 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
2001 cvba
->arg1
= codeview_binannot_uncompress(&cvba
->annot
);
2002 if (cvba
->opcode
== BA_OP_ChangeCodeOffsetAndLineOffset
)
2004 cvba
->arg2
= cvba
->arg1
>> 4;
2007 else if (cvba
->opcode
== BA_OP_ChangeCodeLengthAndCodeOffset
)
2009 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
2010 cvba
->arg2
= codeview_binannot_uncompress(&cvba
->annot
);
2012 else cvba
->arg2
= 0;
2016 static inline int binannot_getsigned(unsigned i
)
2018 return (i
& 1) ? -(int)(i
>> 1) : (int)(i
>> 1);
2021 static BOOL
cv_dbgsubsect_find_inlinee(const struct msc_debug_info
* msc_dbg
,
2023 const struct cv_module_snarf
* cvmod
,
2024 const struct CV_DebugSSubsectionHeader_t
* hdr_files
,
2025 unsigned* srcfile
, unsigned* srcline
)
2027 const struct CV_DebugSSubsectionHeader_t
* hdr
;
2028 const struct CV_DebugSSubsectionHeader_t
* next_hdr
;
2029 const struct CV_InlineeSourceLine_t
* inlsrc
;
2030 const struct CV_InlineeSourceLineEx_t
* inlsrcex
;
2031 const struct CV_Checksum_t
* chksms
;
2033 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
); hdr
= next_hdr
)
2035 next_hdr
= CV_RECORD_GAP(hdr
, hdr
->cbLen
);
2036 if (hdr
->type
!= DEBUG_S_INLINEELINES
) continue;
2037 /* subsection starts with a DWORD signature */
2038 switch (*(DWORD
*)CV_RECORD_AFTER(hdr
))
2040 case CV_INLINEE_SOURCE_LINE_SIGNATURE
:
2041 inlsrc
= CV_RECORD_GAP(hdr
, sizeof(DWORD
));
2042 while (CV_IS_INSIDE(inlsrc
, next_hdr
))
2044 if (inlsrc
->inlinee
== inlineeid
)
2046 chksms
= CV_RECORD_GAP(hdr_files
, inlsrc
->fileId
);
2047 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))) return FALSE
;
2048 *srcfile
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
2049 *srcline
= inlsrc
->sourceLineNum
;
2055 case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
:
2056 inlsrcex
= CV_RECORD_GAP(hdr
, sizeof(DWORD
));
2057 while (CV_IS_INSIDE(inlsrcex
, next_hdr
))
2059 if (inlsrcex
->inlinee
== inlineeid
)
2061 chksms
= CV_RECORD_GAP(hdr_files
, inlsrcex
->fileId
);
2062 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))) return FALSE
;
2063 *srcfile
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
2064 *srcline
= inlsrcex
->sourceLineNum
;
2067 inlsrcex
= CV_RECORD_GAP(inlsrcex
, inlsrcex
->countOfExtraFiles
* sizeof(inlsrcex
->extraFileId
[0]));
2071 FIXME("Unknown signature %lx in INLINEELINES subsection\n", *(DWORD
*)CV_RECORD_AFTER(hdr
));
2078 static inline void inline_site_update_last_range(struct symt_function
* inlined
, unsigned index
, ULONG_PTR hi
)
2080 if (index
&& index
<= inlined
->num_ranges
)
2082 struct addr_range
* range
= &inlined
->ranges
[index
- 1];
2083 /* only change range if it has no span (code start without code end) */
2084 if (range
->low
== range
->high
)
2089 static unsigned inline_site_get_num_ranges(const unsigned char* annot
,
2090 const unsigned char* last_annot
)
2092 struct cv_binannot cvba
;
2093 unsigned num_ranges
= 0;
2096 cvba
.last_annot
= last_annot
;
2098 while (codeview_advance_binannot(&cvba
))
2100 switch (cvba
.opcode
)
2102 case BA_OP_CodeOffset
:
2103 case BA_OP_ChangeCodeLength
:
2104 case BA_OP_ChangeFile
:
2105 case BA_OP_ChangeLineOffset
:
2107 case BA_OP_ChangeCodeOffset
:
2108 case BA_OP_ChangeCodeOffsetAndLineOffset
:
2109 case BA_OP_ChangeCodeLengthAndCodeOffset
:
2113 WARN("Unsupported op %d\n", cvba
.opcode
);
2120 static struct symt_function
* codeview_create_inline_site(const struct msc_debug_info
* msc_dbg
,
2121 const struct cv_module_snarf
* cvmod
,
2122 struct symt_function
* top_func
,
2123 struct symt
* container
,
2124 cv_itemid_t inlinee
,
2125 const unsigned char* annot
,
2126 const unsigned char* last_annot
)
2128 const struct CV_DebugSSubsectionHeader_t
* hdr_files
= NULL
;
2129 const union codeview_type
* cvt
;
2130 struct symt_function
* inlined
;
2131 struct cv_binannot cvba
;
2133 unsigned num_ranges
;
2134 unsigned offset
, index
, line
, srcfile
;
2135 const struct CV_Checksum_t
* chksms
;
2137 if (!cvmod
->ipi_ctp
|| !(cvt
= codeview_jump_to_type(cvmod
->ipi_ctp
, inlinee
)))
2139 FIXME("Couldn't find type %x in IPI stream\n", inlinee
);
2142 num_ranges
= inline_site_get_num_ranges(annot
, last_annot
);
2143 if (!num_ranges
) return NULL
;
2145 switch (cvt
->generic
.id
)
2148 inlined
= symt_new_inlinesite(msc_dbg
->module
, top_func
, container
,
2149 cvt
->func_id_v3
.name
,
2150 codeview_get_type(cvt
->func_id_v3
.type
, FALSE
),
2154 /* FIXME we just declare a function, not a method */
2155 inlined
= symt_new_inlinesite(msc_dbg
->module
, top_func
, container
,
2156 cvt
->mfunc_id_v3
.name
,
2157 codeview_get_type(cvt
->mfunc_id_v3
.type
, FALSE
),
2161 FIXME("unsupported inlinee kind %x\n", cvt
->generic
.id
);
2165 for (hdr_files
= cvmod
->dbgsubsect
;
2166 CV_IS_INSIDE(hdr_files
, cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
);
2167 hdr_files
= CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))
2169 if (hdr_files
->type
== DEBUG_S_FILECHKSMS
)
2172 if (!hdr_files
) return FALSE
;
2173 srcok
= cv_dbgsubsect_find_inlinee(msc_dbg
, inlinee
, cvmod
, hdr_files
, &srcfile
, &line
);
2178 /* rescan all annotations and store ranges & line information */
2182 cvba
.last_annot
= last_annot
;
2184 while (codeview_advance_binannot(&cvba
))
2186 switch (cvba
.opcode
)
2188 case BA_OP_CodeOffset
:
2191 case BA_OP_ChangeCodeOffset
:
2192 offset
+= cvba
.arg1
;
2193 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2195 symt_add_func_line(msc_dbg
->module
, inlined
, srcfile
, line
, top_func
->ranges
[0].low
+ offset
);
2196 inlined
->ranges
[index
].low
= top_func
->ranges
[0].low
+ offset
;
2197 inlined
->ranges
[index
++].high
= top_func
->ranges
[0].low
+ offset
;
2199 case BA_OP_ChangeCodeLength
:
2200 /* this op isn't widely used by MSVC, but clang uses it a lot... */
2201 offset
+= cvba
.arg1
;
2202 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2204 case BA_OP_ChangeFile
:
2205 chksms
= CV_RECORD_GAP(hdr_files
, cvba
.arg1
);
2206 if (CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
)))
2207 srcfile
= source_new(msc_dbg
->module
, NULL
, pdb_get_string_table_entry(cvmod
->strimage
, chksms
->strOffset
));
2209 case BA_OP_ChangeLineOffset
:
2210 line
+= binannot_getsigned(cvba
.arg1
);
2212 case BA_OP_ChangeCodeOffsetAndLineOffset
:
2213 line
+= binannot_getsigned(cvba
.arg2
);
2214 offset
+= cvba
.arg1
;
2215 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2217 symt_add_func_line(msc_dbg
->module
, inlined
, srcfile
, line
, top_func
->ranges
[0].low
+ offset
);
2218 inlined
->ranges
[index
].low
= top_func
->ranges
[0].low
+ offset
;
2219 inlined
->ranges
[index
++].high
= top_func
->ranges
[0].low
+ offset
;
2221 case BA_OP_ChangeCodeLengthAndCodeOffset
:
2222 offset
+= cvba
.arg2
;
2223 inline_site_update_last_range(inlined
, index
, top_func
->ranges
[0].low
+ offset
);
2225 symt_add_func_line(msc_dbg
->module
, inlined
, srcfile
, line
, top_func
->ranges
[0].low
+ offset
);
2226 inlined
->ranges
[index
].low
= top_func
->ranges
[0].low
+ offset
;
2227 inlined
->ranges
[index
++].high
= top_func
->ranges
[0].low
+ offset
+ cvba
.arg1
;
2230 WARN("Unsupported op %d\n", cvba
.opcode
);
2234 if (index
!= num_ranges
) /* sanity check */
2235 FIXME("Internal logic error\n");
2236 if (inlined
->num_ranges
)
2238 struct addr_range
* range
= &inlined
->ranges
[inlined
->num_ranges
- 1];
2239 if (range
->low
== range
->high
) WARN("pending empty range at end of %s inside %s\n",
2240 inlined
->hash_elt
.name
,
2241 top_func
->hash_elt
.name
);
2246 static struct symt_compiland
* codeview_new_compiland(const struct msc_debug_info
* msc_dbg
, const char* objname
)
2248 unsigned int src_idx
= source_new(msc_dbg
->module
, NULL
, objname
);
2251 /* In some cases MSVC generates several compiland entries with same pathname in PDB file.
2252 * (for example: for an import library, one compiland entry per imported function is generated).
2253 * But native dbghelp (in this case) merges in a single compiland instance.
2255 for (i
= 0; i
< msc_dbg
->module
->top
->vchildren
.num_elts
; i
++)
2257 struct symt_compiland
** p
= vector_at(&msc_dbg
->module
->top
->vchildren
, i
);
2258 if (symt_check_tag(&(*p
)->symt
, SymTagCompiland
) && (*p
)->source
== src_idx
)
2261 return symt_new_compiland(msc_dbg
->module
, src_idx
);
2264 static BOOL
codeview_snarf(const struct msc_debug_info
* msc_dbg
,
2265 const BYTE
* root
, unsigned offset
, unsigned size
,
2266 const struct cv_module_snarf
* cvmod
,
2267 const char* objname
)
2269 struct symt_function
* top_func
= NULL
;
2270 struct symt_function
* curr_func
= NULL
;
2272 struct symt_block
* block
= NULL
;
2274 struct symt_compiland
* compiland
= NULL
;
2275 struct location loc
;
2277 /* overwrite compiland name from outer context (if any) */
2279 compiland
= codeview_new_compiland(msc_dbg
, objname
);
2281 * Loop over the different types of records and whenever we
2282 * find something we are interested in, record it and move on.
2284 for (i
= offset
; i
< size
; i
+= length
)
2286 const union codeview_symbol
* sym
= (const union codeview_symbol
*)(root
+ i
);
2287 length
= sym
->generic
.len
+ 2;
2288 if (i
+ length
> size
) break;
2289 if (!sym
->generic
.id
|| length
< 4) break;
2290 if (length
& 3) FIXME("unpadded len %u\n", length
);
2292 switch (sym
->generic
.id
)
2295 * Global and local data symbols. We don't associate these
2296 * with any given source file.
2300 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->data_v1
.p_name
),
2301 sym
->data_v1
.segment
, sym
->data_v1
.offset
, sym
->data_v1
.symtype
,
2302 sym
->generic
.id
== S_LDATA32_16t
, FALSE
, TRUE
);
2306 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->data_v2
.p_name
),
2307 sym
->data_v2
.segment
, sym
->data_v2
.offset
, sym
->data_v2
.symtype
,
2308 sym
->generic
.id
== S_LDATA32_ST
, FALSE
, TRUE
);
2312 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, sym
->data_v3
.name
,
2313 sym
->data_v3
.segment
, sym
->data_v3
.offset
, sym
->data_v3
.symtype
,
2314 sym
->generic
.id
== S_LDATA32
, FALSE
, TRUE
);
2317 /* variables with thread storage */
2318 case S_GTHREAD32_16t
:
2319 case S_LTHREAD32_16t
:
2320 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->thread_v1
.p_name
),
2321 sym
->thread_v1
.segment
, sym
->thread_v1
.offset
, sym
->thread_v1
.symtype
,
2322 sym
->generic
.id
== S_LTHREAD32_16t
, TRUE
, TRUE
);
2324 case S_GTHREAD32_ST
:
2325 case S_LTHREAD32_ST
:
2326 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, terminate_string(&sym
->thread_v2
.p_name
),
2327 sym
->thread_v2
.segment
, sym
->thread_v2
.offset
, sym
->thread_v2
.symtype
,
2328 sym
->generic
.id
== S_LTHREAD32_ST
, TRUE
, TRUE
);
2332 codeview_add_variable(msc_dbg
, compiland
, curr_func
, block
, sym
->thread_v3
.name
,
2333 sym
->thread_v3
.segment
, sym
->thread_v3
.offset
, sym
->thread_v3
.symtype
,
2334 sym
->generic
.id
== S_LTHREAD32
, TRUE
, TRUE
);
2337 /* Public symbols */
2343 /* will be handled later on in codeview_snarf_public */
2347 * Sort of like a global function, but it just points
2348 * to a thunk, which is a stupid name for what amounts to
2349 * a PLT slot in the normal jargon that everyone else uses.
2352 symt_new_thunk(msc_dbg
->module
, compiland
,
2353 terminate_string(&sym
->thunk_v1
.p_name
), sym
->thunk_v1
.thtype
,
2354 codeview_get_address(msc_dbg
, sym
->thunk_v1
.segment
, sym
->thunk_v1
.offset
),
2355 sym
->thunk_v1
.thunk_len
);
2358 symt_new_thunk(msc_dbg
->module
, compiland
,
2359 sym
->thunk_v3
.name
, sym
->thunk_v3
.thtype
,
2360 codeview_get_address(msc_dbg
, sym
->thunk_v3
.segment
, sym
->thunk_v3
.offset
),
2361 sym
->thunk_v3
.thunk_len
);
2365 * Global and static functions.
2369 if (top_func
) FIXME("nested function\n");
2370 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2371 terminate_string(&sym
->proc_v1
.p_name
),
2372 codeview_get_address(msc_dbg
, sym
->proc_v1
.segment
, sym
->proc_v1
.offset
),
2373 sym
->proc_v1
.proc_len
,
2374 codeview_get_type(sym
->proc_v1
.proctype
, FALSE
));
2375 curr_func
= top_func
;
2376 loc
.kind
= loc_absolute
;
2377 loc
.offset
= sym
->proc_v1
.debug_start
;
2378 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2379 loc
.offset
= sym
->proc_v1
.debug_end
;
2380 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2384 if (top_func
) FIXME("nested function\n");
2385 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2386 terminate_string(&sym
->proc_v2
.p_name
),
2387 codeview_get_address(msc_dbg
, sym
->proc_v2
.segment
, sym
->proc_v2
.offset
),
2388 sym
->proc_v2
.proc_len
,
2389 codeview_get_type(sym
->proc_v2
.proctype
, FALSE
));
2390 curr_func
= top_func
;
2391 loc
.kind
= loc_absolute
;
2392 loc
.offset
= sym
->proc_v2
.debug_start
;
2393 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2394 loc
.offset
= sym
->proc_v2
.debug_end
;
2395 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2399 if (top_func
) FIXME("nested function\n");
2400 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2402 codeview_get_address(msc_dbg
, sym
->proc_v3
.segment
, sym
->proc_v3
.offset
),
2403 sym
->proc_v3
.proc_len
,
2404 codeview_get_type(sym
->proc_v3
.proctype
, FALSE
));
2405 curr_func
= top_func
;
2406 loc
.kind
= loc_absolute
;
2407 loc
.offset
= sym
->proc_v3
.debug_start
;
2408 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2409 loc
.offset
= sym
->proc_v3
.debug_end
;
2410 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2413 * Function parameters and stack variables.
2416 loc
.kind
= loc_regrel
;
2417 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2418 loc
.reg
= CV_REG_EBP
;
2419 loc
.offset
= sym
->stack_v1
.offset
;
2420 symt_add_func_local(msc_dbg
->module
, curr_func
,
2421 sym
->stack_v1
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2423 codeview_get_type(sym
->stack_v1
.symtype
, FALSE
),
2424 terminate_string(&sym
->stack_v1
.p_name
));
2427 loc
.kind
= loc_regrel
;
2428 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2429 loc
.reg
= CV_REG_EBP
;
2430 loc
.offset
= sym
->stack_v2
.offset
;
2431 symt_add_func_local(msc_dbg
->module
, curr_func
,
2432 sym
->stack_v2
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2434 codeview_get_type(sym
->stack_v2
.symtype
, FALSE
),
2435 terminate_string(&sym
->stack_v2
.p_name
));
2438 /* S_BPREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2439 if (func_has_local(curr_func
, sym
->stack_v3
.name
)) break;
2440 loc
.kind
= loc_regrel
;
2441 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2442 loc
.reg
= CV_REG_EBP
;
2443 loc
.offset
= sym
->stack_v3
.offset
;
2444 symt_add_func_local(msc_dbg
->module
, curr_func
,
2445 sym
->stack_v3
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2447 codeview_get_type(sym
->stack_v3
.symtype
, FALSE
),
2448 sym
->stack_v3
.name
);
2451 /* S_REGREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2452 if (func_has_local(curr_func
, sym
->regrel_v3
.name
)) break;
2453 loc
.kind
= loc_regrel
;
2454 loc
.reg
= sym
->regrel_v3
.reg
;
2455 loc
.offset
= sym
->regrel_v3
.offset
;
2456 symt_add_func_local(msc_dbg
->module
, curr_func
,
2457 /* FIXME this is wrong !!! */
2458 sym
->regrel_v3
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2460 codeview_get_type(sym
->regrel_v3
.symtype
, FALSE
),
2461 sym
->regrel_v3
.name
);
2464 case S_REGISTER_16t
:
2465 loc
.kind
= loc_register
;
2466 loc
.reg
= sym
->register_v1
.reg
;
2468 symt_add_func_local(msc_dbg
->module
, curr_func
,
2470 block
, codeview_get_type(sym
->register_v1
.type
, FALSE
),
2471 terminate_string(&sym
->register_v1
.p_name
));
2474 loc
.kind
= loc_register
;
2475 loc
.reg
= sym
->register_v2
.reg
;
2477 symt_add_func_local(msc_dbg
->module
, curr_func
,
2479 block
, codeview_get_type(sym
->register_v2
.type
, FALSE
),
2480 terminate_string(&sym
->register_v2
.p_name
));
2483 /* S_REGISTER can be present after S_LOCAL; prefer S_LOCAL when present */
2484 if (func_has_local(curr_func
, sym
->register_v3
.name
)) break;
2485 loc
.kind
= loc_register
;
2486 loc
.reg
= sym
->register_v3
.reg
;
2488 symt_add_func_local(msc_dbg
->module
, curr_func
,
2490 block
, codeview_get_type(sym
->register_v3
.type
, FALSE
),
2491 sym
->register_v3
.name
);
2495 block
= symt_open_func_block(msc_dbg
->module
, curr_func
, block
, 1);
2496 block
->ranges
[0].low
= codeview_get_address(msc_dbg
, sym
->block_v1
.segment
, sym
->block_v1
.offset
);
2497 block
->ranges
[0].high
= block
->ranges
[0].low
+ sym
->block_v1
.length
;
2500 block
= symt_open_func_block(msc_dbg
->module
, curr_func
, block
, 1);
2501 block
->ranges
[0].low
= codeview_get_address(msc_dbg
, sym
->block_v3
.segment
, sym
->block_v3
.offset
);
2502 block
->ranges
[0].high
= block
->ranges
[0].low
+ sym
->block_v3
.length
;
2508 block
= symt_close_func_block(msc_dbg
->module
, curr_func
, block
);
2512 if (curr_func
!= top_func
) FIXME("shouldn't close a top function with an opened inlined function\n");
2513 top_func
= curr_func
= NULL
;
2518 TRACE("S-Compile-V1 machine:%x language:%x %s\n",
2519 sym
->compile_v1
.machine
, sym
->compile_v1
.flags
.language
, terminate_string(&sym
->compile_v1
.p_name
));
2523 TRACE("S-Compile-V2 machine:%x language:%x %s\n",
2524 sym
->compile2_v2
.machine
, sym
->compile2_v2
.flags
.iLanguage
, terminate_string(&sym
->compile2_v2
.p_name
));
2528 TRACE("S-Compile-V3 machine:%x language:%x %s\n", sym
->compile2_v3
.machine
, sym
->compile2_v3
.flags
.iLanguage
, sym
->compile2_v3
.name
);
2532 TRACE("S-Compile3-V3 machine:%x language:%x %s\n", sym
->compile3_v3
.machine
, sym
->compile3_v3
.flags
.iLanguage
, sym
->compile3_v3
.name
);
2539 TRACE("S-ObjName-V3 %s\n", sym
->objname_v3
.name
);
2541 compiland
= codeview_new_compiland(msc_dbg
, sym
->objname_v3
.name
);
2545 TRACE("S-ObjName-V1 %s\n", terminate_string(&sym
->objname_v1
.p_name
));
2547 compiland
= codeview_new_compiland(msc_dbg
, terminate_string(&sym
->objname_v1
.p_name
));
2553 loc
.kind
= loc_absolute
;
2554 loc
.offset
= codeview_get_address(msc_dbg
, sym
->label_v1
.segment
, sym
->label_v1
.offset
) - curr_func
->ranges
[0].low
;
2555 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagLabel
, &loc
,
2556 terminate_string(&sym
->label_v1
.p_name
));
2558 else symt_new_label(msc_dbg
->module
, compiland
,
2559 terminate_string(&sym
->label_v1
.p_name
),
2560 codeview_get_address(msc_dbg
, sym
->label_v1
.segment
, sym
->label_v1
.offset
));
2565 loc
.kind
= loc_absolute
;
2566 loc
.offset
= codeview_get_address(msc_dbg
, sym
->label_v3
.segment
, sym
->label_v3
.offset
) - curr_func
->ranges
[0].low
;
2567 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagLabel
,
2568 &loc
, sym
->label_v3
.name
);
2570 else symt_new_label(msc_dbg
->module
, compiland
, sym
->label_v3
.name
,
2571 codeview_get_address(msc_dbg
, sym
->label_v3
.segment
, sym
->label_v3
.offset
));
2574 case S_CONSTANT_16t
:
2577 const struct p_string
* name
;
2581 vlen
= leaf_as_variant(&v
, &sym
->constant_v1
.cvalue
);
2582 name
= (const struct p_string
*)((const char*)&sym
->constant_v1
.cvalue
+ vlen
);
2583 se
= codeview_get_type(sym
->constant_v1
.type
, FALSE
);
2585 TRACE("S-Constant-V1 %u %s %x\n", V_INT(&v
), terminate_string(name
), sym
->constant_v1
.type
);
2586 symt_new_constant(msc_dbg
->module
, compiland
, terminate_string(name
),
2593 const struct p_string
* name
;
2597 vlen
= leaf_as_variant(&v
, &sym
->constant_v2
.cvalue
);
2598 name
= (const struct p_string
*)((const char*)&sym
->constant_v2
.cvalue
+ vlen
);
2599 se
= codeview_get_type(sym
->constant_v2
.type
, FALSE
);
2601 TRACE("S-Constant-V2 %u %s %x\n", V_INT(&v
), terminate_string(name
), sym
->constant_v2
.type
);
2602 symt_new_constant(msc_dbg
->module
, compiland
, terminate_string(name
),
2613 vlen
= leaf_as_variant(&v
, &sym
->constant_v3
.cvalue
);
2614 name
= (const char*)&sym
->constant_v3
.cvalue
+ vlen
;
2615 se
= codeview_get_type(sym
->constant_v3
.type
, FALSE
);
2617 TRACE("S-Constant-V3 %u %s %x\n", V_INT(&v
), name
, sym
->constant_v3
.type
);
2618 /* FIXME: we should add this as a constant value */
2619 symt_new_constant(msc_dbg
->module
, compiland
, name
, se
, &v
);
2624 if (sym
->udt_v1
.type
)
2626 if ((symt
= codeview_get_type(sym
->udt_v1
.type
, FALSE
)))
2627 symt_new_typedef(msc_dbg
->module
, symt
,
2628 terminate_string(&sym
->udt_v1
.p_name
));
2630 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2631 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
2635 if (sym
->udt_v2
.type
)
2637 if ((symt
= codeview_get_type(sym
->udt_v2
.type
, FALSE
)))
2638 symt_new_typedef(msc_dbg
->module
, symt
,
2639 terminate_string(&sym
->udt_v2
.p_name
));
2641 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2642 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
2646 if (sym
->udt_v3
.type
)
2648 if ((symt
= codeview_get_type(sym
->udt_v3
.type
, FALSE
)))
2649 symt_new_typedef(msc_dbg
->module
, symt
, sym
->udt_v3
.name
);
2651 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2652 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
2656 /* FIXME: don't store global/static variables accessed through registers... we don't support that
2657 * in locals... anyway, global data record should be present as well (so the variable will be available
2658 * through the global definition, but potentially not updated)
2660 if (!sym
->local_v3
.varflags
.enreg_global
&& !sym
->local_v3
.varflags
.enreg_static
)
2662 length
+= codeview_transform_defrange(msc_dbg
, curr_func
, sym
, &loc
);
2663 symt_add_func_local(msc_dbg
->module
, curr_func
,
2664 sym
->local_v3
.varflags
.is_param
? DataIsParam
: DataIsLocal
,
2666 codeview_get_type(sym
->local_v3
.symtype
, FALSE
),
2667 sym
->local_v3
.name
);
2670 length
+= codeview_defrange_length(sym
);
2674 struct symt_function
* inlined
= codeview_create_inline_site(msc_dbg
, cvmod
, top_func
,
2675 block
? &block
->symt
: &curr_func
->symt
,
2676 sym
->inline_site_v3
.inlinee
,
2677 sym
->inline_site_v3
.binaryAnnotations
,
2678 (const unsigned char*)sym
+ length
);
2681 curr_func
= inlined
;
2686 /* skip all records until paired S_INLINESITE_END */
2687 sym
= (const union codeview_symbol
*)(root
+ sym
->inline_site_v3
.pEnd
);
2688 if (sym
->generic
.id
!= S_INLINESITE_END
) FIXME("complete wreckage\n");
2689 length
= sym
->inline_site_v3
.pEnd
- i
+ sym
->generic
.len
;
2695 struct symt_function
* inlined
= codeview_create_inline_site(msc_dbg
, cvmod
, top_func
,
2696 block
? &block
->symt
: &curr_func
->symt
,
2697 sym
->inline_site2_v3
.inlinee
,
2698 sym
->inline_site2_v3
.binaryAnnotations
,
2699 (const unsigned char*)sym
+ length
);
2702 curr_func
= inlined
;
2707 /* skip all records until paired S_INLINESITE_END */
2708 sym
= (const union codeview_symbol
*)(root
+ sym
->inline_site2_v3
.pEnd
);
2709 if (sym
->generic
.id
!= S_INLINESITE_END
) FIXME("complete wreckage\n");
2710 length
= sym
->inline_site_v3
.pEnd
- i
+ sym
->generic
.len
;
2715 case S_INLINESITE_END
:
2716 block
= symt_check_tag(curr_func
->container
, SymTagBlock
) ?
2717 (struct symt_block
*)curr_func
->container
: NULL
;
2718 curr_func
= (struct symt_function
*)symt_get_upper_inlined(curr_func
);
2722 * These are special, in that they are always followed by an
2723 * additional length-prefixed string which is *not* included
2724 * into the symbol length count. We need to skip it.
2732 name
= (const char*)sym
+ length
;
2733 length
+= (*name
+ 1 + 3) & ~3;
2738 TRACE("Start search: seg=0x%x at offset 0x%08x\n",
2739 sym
->ssearch_v1
.segment
, sym
->ssearch_v1
.offset
);
2743 TRACE("S-Align V1\n");
2745 case S_HEAPALLOCSITE
:
2746 TRACE("S-heap site V3: offset=0x%08x at sect_idx 0x%04x, inst_len 0x%08x, index 0x%08x\n",
2747 sym
->heap_alloc_site_v3
.offset
, sym
->heap_alloc_site_v3
.sect_idx
,
2748 sym
->heap_alloc_site_v3
.inst_len
, sym
->heap_alloc_site_v3
.index
);
2754 ULONG_PTR parent_addr
= codeview_get_address(msc_dbg
, sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2755 struct symt_ht
* parent
= symt_find_symbol_at(msc_dbg
->module
, parent_addr
);
2756 if (symt_check_tag(&parent
->symt
, SymTagFunction
))
2758 struct symt_function
* pfunc
= (struct symt_function
*)parent
;
2759 top_func
= symt_new_function(msc_dbg
->module
, compiland
, pfunc
->hash_elt
.name
,
2760 codeview_get_address(msc_dbg
, sym
->sepcode_v3
.sect
, sym
->sepcode_v3
.off
),
2761 sym
->sepcode_v3
.length
, pfunc
->type
);
2762 curr_func
= top_func
;
2765 WARN("Couldn't find function referenced by S_SEPCODE at %04x:%08x\n",
2766 sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2769 FIXME("S_SEPCODE inside top-level function %s\n", top_func
->hash_elt
.name
);
2772 /* the symbols we can safely ignore for now */
2779 case S_CALLSITEINFO
:
2780 /* even if S_LOCAL groks all the S_DEFRANGE* records following itself,
2781 * those kinds of records can also be present after a S_FILESTATIC record
2782 * so silence them until (at least) S_FILESTATIC is supported
2784 case S_DEFRANGE_REGISTER
:
2785 case S_DEFRANGE_FRAMEPOINTER_REL
:
2786 case S_DEFRANGE_SUBFIELD_REGISTER
:
2787 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
2788 case S_DEFRANGE_REGISTER_REL
:
2796 TRACE("Unsupported symbol id %x\n", sym
->generic
.id
);
2800 FIXME("Unsupported symbol id %x\n", sym
->generic
.id
);
2801 dump(sym
, 2 + sym
->generic
.len
);
2805 if (cvmod
) codeview_snarf_linetab2(msc_dbg
, cvmod
);
2809 static BOOL
codeview_is_inside(const struct cv_local_info
* locinfo
, const struct symt_function
* func
, DWORD_PTR ip
)
2812 /* ip must be in local_info range, but not in any of its gaps */
2813 if (ip
< locinfo
->start
|| ip
>= locinfo
->start
+ locinfo
->rangelen
) return FALSE
;
2814 for (i
= 0; i
< locinfo
->ngaps
; ++i
)
2815 if (func
->ranges
[0].low
+ locinfo
->gaps
[i
].gapStartOffset
<= ip
&&
2816 ip
< func
->ranges
[0].low
+ locinfo
->gaps
[i
].gapStartOffset
+ locinfo
->gaps
[i
].cbRange
)
2821 static void pdb_location_compute(struct process
* pcs
,
2822 const struct module_format
* modfmt
,
2823 const struct symt_function
* func
,
2824 struct location
* loc
)
2826 const struct cv_local_info
* locinfo
;
2830 case loc_cv_local_range
:
2831 for (locinfo
= (const struct cv_local_info
*)loc
->offset
;
2833 locinfo
= (const struct cv_local_info
*)((const char*)(locinfo
+ 1) + locinfo
->ngaps
* sizeof(locinfo
->gaps
[0])))
2835 if (!codeview_is_inside(locinfo
, func
, pcs
->localscope_pc
)) continue;
2836 switch (locinfo
->kind
)
2839 case S_DEFRANGE_SUBFIELD
:
2841 FIXME("Unsupported defrange %d\n", locinfo
->kind
);
2842 loc
->kind
= loc_error
;
2843 loc
->reg
= loc_err_internal
;
2845 case S_DEFRANGE_SUBFIELD_REGISTER
:
2846 FIXME("sub-field part not handled\n");
2848 case S_DEFRANGE_REGISTER
:
2849 loc
->kind
= loc_register
;
2850 loc
->reg
= locinfo
->reg
;
2852 case S_DEFRANGE_REGISTER_REL
:
2853 loc
->kind
= loc_regrel
;
2854 loc
->reg
= locinfo
->reg
;
2855 loc
->offset
= locinfo
->offset
;
2857 case S_DEFRANGE_FRAMEPOINTER_REL
:
2858 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
2859 loc
->kind
= loc_regrel
;
2860 loc
->reg
= modfmt
->module
->cpu
->frame_regno
;
2861 loc
->offset
= locinfo
->offset
;
2868 loc
->kind
= loc_error
;
2869 loc
->reg
= loc_err_internal
;
2872 static void* pdb_read_stream(const struct pdb_file_info
* pdb_file
, DWORD stream_nr
);
2873 static unsigned pdb_get_stream_size(const struct pdb_file_info
* pdb_file
, DWORD stream_nr
);
2875 static BOOL
codeview_snarf_sym_hashtable(const struct msc_debug_info
* msc_dbg
, const BYTE
* symroot
, DWORD symsize
,
2876 const BYTE
* hashroot
, DWORD hashsize
,
2877 BOOL (*feed
)(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
*))
2879 const DBI_HASH_HEADER
* hash_hdr
= (const DBI_HASH_HEADER
*)hashroot
;
2880 unsigned num_hash_records
, i
;
2881 const DBI_HASH_RECORD
* hr
;
2883 if (hashsize
< sizeof(DBI_HASH_HEADER
) ||
2884 hash_hdr
->signature
!= 0xFFFFFFFF ||
2885 hash_hdr
->version
!= 0xeffe0000 + 19990810 ||
2886 (hash_hdr
->hash_records_size
% sizeof(DBI_HASH_RECORD
)) != 0 ||
2887 sizeof(DBI_HASH_HEADER
) + hash_hdr
->hash_records_size
+ DBI_BITMAP_HASH_SIZE
> hashsize
||
2888 (hashsize
- (sizeof(DBI_HASH_HEADER
) + hash_hdr
->hash_records_size
+ DBI_BITMAP_HASH_SIZE
)) % sizeof(unsigned))
2890 FIXME("Incorrect hash structure\n");
2894 hr
= (DBI_HASH_RECORD
*)(hash_hdr
+ 1);
2895 num_hash_records
= hash_hdr
->hash_records_size
/ sizeof(DBI_HASH_RECORD
);
2897 /* Only iterate over the records listed in the hash table.
2898 * We assume that records present in stream, but not listed in hash table, are
2899 * invalid (and thus not loaded).
2901 for (i
= 0; i
< num_hash_records
; i
++)
2903 if (hr
[i
].offset
&& hr
[i
].offset
< symsize
)
2905 const union codeview_symbol
* sym
= (const union codeview_symbol
*)(symroot
+ hr
[i
].offset
- 1);
2906 (*feed
)(msc_dbg
, sym
);
2912 static BOOL
pdb_global_feed_types(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
2915 switch (sym
->generic
.id
)
2918 if (sym
->udt_v1
.type
)
2920 if ((symt
= codeview_get_type(sym
->udt_v1
.type
, FALSE
)))
2921 symt_new_typedef(msc_dbg
->module
, symt
,
2922 terminate_string(&sym
->udt_v1
.p_name
));
2924 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2925 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
2929 if (sym
->udt_v2
.type
)
2931 if ((symt
= codeview_get_type(sym
->udt_v2
.type
, FALSE
)))
2932 symt_new_typedef(msc_dbg
->module
, symt
,
2933 terminate_string(&sym
->udt_v2
.p_name
));
2935 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2936 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
2940 if (sym
->udt_v3
.type
)
2942 if ((symt
= codeview_get_type(sym
->udt_v3
.type
, FALSE
)))
2943 symt_new_typedef(msc_dbg
->module
, symt
, sym
->udt_v3
.name
);
2945 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2946 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
2949 default: return FALSE
;
2954 static BOOL
pdb_global_feed_variables(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
2956 /* The only interest here is to add global variables that haven't been seen
2957 * in module (=compilation unit) stream.
2958 * So we don't care about 'local' symbols since we cannot tell their compiland.
2960 switch (sym
->generic
.id
)
2963 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->data_v1
.p_name
),
2964 sym
->data_v1
.segment
, sym
->data_v1
.offset
, sym
->data_v1
.symtype
,
2965 FALSE
, FALSE
, FALSE
);
2968 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->data_v2
.p_name
),
2969 sym
->data_v2
.segment
, sym
->data_v2
.offset
, sym
->data_v2
.symtype
,
2970 FALSE
, FALSE
, FALSE
);
2973 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, sym
->data_v3
.name
,
2974 sym
->data_v3
.segment
, sym
->data_v3
.offset
, sym
->data_v3
.symtype
,
2975 FALSE
, FALSE
, FALSE
);
2977 /* variables with thread storage */
2978 case S_GTHREAD32_16t
:
2979 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->thread_v1
.p_name
),
2980 sym
->thread_v1
.segment
, sym
->thread_v1
.offset
, sym
->thread_v1
.symtype
,
2981 FALSE
, TRUE
, FALSE
);
2983 case S_GTHREAD32_ST
:
2984 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, terminate_string(&sym
->thread_v2
.p_name
),
2985 sym
->thread_v2
.segment
, sym
->thread_v2
.offset
, sym
->thread_v2
.symtype
,
2986 FALSE
, TRUE
, FALSE
);
2989 codeview_add_variable(msc_dbg
, NULL
, NULL
, NULL
, sym
->thread_v3
.name
,
2990 sym
->thread_v3
.segment
, sym
->thread_v3
.offset
, sym
->thread_v3
.symtype
,
2991 FALSE
, TRUE
, FALSE
);
2993 default: return FALSE
;
2998 static BOOL
pdb_global_feed_public(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
3000 switch (sym
->generic
.id
)
3003 symt_new_public(msc_dbg
->module
, NULL
,
3004 terminate_string(&sym
->public_v1
.p_name
),
3005 sym
->public_v1
.pubsymflags
== SYMTYPE_FUNCTION
,
3006 codeview_get_address(msc_dbg
, sym
->public_v1
.segment
, sym
->public_v1
.offset
), 1);
3009 symt_new_public(msc_dbg
->module
, NULL
,
3010 terminate_string(&sym
->public_v2
.p_name
),
3011 sym
->public_v2
.pubsymflags
== SYMTYPE_FUNCTION
,
3012 codeview_get_address(msc_dbg
, sym
->public_v2
.segment
, sym
->public_v2
.offset
), 1);
3015 symt_new_public(msc_dbg
->module
, NULL
,
3016 sym
->public_v3
.name
,
3017 sym
->public_v3
.pubsymflags
== SYMTYPE_FUNCTION
,
3018 codeview_get_address(msc_dbg
, sym
->public_v3
.segment
, sym
->public_v3
.offset
), 1);
3020 default: return FALSE
;
3025 /*========================================================================
3029 static void* pdb_jg_read(const struct PDB_JG_HEADER
* pdb
, const WORD
* block_list
,
3035 if (!size
) return NULL
;
3037 num_blocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
3038 buffer
= HeapAlloc(GetProcessHeap(), 0, num_blocks
* pdb
->block_size
);
3040 for (i
= 0; i
< num_blocks
; i
++)
3041 memcpy(buffer
+ i
* pdb
->block_size
,
3042 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
3047 static void* pdb_ds_read(const struct PDB_DS_HEADER
* pdb
, const UINT
*block_list
,
3053 if (!size
) return NULL
;
3055 num_blocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
3056 buffer
= HeapAlloc(GetProcessHeap(), 0, num_blocks
* pdb
->block_size
);
3058 for (i
= 0; i
< num_blocks
; i
++)
3059 memcpy(buffer
+ i
* pdb
->block_size
,
3060 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
3065 static void* pdb_read_jg_stream(const struct PDB_JG_HEADER
* pdb
,
3066 const struct PDB_JG_TOC
* toc
, DWORD stream_nr
)
3068 const WORD
* block_list
;
3071 if (!toc
|| stream_nr
>= toc
->num_streams
) return NULL
;
3073 block_list
= (const WORD
*) &toc
->streams
[toc
->num_streams
];
3074 for (i
= 0; i
< stream_nr
; i
++)
3075 block_list
+= (toc
->streams
[i
].size
+ pdb
->block_size
- 1) / pdb
->block_size
;
3077 return pdb_jg_read(pdb
, block_list
, toc
->streams
[stream_nr
].size
);
3080 static void* pdb_read_ds_stream(const struct PDB_DS_HEADER
* pdb
,
3081 const struct PDB_DS_TOC
* toc
, DWORD stream_nr
)
3083 const UINT
*block_list
;
3086 if (!toc
|| stream_nr
>= toc
->num_streams
) return NULL
;
3087 if (toc
->stream_size
[stream_nr
] == 0 || toc
->stream_size
[stream_nr
] == 0xFFFFFFFF) return NULL
;
3089 block_list
= &toc
->stream_size
[toc
->num_streams
];
3090 for (i
= 0; i
< stream_nr
; i
++)
3091 block_list
+= (toc
->stream_size
[i
] + pdb
->block_size
- 1) / pdb
->block_size
;
3093 return pdb_ds_read(pdb
, block_list
, toc
->stream_size
[stream_nr
]);
3096 static void* pdb_read_stream(const struct pdb_file_info
* pdb_file
,
3099 switch (pdb_file
->kind
)
3102 return pdb_read_jg_stream((const struct PDB_JG_HEADER
*)pdb_file
->image
,
3103 pdb_file
->u
.jg
.toc
, stream_nr
);
3105 return pdb_read_ds_stream((const struct PDB_DS_HEADER
*)pdb_file
->image
,
3106 pdb_file
->u
.ds
.toc
, stream_nr
);
3111 static unsigned pdb_get_stream_size(const struct pdb_file_info
* pdb_file
, DWORD stream_nr
)
3113 switch (pdb_file
->kind
)
3115 case PDB_JG
: return pdb_file
->u
.jg
.toc
->streams
[stream_nr
].size
;
3116 case PDB_DS
: return pdb_file
->u
.ds
.toc
->stream_size
[stream_nr
];
3121 static void pdb_free(void* buffer
)
3123 HeapFree(GetProcessHeap(), 0, buffer
);
3126 static void pdb_free_file(struct pdb_file_info
* pdb_file
)
3128 switch (pdb_file
->kind
)
3131 pdb_free(pdb_file
->u
.jg
.toc
);
3132 pdb_file
->u
.jg
.toc
= NULL
;
3135 pdb_free(pdb_file
->u
.ds
.toc
);
3136 pdb_file
->u
.ds
.toc
= NULL
;
3139 HeapFree(GetProcessHeap(), 0, pdb_file
->stream_dict
);
3142 static BOOL
pdb_load_stream_name_table(struct pdb_file_info
* pdb_file
, const char* str
, unsigned cb
)
3150 pdw
= (DWORD
*)(str
+ cb
);
3154 pdb_file
->stream_dict
= HeapAlloc(GetProcessHeap(), 0, (numok
+ 1) * sizeof(struct pdb_stream_name
) + cb
);
3155 if (!pdb_file
->stream_dict
) return FALSE
;
3156 cpstr
= (char*)(pdb_file
->stream_dict
+ numok
+ 1);
3157 memcpy(cpstr
, str
, cb
);
3159 /* bitfield: first dword is len (in dword), then data */
3161 pdw
+= *ok_bits
++ + 1;
3164 FIXME("unexpected value\n");
3168 for (i
= j
= 0; i
< count
; i
++)
3170 if (ok_bits
[i
/ 32] & (1 << (i
% 32)))
3172 if (j
>= numok
) break;
3173 pdb_file
->stream_dict
[j
].name
= &cpstr
[*pdw
++];
3174 pdb_file
->stream_dict
[j
].index
= *pdw
++;
3179 pdb_file
->stream_dict
[numok
].name
= NULL
;
3180 pdb_file
->fpoext_stream
= -1;
3184 static unsigned pdb_get_stream_by_name(const struct pdb_file_info
* pdb_file
, const char* name
)
3186 struct pdb_stream_name
* psn
;
3188 for (psn
= pdb_file
->stream_dict
; psn
&& psn
->name
; psn
++)
3190 if (!strcmp(psn
->name
, name
)) return psn
->index
;
3195 static PDB_STRING_TABLE
* pdb_read_strings(const struct pdb_file_info
* pdb_file
)
3198 PDB_STRING_TABLE
*ret
;
3200 idx
= pdb_get_stream_by_name(pdb_file
, "/names");
3203 ret
= pdb_read_stream( pdb_file
, idx
);
3204 if (ret
&& ret
->magic
== 0xeffeeffe &&
3205 sizeof(*ret
) + ret
->length
<= pdb_get_stream_size(pdb_file
, idx
)) return ret
;
3208 WARN("string table not found\n");
3212 static const char* pdb_get_string_table_entry(const PDB_STRING_TABLE
* table
, unsigned offset
)
3214 return (!table
|| offset
>= table
->length
) ? NULL
: (const char*)(table
+ 1) + offset
;
3217 static void pdb_module_remove(struct process
* pcsn
, struct module_format
* modfmt
)
3221 for (i
= 0; i
< modfmt
->u
.pdb_info
->used_subfiles
; i
++)
3223 pdb_free_file(&modfmt
->u
.pdb_info
->pdb_files
[i
]);
3224 if (modfmt
->u
.pdb_info
->pdb_files
[i
].image
)
3225 UnmapViewOfFile(modfmt
->u
.pdb_info
->pdb_files
[i
].image
);
3226 if (modfmt
->u
.pdb_info
->pdb_files
[i
].hMap
)
3227 CloseHandle(modfmt
->u
.pdb_info
->pdb_files
[i
].hMap
);
3229 HeapFree(GetProcessHeap(), 0, modfmt
);
3232 static BOOL
pdb_convert_types_header(PDB_TYPES
* types
, const BYTE
* image
)
3234 if (!image
) return FALSE
;
3236 if (*(const DWORD
*)image
< 19960000) /* FIXME: correct version? */
3238 /* Old version of the types record header */
3239 const PDB_TYPES_OLD
* old
= (const PDB_TYPES_OLD
*)image
;
3240 memset(types
, 0, sizeof(PDB_TYPES
));
3241 types
->version
= old
->version
;
3242 types
->type_offset
= sizeof(PDB_TYPES_OLD
);
3243 types
->type_size
= old
->type_size
;
3244 types
->first_index
= old
->first_index
;
3245 types
->last_index
= old
->last_index
;
3246 types
->hash_stream
= old
->hash_stream
;
3250 /* New version of the types record header */
3251 *types
= *(const PDB_TYPES
*)image
;
3256 static void pdb_convert_symbols_header(PDB_SYMBOLS
* symbols
,
3257 int* header_size
, const BYTE
* image
)
3259 memset(symbols
, 0, sizeof(PDB_SYMBOLS
));
3262 if (*(const DWORD
*)image
!= 0xffffffff)
3264 /* Old version of the symbols record header */
3265 const PDB_SYMBOLS_OLD
* old
= (const PDB_SYMBOLS_OLD
*)image
;
3266 symbols
->version
= 0;
3267 symbols
->module_size
= old
->module_size
;
3268 symbols
->sectcontrib_size
= old
->sectcontrib_size
;
3269 symbols
->segmap_size
= old
->segmap_size
;
3270 symbols
->srcmodule_size
= old
->srcmodule_size
;
3271 symbols
->pdbimport_size
= 0;
3272 symbols
->global_hash_stream
= old
->global_hash_stream
;
3273 symbols
->public_stream
= old
->public_stream
;
3274 symbols
->gsym_stream
= old
->gsym_stream
;
3276 *header_size
= sizeof(PDB_SYMBOLS_OLD
);
3280 /* New version of the symbols record header */
3281 *symbols
= *(const PDB_SYMBOLS
*)image
;
3282 *header_size
= sizeof(PDB_SYMBOLS
);
3286 static void pdb_convert_symbol_file(const PDB_SYMBOLS
* symbols
,
3287 PDB_SYMBOL_FILE_EX
* sfile
,
3288 unsigned* size
, const void* image
)
3291 if (symbols
->version
< 19970000)
3293 const PDB_SYMBOL_FILE
*sym_file
= image
;
3294 memset(sfile
, 0, sizeof(*sfile
));
3295 sfile
->stream
= sym_file
->stream
;
3296 sfile
->range
.index
= sym_file
->range
.index
;
3297 sfile
->symbol_size
= sym_file
->symbol_size
;
3298 sfile
->lineno_size
= sym_file
->lineno_size
;
3299 sfile
->lineno2_size
= sym_file
->lineno2_size
;
3300 *size
= sizeof(PDB_SYMBOL_FILE
) - 1;
3304 memcpy(sfile
, image
, sizeof(PDB_SYMBOL_FILE_EX
));
3305 *size
= sizeof(PDB_SYMBOL_FILE_EX
) - 1;
3309 static HANDLE
map_pdb_file(const struct process
* pcs
,
3310 const struct pdb_lookup
* lookup
,
3311 struct module
* module
)
3313 HANDLE hFile
, hMap
= NULL
;
3314 WCHAR dbg_file_path
[MAX_PATH
];
3317 switch (lookup
->kind
)
3320 ret
= path_find_symbol_file(pcs
, module
, lookup
->filename
, DMT_PDB
, NULL
, lookup
->timestamp
,
3321 lookup
->age
, dbg_file_path
, &module
->module
.PdbUnmatched
);
3324 ret
= path_find_symbol_file(pcs
, module
, lookup
->filename
, DMT_PDB
, &lookup
->guid
, 0,
3325 lookup
->age
, dbg_file_path
, &module
->module
.PdbUnmatched
);
3330 WARN("\tCouldn't find %s\n", lookup
->filename
);
3333 if ((hFile
= CreateFileW(dbg_file_path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
3334 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
)) != INVALID_HANDLE_VALUE
)
3336 hMap
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3342 static void pdb_dispose_type_parse(struct codeview_type_parse
* ctp
)
3344 pdb_free(ctp
->hash_stream
);
3345 free((DWORD
*)ctp
->offset
);
3346 free((DWORD
*)ctp
->hash
);
3347 free((DWORD
*)ctp
->alloc_hash
);
3350 static BOOL
pdb_bitfield_is_bit_set(const unsigned* dw
, unsigned len
, unsigned i
)
3352 if (i
>= len
* sizeof(unsigned) * 8) return FALSE
;
3353 return (dw
[i
>> 5] & (1u << (i
& 31u))) != 0;
3356 static BOOL
pdb_init_type_parse(const struct msc_debug_info
* msc_dbg
,
3357 const struct pdb_file_info
* pdb_file
,
3358 struct codeview_type_parse
* ctp
,
3365 ctp
->hash_stream
= NULL
;
3368 ctp
->alloc_hash
= NULL
;
3369 if (!pdb_convert_types_header(&ctp
->header
, image
))
3372 /* Check for unknown versions */
3373 switch (ctp
->header
.version
)
3375 case 19950410: /* VC 4.0 */
3377 case 19961031: /* VC 5.0 / 6.0 */
3378 case 19990903: /* VC 7.0 */
3379 case 20040203: /* VC 8.0 */
3382 ERR("-Unknown type info version %d\n", ctp
->header
.version
);
3385 if (ctp
->header
.hash_value_size
!= 2 && ctp
->header
.hash_value_size
!= 4)
3387 ERR("-Unsupported hash of size %u\n", ctp
->header
.hash_value_size
);
3390 ctp
->hash_stream
= pdb_read_stream(pdb_file
, ctp
->header
.hash_stream
);
3391 /* FIXME always present? if not reconstruct ?*/
3392 if (!ctp
->hash_stream
)
3394 ERR("-Missing hash table in PDB file\n");
3398 ctp
->module
= msc_dbg
->module
;
3399 /* Reconstruct the types offset table
3400 * Note: the hash stream of the PDB_TYPES only contains a partial table
3401 * (not all the indexes are present, so it requires first a binary search in partial table,
3402 * followed by a linear search...)
3404 offset
= malloc(sizeof(DWORD
) * (ctp
->header
.last_index
- ctp
->header
.first_index
));
3405 if (!offset
) goto oom
;
3406 ctp
->table
= ptr
= image
+ ctp
->header
.type_offset
;
3407 for (i
= ctp
->header
.first_index
; i
< ctp
->header
.last_index
; i
++)
3409 offset
[i
- ctp
->header
.first_index
] = ptr
- ctp
->table
;
3410 ptr
+= ((const union codeview_type
*)ptr
)->generic
.len
+ 2;
3412 ctp
->offset
= offset
;
3413 ctp
->hash
= calloc(ctp
->header
.hash_num_buckets
, sizeof(struct hash_link
*));
3414 if (!ctp
->hash
) goto oom
;
3415 ctp
->alloc_hash
= calloc(ctp
->header
.last_index
- ctp
->header
.first_index
, sizeof(struct hash_link
));
3416 if (!ctp
->alloc_hash
) goto oom
;
3417 for (i
= ctp
->header
.first_index
; i
< ctp
->header
.last_index
; i
++)
3419 unsigned hash_i
= pdb_read_hash_value(ctp
, i
);
3420 ctp
->alloc_hash
[i
- ctp
->header
.first_index
].id
= i
;
3421 ctp
->alloc_hash
[i
- ctp
->header
.first_index
].next
= ctp
->hash
[hash_i
];
3422 ctp
->hash
[hash_i
] = &ctp
->alloc_hash
[i
- ctp
->header
.first_index
];
3424 /* parse the remap table
3425 * => move listed type_id at first position of their hash buckets so that we force remap to them
3427 if (ctp
->header
.type_remap_size
)
3429 const unsigned* remap
= (const unsigned*)((const BYTE
*)ctp
->hash_stream
+ ctp
->header
.type_remap_offset
);
3430 unsigned i
, capa
, count_present
;
3431 const unsigned* present_bitset
;
3432 remap
++; /* no need of num */
3434 count_present
= *remap
++;
3435 present_bitset
= remap
;
3436 remap
+= count_present
;
3437 remap
+= *remap
+ 1; /* skip deleted bit set */
3438 for (i
= 0; i
< capa
; ++i
)
3440 if (pdb_bitfield_is_bit_set(present_bitset
, count_present
, i
))
3443 struct hash_link
** phl
;
3444 /* remap[0] is an offset for a string in /string stream, followed by type_id to force */
3445 hash_i
= pdb_read_hash_value(ctp
, remap
[1]);
3446 for (phl
= &ctp
->hash
[hash_i
]; *phl
; phl
= &(*phl
)->next
)
3447 if ((*phl
)->id
== remap
[1])
3449 struct hash_link
* hl
= *phl
;
3450 /* move hl node at first position of its hash bucket */
3452 hl
->next
= ctp
->hash
[hash_i
];
3453 ctp
->hash
[hash_i
] = hl
;
3462 pdb_dispose_type_parse(ctp
);
3466 static void pdb_process_types(const struct msc_debug_info
* msc_dbg
,
3467 const struct pdb_file_info
* pdb_file
)
3469 struct codeview_type_parse ctp
;
3470 BYTE
* types_image
= pdb_read_stream(pdb_file
, 2);
3474 if (pdb_init_type_parse(msc_dbg
, pdb_file
, &ctp
, types_image
))
3476 /* Read type table */
3477 codeview_parse_type_table(&ctp
);
3478 pdb_dispose_type_parse(&ctp
);
3480 pdb_free(types_image
);
3484 static const char PDB_JG_IDENT
[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0";
3485 static const char PDB_DS_IDENT
[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
3487 /******************************************************************
3490 * Tries to load a pdb file
3491 * 'matched' is filled with the number of correct matches for this file:
3492 * - age counts for one
3493 * - timestamp or guid depending on kind counts for one
3494 * a wrong kind of file returns FALSE (FIXME ?)
3496 static BOOL
pdb_init(const struct pdb_lookup
* pdb_lookup
, struct pdb_file_info
* pdb_file
,
3497 const char* image
, unsigned* matched
)
3501 /* check the file header, and if ok, load the TOC */
3502 TRACE("PDB(%s): %.40s\n", pdb_lookup
->filename
, debugstr_an(image
, 40));
3505 if (!memcmp(image
, PDB_JG_IDENT
, sizeof(PDB_JG_IDENT
)))
3507 const struct PDB_JG_HEADER
* pdb
= (const struct PDB_JG_HEADER
*)image
;
3508 struct PDB_JG_ROOT
* root
;
3510 pdb_file
->u
.jg
.toc
= pdb_jg_read(pdb
, pdb
->toc_block
, pdb
->toc
.size
);
3511 root
= pdb_read_jg_stream(pdb
, pdb_file
->u
.jg
.toc
, 1);
3514 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup
->filename
);
3517 switch (root
->Version
)
3519 case 19950623: /* VC 4.0 */
3521 case 19960307: /* VC 5.0 */
3522 case 19970604: /* VC 6.0 */
3525 ERR("-Unknown root block version %d\n", root
->Version
);
3527 if (pdb_lookup
->kind
!= PDB_JG
)
3529 WARN("Found %s, but wrong PDB kind\n", pdb_lookup
->filename
);
3533 pdb_file
->kind
= PDB_JG
;
3534 pdb_file
->u
.jg
.timestamp
= root
->TimeDateStamp
;
3535 pdb_file
->age
= root
->Age
;
3536 if (root
->TimeDateStamp
== pdb_lookup
->timestamp
) (*matched
)++;
3537 else WARN("Found %s, but wrong signature: %08x %08x\n",
3538 pdb_lookup
->filename
, root
->TimeDateStamp
, pdb_lookup
->timestamp
);
3539 if (root
->Age
== pdb_lookup
->age
) (*matched
)++;
3540 else WARN("Found %s, but wrong age: %08x %08x\n",
3541 pdb_lookup
->filename
, root
->Age
, pdb_lookup
->age
);
3542 TRACE("found JG for %s: age=%x timestamp=%x\n",
3543 pdb_lookup
->filename
, root
->Age
, root
->TimeDateStamp
);
3544 ret
= pdb_load_stream_name_table(pdb_file
, &root
->names
[0], root
->cbNames
);
3547 else if (!memcmp(image
, PDB_DS_IDENT
, sizeof(PDB_DS_IDENT
)))
3549 const struct PDB_DS_HEADER
* pdb
= (const struct PDB_DS_HEADER
*)image
;
3550 struct PDB_DS_ROOT
* root
;
3552 pdb_file
->u
.ds
.toc
=
3553 pdb_ds_read(pdb
, (const UINT
*)((const char*)pdb
+ pdb
->toc_block
* pdb
->block_size
),
3555 root
= pdb_read_ds_stream(pdb
, pdb_file
->u
.ds
.toc
, 1);
3558 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup
->filename
);
3561 switch (root
->Version
)
3566 ERR("-Unknown root block version %u\n", root
->Version
);
3568 pdb_file
->kind
= PDB_DS
;
3569 pdb_file
->u
.ds
.guid
= root
->guid
;
3570 pdb_file
->age
= root
->Age
;
3571 if (!memcmp(&root
->guid
, &pdb_lookup
->guid
, sizeof(GUID
))) (*matched
)++;
3572 else WARN("Found %s, but wrong GUID: %s %s\n",
3573 pdb_lookup
->filename
, debugstr_guid(&root
->guid
),
3574 debugstr_guid(&pdb_lookup
->guid
));
3575 if (root
->Age
== pdb_lookup
->age
) (*matched
)++;
3576 else WARN("Found %s, but wrong age: %08x %08x\n",
3577 pdb_lookup
->filename
, root
->Age
, pdb_lookup
->age
);
3578 TRACE("found DS for %s: age=%x guid=%s\n",
3579 pdb_lookup
->filename
, root
->Age
, debugstr_guid(&root
->guid
));
3580 ret
= pdb_load_stream_name_table(pdb_file
, &root
->names
[0], root
->cbNames
);
3585 if (0) /* some tool to dump the internal files from a PDB file */
3589 switch (pdb_file
->kind
)
3591 case PDB_JG
: num_streams
= pdb_file
->u
.jg
.toc
->num_streams
; break;
3592 case PDB_DS
: num_streams
= pdb_file
->u
.ds
.toc
->num_streams
; break;
3595 for (i
= 1; i
< num_streams
; i
++)
3597 unsigned char* x
= pdb_read_stream(pdb_file
, i
);
3598 FIXME("********************** [%u]: size=%08x\n",
3599 i
, pdb_get_stream_size(pdb_file
, i
));
3600 dump(x
, pdb_get_stream_size(pdb_file
, i
));
3607 static BOOL
pdb_process_internal(const struct process
* pcs
,
3608 const struct msc_debug_info
* msc_dbg
,
3609 const struct pdb_lookup
* pdb_lookup
,
3610 struct pdb_module_info
* pdb_module_info
,
3611 unsigned module_index
);
3613 DWORD
pdb_get_file_indexinfo(void* image
, DWORD size
, SYMSRV_INDEX_INFOW
* info
)
3615 /* check the file header, and if ok, load the TOC */
3616 TRACE("PDB: %.40s\n", debugstr_an(image
, 40));
3618 if (!memcmp(image
, PDB_JG_IDENT
, sizeof(PDB_JG_IDENT
)))
3620 FIXME("Unsupported for PDB files in JG format\n");
3621 return ERROR_FILE_CORRUPT
;
3623 if (!memcmp(image
, PDB_DS_IDENT
, sizeof(PDB_DS_IDENT
)))
3625 const struct PDB_DS_HEADER
* pdb
= (const struct PDB_DS_HEADER
*)image
;
3626 struct PDB_DS_TOC
* ds_toc
;
3627 struct PDB_DS_ROOT
* root
;
3628 DWORD ec
= ERROR_SUCCESS
;
3630 ds_toc
= pdb_ds_read(pdb
, (const UINT
*)((const char*)pdb
+ pdb
->toc_block
* pdb
->block_size
),
3632 root
= pdb_read_ds_stream(pdb
, ds_toc
, 1);
3636 return ERROR_FILE_CORRUPT
;
3638 switch (root
->Version
)
3643 ERR("-Unknown root block version %u\n", root
->Version
);
3644 ec
= ERROR_FILE_CORRUPT
;
3646 /* The age field is present twice (in PDB_ROOT and in PDB_SYMBOLS ),
3647 * It's the one in PDB_SYMBOLS which is reported.
3649 if (ec
== ERROR_SUCCESS
)
3651 PDB_SYMBOLS
* symbols
= pdb_read_ds_stream(pdb
, ds_toc
, 3);
3653 if (symbols
&& symbols
->version
== 19990903)
3655 info
->age
= symbols
->age
;
3660 ERR("-Unknown symbol info version %u %08x\n", symbols
->version
, symbols
->version
);
3661 ec
= ERROR_FILE_CORRUPT
;
3665 if (ec
== ERROR_SUCCESS
)
3667 info
->dbgfile
[0] = '\0';
3668 info
->guid
= root
->guid
;
3669 info
->pdbfile
[0] = '\0';
3672 info
->stripped
= FALSE
;
3673 info
->timestamp
= 0;
3680 return ERROR_BAD_FORMAT
;
3683 static void pdb_process_symbol_imports(const struct process
* pcs
,
3684 const struct msc_debug_info
* msc_dbg
,
3685 const PDB_SYMBOLS
* symbols
,
3686 const void* symbols_image
,
3688 const struct pdb_lookup
* pdb_lookup
,
3689 struct pdb_module_info
* pdb_module_info
,
3690 unsigned module_index
)
3692 if (module_index
== -1 && symbols
&& symbols
->pdbimport_size
)
3694 const PDB_SYMBOL_IMPORT
*imp
;
3699 struct pdb_file_info sf0
= pdb_module_info
->pdb_files
[0];
3701 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)symbols_image
+ sizeof(PDB_SYMBOLS
) +
3702 symbols
->module_size
+ symbols
->sectcontrib_size
+
3703 symbols
->segmap_size
+ symbols
->srcmodule_size
);
3705 last
= (const char*)imp
+ symbols
->pdbimport_size
;
3706 while (imp
< (const PDB_SYMBOL_IMPORT
*)last
)
3708 ptr
= (const char*)imp
+ sizeof(*imp
) + strlen(imp
->filename
);
3709 if (i
>= CV_MAX_MODULES
) FIXME("Out of bounds!!!\n");
3710 if (!stricmp(pdb_lookup
->filename
, imp
->filename
))
3712 if (module_index
!= -1) FIXME("Twice the entry\n");
3713 else module_index
= i
;
3714 pdb_module_info
->pdb_files
[i
] = sf0
;
3718 struct pdb_lookup imp_pdb_lookup
;
3720 /* FIXME: this is an import of a JG PDB file
3721 * how's a DS PDB handled ?
3723 imp_pdb_lookup
.filename
= imp
->filename
;
3724 imp_pdb_lookup
.kind
= PDB_JG
;
3725 imp_pdb_lookup
.timestamp
= imp
->TimeDateStamp
;
3726 imp_pdb_lookup
.age
= imp
->Age
;
3727 TRACE("got for %s: age=%u ts=%x\n",
3728 imp
->filename
, imp
->Age
, imp
->TimeDateStamp
);
3729 pdb_process_internal(pcs
, msc_dbg
, &imp_pdb_lookup
, pdb_module_info
, i
);
3732 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)first
+ ((ptr
- (const char*)first
+ strlen(ptr
) + 1 + 3) & ~3));
3734 pdb_module_info
->used_subfiles
= i
;
3736 if (module_index
== -1)
3739 pdb_module_info
->used_subfiles
= 1;
3741 cv_current_module
= &cv_zmodules
[module_index
];
3742 if (cv_current_module
->allowed
) FIXME("Already allowed??\n");
3743 cv_current_module
->allowed
= TRUE
;
3746 static BOOL
pdb_process_internal(const struct process
* pcs
,
3747 const struct msc_debug_info
* msc_dbg
,
3748 const struct pdb_lookup
* pdb_lookup
,
3749 struct pdb_module_info
* pdb_module_info
,
3750 unsigned module_index
)
3754 BYTE
* symbols_image
= NULL
;
3755 PDB_STRING_TABLE
* files_image
= NULL
;
3757 struct pdb_file_info
* pdb_file
;
3759 TRACE("Processing PDB file %s\n", pdb_lookup
->filename
);
3761 pdb_file
= &pdb_module_info
->pdb_files
[module_index
== -1 ? 0 : module_index
];
3762 /* Open and map() .PDB file */
3763 if ((hMap
= map_pdb_file(pcs
, pdb_lookup
, msc_dbg
->module
)) == NULL
||
3764 ((image
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) == NULL
))
3766 WARN("Unable to open .PDB file: %s\n", pdb_lookup
->filename
);
3770 if (!pdb_init(pdb_lookup
, pdb_file
, image
, &matched
) || matched
!= 2)
3773 UnmapViewOfFile(image
);
3777 pdb_file
->hMap
= hMap
;
3778 pdb_file
->image
= image
;
3779 symbols_image
= pdb_read_stream(pdb_file
, 3);
3782 PDB_SYMBOLS symbols
;
3786 struct codeview_type_parse ipi_ctp
;
3788 int header_size
= 0;
3789 PDB_STREAM_INDEXES
* psi
;
3792 pdb_convert_symbols_header(&symbols
, &header_size
, symbols_image
);
3793 switch (symbols
.version
)
3795 case 0: /* VC 4.0 */
3796 case 19960307: /* VC 5.0 */
3797 case 19970606: /* VC 6.0 */
3801 ERR("-Unknown symbol info version %u %08x\n",
3802 symbols
.version
, symbols
.version
);
3805 switch (symbols
.stream_index_size
)
3808 case sizeof(PDB_STREAM_INDEXES_OLD
):
3809 /* no fpo ext stream in this case */
3811 case sizeof(PDB_STREAM_INDEXES
):
3812 psi
= (PDB_STREAM_INDEXES
*)((const char*)symbols_image
+ sizeof(PDB_SYMBOLS
) +
3813 symbols
.module_size
+ symbols
.sectcontrib_size
+
3814 symbols
.segmap_size
+ symbols
.srcmodule_size
+
3815 symbols
.pdbimport_size
+ symbols
.unknown2_size
);
3816 pdb_file
->fpoext_stream
= psi
->FPO_EXT
;
3819 FIXME("Unknown PDB_STREAM_INDEXES size (%u)\n", symbols
.stream_index_size
);
3820 pdb_free(symbols_image
);
3823 files_image
= pdb_read_strings(pdb_file
);
3825 pdb_process_symbol_imports(pcs
, msc_dbg
, &symbols
, symbols_image
, image
,
3826 pdb_lookup
, pdb_module_info
, module_index
);
3827 pdb_process_types(msc_dbg
, pdb_file
);
3829 ipi_image
= pdb_read_stream(pdb_file
, 4);
3830 ipi_ok
= pdb_init_type_parse(msc_dbg
, pdb_file
, &ipi_ctp
, ipi_image
);
3832 /* Read global types first, so that lookup by name in module (=compilation unit)
3833 * streams' loading can succeed them.
3835 globalimage
= pdb_read_stream(pdb_file
, symbols
.gsym_stream
);
3839 unsigned global_size
= pdb_get_stream_size(pdb_file
, symbols
.gsym_stream
);
3841 data
= pdb_read_stream(pdb_file
, symbols
.global_hash_stream
);
3844 codeview_snarf_sym_hashtable(msc_dbg
, globalimage
, global_size
,
3845 data
, pdb_get_stream_size(pdb_file
, symbols
.global_hash_stream
),
3846 pdb_global_feed_types
);
3847 pdb_free((void*)data
);
3851 /* Read per-module symbols' tables */
3852 file
= symbols_image
+ header_size
;
3853 while (file
- symbols_image
< header_size
+ symbols
.module_size
)
3855 PDB_SYMBOL_FILE_EX sfile
;
3856 const char* file_name
;
3859 HeapValidate(GetProcessHeap(), 0, NULL
);
3860 pdb_convert_symbol_file(&symbols
, &sfile
, &size
, file
);
3862 modimage
= pdb_read_stream(pdb_file
, sfile
.stream
);
3863 file_name
= (const char*)file
+ size
;
3866 struct cv_module_snarf cvmod
= {ipi_ok
? &ipi_ctp
: NULL
, (const void*)(modimage
+ sfile
.symbol_size
), sfile
.lineno2_size
,
3868 codeview_snarf(msc_dbg
, modimage
, sizeof(DWORD
), sfile
.symbol_size
, &cvmod
, file_name
);
3870 if (sfile
.lineno_size
&& sfile
.lineno2_size
)
3871 FIXME("Both line info present... only supporting second\n");
3872 else if (sfile
.lineno_size
)
3873 codeview_snarf_linetab(msc_dbg
,
3874 modimage
+ sfile
.symbol_size
,
3876 pdb_file
->kind
== PDB_JG
);
3880 file_name
+= strlen(file_name
) + 1;
3881 /* now at lib_name */
3882 file
= (BYTE
*)((DWORD_PTR
)(file_name
+ strlen(file_name
) + 1 + 3) & ~3);
3884 /* Load the global variables and constants (if not yet loaded) and public information */
3888 unsigned global_size
= pdb_get_stream_size(pdb_file
, symbols
.gsym_stream
);
3890 data
= pdb_read_stream(pdb_file
, symbols
.global_hash_stream
);
3893 codeview_snarf_sym_hashtable(msc_dbg
, globalimage
, global_size
,
3894 data
, pdb_get_stream_size(pdb_file
, symbols
.global_hash_stream
),
3895 pdb_global_feed_variables
);
3896 pdb_free((void*)data
);
3898 if (!(dbghelp_options
& SYMOPT_NO_PUBLICS
) && (data
= pdb_read_stream(pdb_file
, symbols
.public_stream
)))
3900 const DBI_PUBLIC_HEADER
* pubhdr
= (const DBI_PUBLIC_HEADER
*)data
;
3901 codeview_snarf_sym_hashtable(msc_dbg
, globalimage
, pdb_get_stream_size(pdb_file
, symbols
.gsym_stream
),
3902 (const BYTE
*)(pubhdr
+ 1), pubhdr
->hash_size
, pdb_global_feed_public
);
3903 pdb_free((void*)data
);
3905 pdb_free(globalimage
);
3907 HeapFree(GetProcessHeap(), 0, (DWORD
*)ipi_ctp
.offset
);
3908 pdb_free(ipi_image
);
3911 pdb_process_symbol_imports(pcs
, msc_dbg
, NULL
, NULL
, image
,
3912 pdb_lookup
, pdb_module_info
, module_index
);
3914 pdb_free(symbols_image
);
3915 pdb_free(files_image
);
3920 static BOOL
pdb_process_file(const struct process
* pcs
,
3921 const struct msc_debug_info
* msc_dbg
,
3922 struct pdb_lookup
* pdb_lookup
)
3925 struct module_format
* modfmt
;
3926 struct pdb_module_info
* pdb_module_info
;
3928 modfmt
= HeapAlloc(GetProcessHeap(), 0,
3929 sizeof(struct module_format
) + sizeof(struct pdb_module_info
));
3930 if (!modfmt
) return FALSE
;
3932 pdb_module_info
= (void*)(modfmt
+ 1);
3933 msc_dbg
->module
->format_info
[DFI_PDB
] = modfmt
;
3934 modfmt
->module
= msc_dbg
->module
;
3935 modfmt
->remove
= pdb_module_remove
;
3936 modfmt
->loc_compute
= pdb_location_compute
;
3937 modfmt
->u
.pdb_info
= pdb_module_info
;
3939 memset(cv_zmodules
, 0, sizeof(cv_zmodules
));
3940 codeview_init_basic_types(msc_dbg
->module
);
3941 ret
= pdb_process_internal(pcs
, msc_dbg
, pdb_lookup
,
3942 msc_dbg
->module
->format_info
[DFI_PDB
]->u
.pdb_info
, -1);
3943 codeview_clear_type_table();
3946 struct pdb_module_info
* pdb_info
= msc_dbg
->module
->format_info
[DFI_PDB
]->u
.pdb_info
;
3947 msc_dbg
->module
->module
.SymType
= SymPdb
;
3948 if (pdb_info
->pdb_files
[0].kind
== PDB_JG
)
3949 msc_dbg
->module
->module
.PdbSig
= pdb_info
->pdb_files
[0].u
.jg
.timestamp
;
3951 msc_dbg
->module
->module
.PdbSig70
= pdb_info
->pdb_files
[0].u
.ds
.guid
;
3952 msc_dbg
->module
->module
.PdbAge
= pdb_info
->pdb_files
[0].age
;
3953 MultiByteToWideChar(CP_ACP
, 0, pdb_lookup
->filename
, -1,
3954 msc_dbg
->module
->module
.LoadedPdbName
,
3955 ARRAY_SIZE(msc_dbg
->module
->module
.LoadedPdbName
));
3956 /* FIXME: we could have a finer grain here */
3957 msc_dbg
->module
->module
.LineNumbers
= TRUE
;
3958 msc_dbg
->module
->module
.GlobalSymbols
= TRUE
;
3959 msc_dbg
->module
->module
.TypeInfo
= TRUE
;
3960 msc_dbg
->module
->module
.SourceIndexed
= TRUE
;
3961 msc_dbg
->module
->module
.Publics
= TRUE
;
3965 msc_dbg
->module
->format_info
[DFI_PDB
] = NULL
;
3966 HeapFree(GetProcessHeap(), 0, modfmt
);
3971 BOOL
pdb_fetch_file_info(const struct pdb_lookup
* pdb_lookup
, unsigned* matched
)
3973 HANDLE hFile
, hMap
= NULL
;
3976 struct pdb_file_info pdb_file
;
3978 if ((hFile
= CreateFileA(pdb_lookup
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
3979 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
)) == INVALID_HANDLE_VALUE
||
3980 ((hMap
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
)) == NULL
) ||
3981 ((image
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) == NULL
))
3983 WARN("Unable to open .PDB file: %s\n", pdb_lookup
->filename
);
3988 ret
= pdb_init(pdb_lookup
, &pdb_file
, image
, matched
);
3989 pdb_free_file(&pdb_file
);
3992 if (image
) UnmapViewOfFile(image
);
3993 if (hMap
) CloseHandle(hMap
);
3994 if (hFile
!= INVALID_HANDLE_VALUE
) CloseHandle(hFile
);
3999 /*========================================================================
4000 * FPO unwinding code
4003 /* Stack unwinding is based on postfixed operations.
4004 * Let's define our Postfix EValuator
4006 #define PEV_MAX_LEN 32
4009 struct cpu_stack_walk
* csw
;
4011 struct vector stack
;
4013 struct hash_table values
;
4020 struct hash_table_elt elt
;
4023 #define PEV_ERROR(pev, msg) snprintf((pev)->error, sizeof((pev)->error), "%s", (msg))
4024 #define PEV_ERROR1(pev, msg, pmt) snprintf((pev)->error, sizeof((pev)->error), (msg), (pmt))
4027 static void pev_dump_stack(struct pevaluator
* pev
)
4030 FIXME("stack #%d\n", pev
->stk_index
);
4031 for (i
= 0; i
< pev
->stk_index
; i
++)
4033 FIXME("\t%d) %s\n", i
, *(char**)vector_at(&pev
->stack
, i
));
4038 /* get the value out of an operand (variable or literal) */
4039 static BOOL
pev_get_val(struct pevaluator
* pev
, const char* str
, DWORD_PTR
* val
)
4042 struct hash_table_iter hti
;
4049 hash_table_iter_init(&pev
->values
, &hti
, str
);
4050 while ((ptr
= hash_table_iter_up(&hti
)))
4052 if (!strcmp(CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->elt
.name
, str
))
4054 *val
= CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->value
;
4058 return PEV_ERROR1(pev
, "get_zvalue: no value found (%s)", str
);
4060 *val
= strtol(str
, &n
, 10);
4061 if (n
== str
|| *n
!= '\0')
4062 return PEV_ERROR1(pev
, "get_val: not a literal (%s)", str
);
4067 /* push an operand onto the stack */
4068 static BOOL
pev_push(struct pevaluator
* pev
, const char* elt
)
4071 if (pev
->stk_index
< vector_length(&pev
->stack
))
4072 at
= vector_at(&pev
->stack
, pev
->stk_index
);
4074 at
= vector_add(&pev
->stack
, &pev
->pool
);
4075 if (!at
) return PEV_ERROR(pev
, "push: out of memory");
4076 *at
= pool_strdup(&pev
->pool
, elt
);
4081 /* pop an operand from the stack */
4082 static BOOL
pev_pop(struct pevaluator
* pev
, char* elt
)
4084 char** at
= vector_at(&pev
->stack
, --pev
->stk_index
);
4085 if (!at
) return PEV_ERROR(pev
, "pop: stack empty");
4090 /* pop an operand from the stack, and gets its value */
4091 static BOOL
pev_pop_val(struct pevaluator
* pev
, DWORD_PTR
* val
)
4093 char p
[PEV_MAX_LEN
];
4095 return pev_pop(pev
, p
) && pev_get_val(pev
, p
, val
);
4098 /* set var 'name' a new value (creates the var if it doesn't exist) */
4099 static BOOL
pev_set_value(struct pevaluator
* pev
, const char* name
, DWORD_PTR val
)
4101 struct hash_table_iter hti
;
4104 hash_table_iter_init(&pev
->values
, &hti
, name
);
4105 while ((ptr
= hash_table_iter_up(&hti
)))
4107 if (!strcmp(CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->elt
.name
, name
))
4109 CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->value
= val
;
4115 struct zvalue
* zv
= pool_alloc(&pev
->pool
, sizeof(*zv
));
4116 if (!zv
) return PEV_ERROR(pev
, "set_value: out of memory");
4119 zv
->elt
.name
= pool_strdup(&pev
->pool
, name
);
4120 hash_table_add(&pev
->values
, &zv
->elt
);
4125 /* execute a binary operand from the two top most values on the stack.
4126 * puts result on top of the stack */
4127 static BOOL
pev_binop(struct pevaluator
* pev
, char op
)
4129 char res
[PEV_MAX_LEN
];
4130 DWORD_PTR v1
, v2
, c
;
4132 if (!pev_pop_val(pev
, &v1
) || !pev_pop_val(pev
, &v2
)) return FALSE
;
4135 case '+': c
= v1
+ v2
; break;
4136 case '-': c
= v1
- v2
; break;
4137 case '*': c
= v1
* v2
; break;
4138 case '/': c
= v1
/ v2
; break;
4139 case '%': c
= v1
% v2
; break;
4140 default: return PEV_ERROR1(pev
, "binop: unknown op (%c)", op
);
4142 snprintf(res
, sizeof(res
), "%Id", c
);
4147 /* pops top most operand, dereference it, on pushes the result on top of the stack */
4148 static BOOL
pev_deref(struct pevaluator
* pev
)
4150 char res
[PEV_MAX_LEN
];
4151 DWORD_PTR v1
, v2
= 0;
4153 if (!pev_pop_val(pev
, &v1
)) return FALSE
;
4154 if (!sw_read_mem(pev
->csw
, v1
, &v2
, pev
->csw
->cpu
->word_size
))
4155 return PEV_ERROR1(pev
, "deref: cannot read mem at %Ix\n", v1
);
4156 snprintf(res
, sizeof(res
), "%Id", v2
);
4161 /* assign value to variable (from two top most operands) */
4162 static BOOL
pev_assign(struct pevaluator
* pev
)
4164 char p2
[PEV_MAX_LEN
];
4167 if (!pev_pop_val(pev
, &v1
) || !pev_pop(pev
, p2
)) return FALSE
;
4168 if (p2
[0] != '$') return PEV_ERROR1(pev
, "assign: %s isn't a variable", p2
);
4169 pev_set_value(pev
, p2
, v1
);
4174 /* initializes the postfix evaluator */
4175 static void pev_init(struct pevaluator
* pev
, struct cpu_stack_walk
* csw
,
4176 PDB_FPO_DATA
* fpoext
, struct pdb_cmd_pair
* cpair
)
4179 pool_init(&pev
->pool
, 512);
4180 vector_init(&pev
->stack
, sizeof(char*), 8);
4182 hash_table_init(&pev
->pool
, &pev
->values
, 8);
4183 pev
->error
[0] = '\0';
4184 for (; cpair
->name
; cpair
++)
4185 pev_set_value(pev
, cpair
->name
, *cpair
->pvalue
);
4186 pev_set_value(pev
, ".raSearchStart", fpoext
->start
);
4187 pev_set_value(pev
, ".cbLocals", fpoext
->locals_size
);
4188 pev_set_value(pev
, ".cbParams", fpoext
->params_size
);
4189 pev_set_value(pev
, ".cbSavedRegs", fpoext
->savedregs_size
);
4192 static BOOL
pev_free(struct pevaluator
* pev
, struct pdb_cmd_pair
* cpair
)
4196 if (cpair
) for (; cpair
->name
; cpair
++)
4198 if (pev_get_val(pev
, cpair
->name
, &val
))
4199 *cpair
->pvalue
= val
;
4201 pool_destroy(&pev
->pool
);
4205 static BOOL
pdb_parse_cmd_string(struct cpu_stack_walk
* csw
, PDB_FPO_DATA
* fpoext
,
4206 const char* cmd
, struct pdb_cmd_pair
* cpair
)
4208 char token
[PEV_MAX_LEN
];
4212 struct pevaluator pev
;
4214 if (!cmd
) return FALSE
;
4215 pev_init(&pev
, csw
, fpoext
, cpair
);
4216 for (ptr
= cmd
; !over
; ptr
++)
4218 if (*ptr
== ' ' || (over
= *ptr
== '\0'))
4222 if (!strcmp(token
, "+") || !strcmp(token
, "-") || !strcmp(token
, "*") ||
4223 !strcmp(token
, "/") || !strcmp(token
, "%"))
4225 if (!pev_binop(&pev
, token
[0])) goto done
;
4227 else if (!strcmp(token
, "^"))
4229 if (!pev_deref(&pev
)) goto done
;
4231 else if (!strcmp(token
, "="))
4233 if (!pev_assign(&pev
)) goto done
;
4237 if (!pev_push(&pev
, token
)) goto done
;
4243 if (ptok
- token
>= PEV_MAX_LEN
- 1)
4245 PEV_ERROR1(&pev
, "parse: token too long (%s)", ptr
- (ptok
- token
));
4251 pev_free(&pev
, cpair
);
4254 FIXME("Couldn't evaluate %s => %s\n", wine_dbgstr_a(cmd
), pev
.error
);
4255 pev_free(&pev
, NULL
);
4259 BOOL
pdb_virtual_unwind(struct cpu_stack_walk
*csw
, DWORD_PTR ip
,
4260 union ctx
*context
, struct pdb_cmd_pair
*cpair
)
4262 struct module_pair pair
;
4263 struct pdb_module_info
* pdb_info
;
4264 PDB_FPO_DATA
* fpoext
;
4266 PDB_STRING_TABLE
* strbase
;
4269 if (!module_init_pair(&pair
, csw
->hProcess
, ip
)) return FALSE
;
4270 if (!pair
.effective
->format_info
[DFI_PDB
]) return FALSE
;
4271 pdb_info
= pair
.effective
->format_info
[DFI_PDB
]->u
.pdb_info
;
4272 TRACE("searching %Ix => %Ix\n", ip
, ip
- (DWORD_PTR
)pair
.effective
->module
.BaseOfImage
);
4273 ip
-= (DWORD_PTR
)pair
.effective
->module
.BaseOfImage
;
4275 strbase
= pdb_read_strings(&pdb_info
->pdb_files
[0]);
4276 if (!strbase
) return FALSE
;
4277 fpoext
= pdb_read_stream(&pdb_info
->pdb_files
[0], pdb_info
->pdb_files
[0].fpoext_stream
);
4278 size
= pdb_get_stream_size(&pdb_info
->pdb_files
[0], pdb_info
->pdb_files
[0].fpoext_stream
);
4279 if (fpoext
&& (size
% sizeof(*fpoext
)) == 0)
4281 size
/= sizeof(*fpoext
);
4282 for (i
= 0; i
< size
; i
++)
4284 if (fpoext
[i
].start
<= ip
&& ip
< fpoext
[i
].start
+ fpoext
[i
].func_size
)
4286 TRACE("\t%08x %08x %8x %8x %4x %4x %4x %08x %s\n",
4287 fpoext
[i
].start
, fpoext
[i
].func_size
, fpoext
[i
].locals_size
,
4288 fpoext
[i
].params_size
, fpoext
[i
].maxstack_size
, fpoext
[i
].prolog_size
,
4289 fpoext
[i
].savedregs_size
, fpoext
[i
].flags
,
4290 wine_dbgstr_a(pdb_get_string_table_entry(strbase
, fpoext
[i
].str_offset
)));
4291 ret
= pdb_parse_cmd_string(csw
, &fpoext
[i
],
4292 pdb_get_string_table_entry(strbase
, fpoext
[i
].str_offset
),
4305 /*========================================================================
4306 * Process CodeView debug information.
4309 #define MAKESIG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
4310 #define CODEVIEW_NB09_SIG MAKESIG('N','B','0','9')
4311 #define CODEVIEW_NB10_SIG MAKESIG('N','B','1','0')
4312 #define CODEVIEW_NB11_SIG MAKESIG('N','B','1','1')
4313 #define CODEVIEW_RSDS_SIG MAKESIG('R','S','D','S')
4315 static BOOL
codeview_process_info(const struct process
* pcs
,
4316 const struct msc_debug_info
* msc_dbg
)
4318 const DWORD
* signature
= (const DWORD
*)msc_dbg
->root
;
4320 struct pdb_lookup pdb_lookup
;
4322 TRACE("Processing signature %.4s\n", (const char*)signature
);
4326 case CODEVIEW_NB09_SIG
:
4327 case CODEVIEW_NB11_SIG
:
4329 const OMFSignature
* cv
= (const OMFSignature
*)msc_dbg
->root
;
4330 const OMFDirHeader
* hdr
= (const OMFDirHeader
*)(msc_dbg
->root
+ cv
->filepos
);
4331 const OMFDirEntry
* ent
;
4332 const OMFDirEntry
* prev
;
4333 const OMFDirEntry
* next
;
4336 codeview_init_basic_types(msc_dbg
->module
);
4338 for (i
= 0; i
< hdr
->cDir
; i
++)
4340 ent
= (const OMFDirEntry
*)((const BYTE
*)hdr
+ hdr
->cbDirHeader
+ i
* hdr
->cbDirEntry
);
4341 if (ent
->SubSection
== sstGlobalTypes
)
4343 const OMFGlobalTypes
* types
;
4344 struct codeview_type_parse ctp
;
4346 types
= (const OMFGlobalTypes
*)(msc_dbg
->root
+ ent
->lfo
);
4347 ctp
.module
= msc_dbg
->module
;
4348 ctp
.offset
= (const DWORD
*)(types
+ 1);
4349 memset(&ctp
.header
, 0, sizeof(ctp
.header
));
4350 ctp
.header
.first_index
= T_FIRSTDEFINABLETYPE
;
4351 ctp
.header
.last_index
= ctp
.header
.first_index
+ types
->cTypes
;
4352 ctp
.table
= (const BYTE
*)(ctp
.offset
+ types
->cTypes
);
4354 cv_current_module
= &cv_zmodules
[0];
4355 if (cv_current_module
->allowed
) FIXME("Already allowed??\n");
4356 cv_current_module
->allowed
= TRUE
;
4358 codeview_parse_type_table(&ctp
);
4363 ent
= (const OMFDirEntry
*)((const BYTE
*)hdr
+ hdr
->cbDirHeader
);
4364 for (i
= 0; i
< hdr
->cDir
; i
++, ent
= next
)
4366 next
= (i
== hdr
->cDir
-1) ? NULL
:
4367 (const OMFDirEntry
*)((const BYTE
*)ent
+ hdr
->cbDirEntry
);
4368 prev
= (i
== 0) ? NULL
:
4369 (const OMFDirEntry
*)((const BYTE
*)ent
- hdr
->cbDirEntry
);
4371 if (ent
->SubSection
== sstAlignSym
)
4373 codeview_snarf(msc_dbg
, msc_dbg
->root
+ ent
->lfo
, sizeof(DWORD
), ent
->cb
, NULL
, NULL
);
4376 * Check the next and previous entry. If either is a
4377 * sstSrcModule, it contains the line number info for
4380 * FIXME: This is not a general solution!
4382 if (next
&& next
->iMod
== ent
->iMod
&& next
->SubSection
== sstSrcModule
)
4383 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ next
->lfo
,
4386 if (prev
&& prev
->iMod
== ent
->iMod
&& prev
->SubSection
== sstSrcModule
)
4387 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ prev
->lfo
,
4393 msc_dbg
->module
->module
.SymType
= SymCv
;
4394 /* FIXME: we could have a finer grain here */
4395 msc_dbg
->module
->module
.LineNumbers
= TRUE
;
4396 msc_dbg
->module
->module
.GlobalSymbols
= TRUE
;
4397 msc_dbg
->module
->module
.TypeInfo
= TRUE
;
4398 msc_dbg
->module
->module
.SourceIndexed
= TRUE
;
4399 msc_dbg
->module
->module
.Publics
= TRUE
;
4400 codeview_clear_type_table();
4405 case CODEVIEW_NB10_SIG
:
4407 const CODEVIEW_PDB_DATA
* pdb
= (const CODEVIEW_PDB_DATA
*)msc_dbg
->root
;
4408 pdb_lookup
.filename
= pdb
->name
;
4409 pdb_lookup
.kind
= PDB_JG
;
4410 pdb_lookup
.timestamp
= pdb
->timestamp
;
4411 pdb_lookup
.age
= pdb
->age
;
4412 ret
= pdb_process_file(pcs
, msc_dbg
, &pdb_lookup
);
4415 case CODEVIEW_RSDS_SIG
:
4417 const OMFSignatureRSDS
* rsds
= (const OMFSignatureRSDS
*)msc_dbg
->root
;
4419 TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
4420 wine_dbgstr_guid(&rsds
->guid
), rsds
->age
, rsds
->name
);
4421 pdb_lookup
.filename
= rsds
->name
;
4422 pdb_lookup
.kind
= PDB_DS
;
4423 pdb_lookup
.guid
= rsds
->guid
;
4424 pdb_lookup
.age
= rsds
->age
;
4425 ret
= pdb_process_file(pcs
, msc_dbg
, &pdb_lookup
);
4429 ERR("Unknown CODEVIEW signature %08lx in module %s\n",
4430 *signature
, debugstr_w(msc_dbg
->module
->modulename
));
4435 msc_dbg
->module
->module
.CVSig
= *signature
;
4436 memcpy(msc_dbg
->module
->module
.CVData
, msc_dbg
->root
,
4437 sizeof(msc_dbg
->module
->module
.CVData
));
4442 /*========================================================================
4443 * Process debug directory.
4445 BOOL
pe_load_debug_directory(const struct process
* pcs
, struct module
* module
,
4446 const BYTE
* mapping
,
4447 const IMAGE_SECTION_HEADER
* sectp
, DWORD nsect
,
4448 const IMAGE_DEBUG_DIRECTORY
* dbg
, int nDbg
)
4452 struct msc_debug_info msc_dbg
;
4454 msc_dbg
.module
= module
;
4455 msc_dbg
.nsect
= nsect
;
4456 msc_dbg
.sectp
= sectp
;
4458 msc_dbg
.omapp
= NULL
;
4464 /* First, watch out for OMAP data */
4465 for (i
= 0; i
< nDbg
; i
++)
4467 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_OMAP_FROM_SRC
)
4469 msc_dbg
.nomap
= dbg
[i
].SizeOfData
/ sizeof(OMAP
);
4470 msc_dbg
.omapp
= (const OMAP
*)(mapping
+ dbg
[i
].PointerToRawData
);
4475 /* Now, try to parse CodeView debug info */
4476 for (i
= 0; i
< nDbg
; i
++)
4478 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
4480 msc_dbg
.root
= mapping
+ dbg
[i
].PointerToRawData
;
4481 if ((ret
= codeview_process_info(pcs
, &msc_dbg
))) goto done
;
4485 /* If not found, try to parse COFF debug info */
4486 for (i
= 0; i
< nDbg
; i
++)
4488 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_COFF
)
4490 msc_dbg
.root
= mapping
+ dbg
[i
].PointerToRawData
;
4491 if ((ret
= coff_process_info(&msc_dbg
))) goto done
;
4495 /* FIXME: this should be supported... this is the debug information for
4496 * functions compiled without a frame pointer (FPO = frame pointer omission)
4497 * the associated data helps finding out the relevant information
4499 for (i
= 0; i
< nDbg
; i
++)
4500 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_FPO
)
4501 FIXME("This guy has FPO information\n");
4505 #define FRAME_TRAP 1
4508 typedef struct _FPO_DATA
4510 DWORD ulOffStart
; /* offset 1st byte of function code */
4511 DWORD cbProcSize
; /* # bytes in function */
4512 DWORD cdwLocals
; /* # bytes in locals/4 */
4513 WORD cdwParams
; /* # bytes in params/4 */
4515 WORD cbProlog
: 8; /* # bytes in prolog */
4516 WORD cbRegs
: 3; /* # regs saved */
4517 WORD fHasSEH
: 1; /* TRUE if SEH in func */
4518 WORD fUseBP
: 1; /* TRUE if EBP has been allocated */
4519 WORD reserved
: 1; /* reserved for future use */
4520 WORD cbFrame
: 2; /* frame type */
4527 ERR("Got a page fault while loading symbols\n");
4534 DWORD
msc_get_file_indexinfo(void* image
, const IMAGE_DEBUG_DIRECTORY
* debug_dir
, DWORD num_dir
, SYMSRV_INDEX_INFOW
* info
)
4537 unsigned num_misc_records
= 0;
4540 memset(&info
->guid
, 0, sizeof(info
->guid
));
4542 info
->dbgfile
[0] = L
'\0';
4543 info
->pdbfile
[0] = L
'\0';
4545 for (i
= 0; i
< num_dir
; i
++)
4547 if (debug_dir
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
4549 const CODEVIEW_PDB_DATA
* data
= (const CODEVIEW_PDB_DATA
*)((char*)image
+ debug_dir
[i
].PointerToRawData
);
4550 const OMFSignatureRSDS
* rsds_data
= (const OMFSignatureRSDS
*)data
;
4551 if (!memcmp(data
->Signature
, "NB10", 4))
4553 info
->age
= data
->age
;
4554 info
->sig
= data
->timestamp
;
4555 MultiByteToWideChar(CP_ACP
, 0, data
->name
, -1, info
->pdbfile
, ARRAY_SIZE(info
->pdbfile
));
4557 if (!memcmp(rsds_data
->Signature
, "RSDS", 4))
4559 info
->age
= rsds_data
->age
;
4560 info
->guid
= rsds_data
->guid
;
4561 MultiByteToWideChar(CP_ACP
, 0, rsds_data
->name
, -1, info
->pdbfile
, ARRAY_SIZE(info
->pdbfile
));
4564 else if (debug_dir
[i
].Type
== IMAGE_DEBUG_TYPE_MISC
&& info
->stripped
)
4566 const IMAGE_DEBUG_MISC
* misc
= (const IMAGE_DEBUG_MISC
*)
4567 ((const char*)image
+ debug_dir
[i
].PointerToRawData
);
4569 wcscpy(info
->dbgfile
, (WCHAR
*)misc
->Data
);
4571 MultiByteToWideChar(CP_ACP
, 0, (const char*)misc
->Data
, -1, info
->dbgfile
, ARRAY_SIZE(info
->dbgfile
));
4575 return info
->stripped
&& !num_misc_records
? ERROR_BAD_EXE_FORMAT
: ERROR_SUCCESS
;