2 * File msc.c - read VC++ debug information from COFF and eventually
5 * Copyright (C) 1996, Eric Youngdale.
6 * Copyright (C) 1999-2000, Ulrich Weigand.
7 * Copyright (C) 2004-2009, Eric Pouech.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 * Note - this handles reading debug information for 32 bit applications
26 * that run under Windows-NT for example. I doubt that this would work well
27 * for 16 bit applications, but I don't think it really matters since the
28 * file format is different, and we should never get in here in such cases.
31 * Get 16 bit CV stuff working.
32 * Add symbol size to internal symbol table.
35 #define NONAMELESSUNION
47 #include "wine/exception.h"
48 #include "wine/debug.h"
49 #include "dbghelp_private.h"
50 #include "wine/mscvpdb.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_msc
);
54 struct pdb_stream_name
66 struct pdb_stream_name
* stream_dict
;
67 unsigned fpoext_stream
;
73 struct PDB_JG_TOC
* toc
;
78 struct PDB_DS_TOC
* toc
;
83 /* FIXME: don't make it static */
84 #define CV_MAX_MODULES 32
85 struct pdb_module_info
87 unsigned used_subfiles
;
88 struct pdb_file_info pdb_files
[CV_MAX_MODULES
];
91 #define loc_cv_local_range (loc_user + 0) /* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */
93 struct cv_module_snarf
95 const struct codeview_type_parse
* ipi_ctp
;
96 const struct CV_DebugSSubsectionHeader_t
* dbgsubsect
;
97 unsigned dbgsubsect_size
;
102 /*========================================================================
103 * Debug file access helper routines
106 static void dump(const void* ptr
, unsigned len
)
110 const char* hexof
= "0123456789abcdef";
113 for (i
= 0; i
< len
; i
+= 16)
115 sprintf(msg
, "%08x: ", i
);
116 memset(msg
+ 10, ' ', 3 * 16 + 1 + 16);
117 for (j
= 0; j
< min(16, len
- i
); j
++)
119 msg
[10 + 3 * j
+ 0] = hexof
[x
[i
+ j
] >> 4];
120 msg
[10 + 3 * j
+ 1] = hexof
[x
[i
+ j
] & 15];
121 msg
[10 + 3 * j
+ 2] = ' ';
122 msg
[10 + 3 * 16 + 1 + j
] = (x
[i
+ j
] >= 0x20 && x
[i
+ j
] < 0x7f) ?
125 msg
[10 + 3 * 16] = ' ';
126 msg
[10 + 3 * 16 + 1 + 16] = '\0';
131 /*========================================================================
132 * Process CodeView type information.
135 #define MAX_BUILTIN_TYPES 0x06FF
136 #define FIRST_DEFINABLE_TYPE 0x1000
138 static struct symt
* cv_basic_types
[MAX_BUILTIN_TYPES
];
140 struct cv_defined_module
143 unsigned int num_defined_types
;
144 struct symt
** defined_types
;
146 /* FIXME: don't make it static */
147 #define CV_MAX_MODULES 32
148 static struct cv_defined_module cv_zmodules
[CV_MAX_MODULES
];
149 static struct cv_defined_module
*cv_current_module
;
151 static void codeview_init_basic_types(struct module
* module
)
153 unsigned ptrsz
= module
->cpu
->word_size
;
156 * These are the common builtin types that are used by VC++.
158 cv_basic_types
[T_NOTYPE
] = NULL
;
159 cv_basic_types
[T_ABS
] = NULL
;
160 cv_basic_types
[T_VOID
] = &symt_get_basic(btVoid
, 0)->symt
; /* void */
161 cv_basic_types
[T_CHAR
] = &symt_get_basic(btInt
, 1)->symt
; /* signed char (and char in C) */
162 cv_basic_types
[T_SHORT
] = &symt_get_basic(btInt
, 2)->symt
; /* short int */
163 cv_basic_types
[T_LONG
] = &symt_get_basic(btLong
, 4)->symt
; /* long int */
164 cv_basic_types
[T_QUAD
] = &symt_get_basic(btInt
, 8)->symt
; /* long long int */
165 cv_basic_types
[T_UCHAR
] = &symt_get_basic(btUInt
, 1)->symt
; /* unsigned char */
166 cv_basic_types
[T_USHORT
] = &symt_get_basic(btUInt
, 2)->symt
; /* unsigned short */
167 cv_basic_types
[T_ULONG
] = &symt_get_basic(btULong
, 4)->symt
; /* unsigned long */
168 cv_basic_types
[T_UQUAD
] = &symt_get_basic(btUInt
, 8)->symt
; /* unsigned long long */
169 cv_basic_types
[T_BOOL08
] = &symt_get_basic(btBool
, 1)->symt
; /* BOOL08 */
170 cv_basic_types
[T_BOOL16
] = &symt_get_basic(btBool
, 2)->symt
; /* BOOL16 */
171 cv_basic_types
[T_BOOL32
] = &symt_get_basic(btBool
, 4)->symt
; /* BOOL32 */
172 cv_basic_types
[T_BOOL64
] = &symt_get_basic(btBool
, 8)->symt
; /* BOOL64 */
173 cv_basic_types
[T_REAL32
] = &symt_get_basic(btFloat
, 4)->symt
; /* float */
174 cv_basic_types
[T_REAL64
] = &symt_get_basic(btFloat
, 8)->symt
; /* double */
175 cv_basic_types
[T_REAL80
] = &symt_get_basic(btFloat
, 10)->symt
; /* long double */
176 cv_basic_types
[T_RCHAR
] = &symt_get_basic(btChar
, 1)->symt
; /* "real" char (char in C++) */
177 cv_basic_types
[T_WCHAR
] = &symt_get_basic(btWChar
, 2)->symt
; /* char8_t */
178 cv_basic_types
[T_CHAR16
] = &symt_get_basic(btChar16
, 2)->symt
; /* char16_t */
179 cv_basic_types
[T_CHAR32
] = &symt_get_basic(btChar32
, 4)->symt
; /* char32_t */
180 cv_basic_types
[T_CHAR8
] = &symt_get_basic(btChar8
, 1)->symt
; /* char8_t */
181 cv_basic_types
[T_INT2
] = &symt_get_basic(btInt
, 2)->symt
; /* INT2 */
182 cv_basic_types
[T_UINT2
] = &symt_get_basic(btUInt
, 2)->symt
; /* UINT2 */
183 cv_basic_types
[T_INT4
] = &symt_get_basic(btInt
, 4)->symt
; /* INT4 */
184 cv_basic_types
[T_UINT4
] = &symt_get_basic(btUInt
, 4)->symt
; /* UINT4 */
185 cv_basic_types
[T_INT8
] = &symt_get_basic(btInt
, 8)->symt
; /* INT8 */
186 cv_basic_types
[T_UINT8
] = &symt_get_basic(btUInt
, 8)->symt
; /* UINT8 */
187 cv_basic_types
[T_HRESULT
]= &symt_get_basic(btUInt
, 4)->symt
; /* HRESULT */
189 cv_basic_types
[T_32PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], 4)->symt
;
190 cv_basic_types
[T_32PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], 4)->symt
;
191 cv_basic_types
[T_32PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], 4)->symt
;
192 cv_basic_types
[T_32PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], 4)->symt
;
193 cv_basic_types
[T_32PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], 4)->symt
;
194 cv_basic_types
[T_32PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], 4)->symt
;
195 cv_basic_types
[T_32PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], 4)->symt
;
196 cv_basic_types
[T_32PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], 4)->symt
;
197 cv_basic_types
[T_32PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], 4)->symt
;
198 cv_basic_types
[T_32PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], 4)->symt
;
199 cv_basic_types
[T_32PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], 4)->symt
;
200 cv_basic_types
[T_32PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], 4)->symt
;
201 cv_basic_types
[T_32PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], 4)->symt
;
202 cv_basic_types
[T_32PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], 4)->symt
;
203 cv_basic_types
[T_32PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], 4)->symt
;
204 cv_basic_types
[T_32PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], 4)->symt
;
205 cv_basic_types
[T_32PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], 4)->symt
;
206 cv_basic_types
[T_32PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], 4)->symt
;
207 cv_basic_types
[T_32PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], 4)->symt
;
208 cv_basic_types
[T_32PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], 4)->symt
;
209 cv_basic_types
[T_32PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], 4)->symt
;
210 cv_basic_types
[T_32PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], 4)->symt
;
211 cv_basic_types
[T_32PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], 4)->symt
;
212 cv_basic_types
[T_32PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], 4)->symt
;
213 cv_basic_types
[T_32PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], 4)->symt
;
214 cv_basic_types
[T_32PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], 4)->symt
;
215 cv_basic_types
[T_32PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], 4)->symt
;
216 cv_basic_types
[T_32PHRESULT
]= &symt_new_pointer(module
, cv_basic_types
[T_HRESULT
], 4)->symt
;
218 cv_basic_types
[T_64PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], 8)->symt
;
219 cv_basic_types
[T_64PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], 8)->symt
;
220 cv_basic_types
[T_64PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], 8)->symt
;
221 cv_basic_types
[T_64PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], 8)->symt
;
222 cv_basic_types
[T_64PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], 8)->symt
;
223 cv_basic_types
[T_64PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], 8)->symt
;
224 cv_basic_types
[T_64PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], 8)->symt
;
225 cv_basic_types
[T_64PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], 8)->symt
;
226 cv_basic_types
[T_64PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], 8)->symt
;
227 cv_basic_types
[T_64PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], 8)->symt
;
228 cv_basic_types
[T_64PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], 8)->symt
;
229 cv_basic_types
[T_64PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], 8)->symt
;
230 cv_basic_types
[T_64PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], 8)->symt
;
231 cv_basic_types
[T_64PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], 8)->symt
;
232 cv_basic_types
[T_64PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], 8)->symt
;
233 cv_basic_types
[T_64PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], 8)->symt
;
234 cv_basic_types
[T_64PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], 8)->symt
;
235 cv_basic_types
[T_64PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], 8)->symt
;
236 cv_basic_types
[T_64PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], 8)->symt
;
237 cv_basic_types
[T_64PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], 8)->symt
;
238 cv_basic_types
[T_64PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], 8)->symt
;
239 cv_basic_types
[T_64PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], 8)->symt
;
240 cv_basic_types
[T_64PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], 8)->symt
;
241 cv_basic_types
[T_64PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], 8)->symt
;
242 cv_basic_types
[T_64PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], 8)->symt
;
243 cv_basic_types
[T_64PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], 8)->symt
;
244 cv_basic_types
[T_64PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], 8)->symt
;
245 cv_basic_types
[T_64PHRESULT
]= &symt_new_pointer(module
, cv_basic_types
[T_HRESULT
], 8)->symt
;
247 cv_basic_types
[T_PVOID
] = &symt_new_pointer(module
, cv_basic_types
[T_VOID
], ptrsz
)->symt
;
248 cv_basic_types
[T_PCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR
], ptrsz
)->symt
;
249 cv_basic_types
[T_PSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_SHORT
], ptrsz
)->symt
;
250 cv_basic_types
[T_PLONG
] = &symt_new_pointer(module
, cv_basic_types
[T_LONG
], ptrsz
)->symt
;
251 cv_basic_types
[T_PQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_QUAD
], ptrsz
)->symt
;
252 cv_basic_types
[T_PUCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_UCHAR
], ptrsz
)->symt
;
253 cv_basic_types
[T_PUSHORT
] = &symt_new_pointer(module
, cv_basic_types
[T_USHORT
], ptrsz
)->symt
;
254 cv_basic_types
[T_PULONG
] = &symt_new_pointer(module
, cv_basic_types
[T_ULONG
], ptrsz
)->symt
;
255 cv_basic_types
[T_PUQUAD
] = &symt_new_pointer(module
, cv_basic_types
[T_UQUAD
], ptrsz
)->symt
;
256 cv_basic_types
[T_PBOOL08
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL08
], ptrsz
)->symt
;
257 cv_basic_types
[T_PBOOL16
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL16
], ptrsz
)->symt
;
258 cv_basic_types
[T_PBOOL32
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL32
], ptrsz
)->symt
;
259 cv_basic_types
[T_PBOOL64
] = &symt_new_pointer(module
, cv_basic_types
[T_BOOL64
], ptrsz
)->symt
;
260 cv_basic_types
[T_PREAL32
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL32
], ptrsz
)->symt
;
261 cv_basic_types
[T_PREAL64
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL64
], ptrsz
)->symt
;
262 cv_basic_types
[T_PREAL80
] = &symt_new_pointer(module
, cv_basic_types
[T_REAL80
], ptrsz
)->symt
;
263 cv_basic_types
[T_PRCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_RCHAR
], ptrsz
)->symt
;
264 cv_basic_types
[T_PWCHAR
] = &symt_new_pointer(module
, cv_basic_types
[T_WCHAR
], ptrsz
)->symt
;
265 cv_basic_types
[T_PCHAR16
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR16
], ptrsz
)->symt
;
266 cv_basic_types
[T_PCHAR32
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR32
], ptrsz
)->symt
;
267 cv_basic_types
[T_PCHAR8
] = &symt_new_pointer(module
, cv_basic_types
[T_CHAR8
], ptrsz
)->symt
;
268 cv_basic_types
[T_PINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_INT2
], ptrsz
)->symt
;
269 cv_basic_types
[T_PUINT2
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT2
], ptrsz
)->symt
;
270 cv_basic_types
[T_PINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_INT4
], ptrsz
)->symt
;
271 cv_basic_types
[T_PUINT4
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT4
], ptrsz
)->symt
;
272 cv_basic_types
[T_PINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_INT8
], ptrsz
)->symt
;
273 cv_basic_types
[T_PUINT8
] = &symt_new_pointer(module
, cv_basic_types
[T_UINT8
], ptrsz
)->symt
;
276 static int leaf_as_variant(VARIANT
* v
, const unsigned short int* leaf
)
278 unsigned short int type
= *leaf
++;
281 if (type
< LF_NUMERIC
)
293 V_I1(v
) = *(const char*)leaf
;
299 V_I2(v
) = *(const short*)leaf
;
311 V_I4(v
) = *(const int*)leaf
;
317 V_UI4(v
) = *(const unsigned int*)leaf
;
323 V_I8(v
) = *(const long long int*)leaf
;
329 V_UI8(v
) = *(const long long unsigned int*)leaf
;
335 V_R4(v
) = *(const float*)leaf
;
339 FIXME("Unsupported numeric leaf type %04x\n", type
);
341 V_VT(v
) = VT_EMPTY
; /* FIXME */
347 V_R8(v
) = *(const double*)leaf
;
351 FIXME("Unsupported numeric leaf type %04x\n", type
);
353 V_VT(v
) = VT_EMPTY
; /* FIXME */
357 FIXME("Unsupported numeric leaf type %04x\n", type
);
359 V_VT(v
) = VT_EMPTY
; /* FIXME */
363 FIXME("Unsupported numeric leaf type %04x\n", type
);
365 V_VT(v
) = VT_EMPTY
; /* FIXME */
369 FIXME("Unsupported numeric leaf type %04x\n", type
);
371 V_VT(v
) = VT_EMPTY
; /* FIXME */
375 FIXME("Unsupported numeric leaf type %04x\n", type
);
380 FIXME("Unsupported numeric leaf type %04x\n", type
);
382 V_VT(v
) = VT_EMPTY
; /* FIXME */
386 FIXME("Unsupported numeric leaf type %04x\n", type
);
388 V_VT(v
) = VT_EMPTY
; /* FIXME */
392 FIXME("Unknown numeric leaf type %04x\n", type
);
393 V_VT(v
) = VT_EMPTY
; /* FIXME */
401 static int numeric_leaf(int* value
, const unsigned short int* leaf
)
403 unsigned short int type
= *leaf
++;
406 if (type
< LF_NUMERIC
)
416 *value
= *(const char*)leaf
;
421 *value
= *(const short*)leaf
;
431 *value
= *(const int*)leaf
;
436 *value
= *(const unsigned int*)leaf
;
441 FIXME("Unsupported numeric leaf type %04x\n", type
);
443 *value
= 0; /* FIXME */
447 FIXME("Unsupported numeric leaf type %04x\n", type
);
449 *value
= 0; /* FIXME */
453 FIXME("Unsupported numeric leaf type %04x\n", type
);
455 *value
= 0; /* FIXME */
459 FIXME("Unsupported numeric leaf type %04x\n", type
);
461 *value
= 0; /* FIXME */
465 FIXME("Unsupported numeric leaf type %04x\n", type
);
467 *value
= 0; /* FIXME */
471 FIXME("Unsupported numeric leaf type %04x\n", type
);
473 *value
= 0; /* FIXME */
477 FIXME("Unsupported numeric leaf type %04x\n", type
);
479 *value
= 0; /* FIXME */
483 FIXME("Unsupported numeric leaf type %04x\n", type
);
485 *value
= 0; /* FIXME */
489 FIXME("Unsupported numeric leaf type %04x\n", type
);
491 *value
= 0; /* FIXME */
495 FIXME("Unsupported numeric leaf type %04x\n", type
);
497 *value
= 0; /* FIXME */
501 FIXME("Unsupported numeric leaf type %04x\n", type
);
503 *value
= 0; /* FIXME */
507 FIXME("Unknown numeric leaf type %04x\n", type
);
516 /* convert a pascal string (as stored in debug information) into
517 * a C string (null terminated).
519 static const char* terminate_string(const struct p_string
* p_name
)
521 static char symname
[256];
523 memcpy(symname
, p_name
->name
, p_name
->namelen
);
524 symname
[p_name
->namelen
] = '\0';
526 return (!*symname
|| strcmp(symname
, "__unnamed") == 0) ? NULL
: symname
;
529 static struct symt
* codeview_get_type(unsigned int typeno
, BOOL quiet
)
531 struct symt
* symt
= NULL
;
534 * Convert Codeview type numbers into something we can grok internally.
535 * Numbers < FIRST_DEFINABLE_TYPE are all fixed builtin types.
536 * Numbers from FIRST_DEFINABLE_TYPE and up are all user defined (structs, etc).
538 if (typeno
< FIRST_DEFINABLE_TYPE
)
540 if (typeno
< MAX_BUILTIN_TYPES
)
541 symt
= cv_basic_types
[typeno
];
545 unsigned mod_index
= typeno
>> 24;
546 unsigned mod_typeno
= typeno
& 0x00FFFFFF;
547 struct cv_defined_module
* mod
;
549 mod
= (mod_index
== 0) ? cv_current_module
: &cv_zmodules
[mod_index
];
551 if (mod_index
>= CV_MAX_MODULES
|| !mod
->allowed
)
552 FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index
, typeno
);
555 if (mod_typeno
- FIRST_DEFINABLE_TYPE
< mod
->num_defined_types
)
556 symt
= mod
->defined_types
[mod_typeno
- FIRST_DEFINABLE_TYPE
];
559 if (!quiet
&& !symt
&& typeno
) FIXME("Returning NULL symt for type-id %x\n", typeno
);
563 struct codeview_type_parse
565 struct module
* module
;
571 static inline const void* codeview_jump_to_type(const struct codeview_type_parse
* ctp
, DWORD idx
)
573 if (idx
< FIRST_DEFINABLE_TYPE
) return NULL
;
574 idx
-= FIRST_DEFINABLE_TYPE
;
575 return (idx
>= ctp
->num
) ? NULL
: (ctp
->table
+ ctp
->offset
[idx
]);
578 static int codeview_add_type(unsigned int typeno
, struct symt
* dt
)
580 if (typeno
< FIRST_DEFINABLE_TYPE
)
581 FIXME("What the heck\n");
582 if (!cv_current_module
)
584 FIXME("Adding %x to non allowed module\n", typeno
);
587 if ((typeno
>> 24) != 0)
588 FIXME("No module index while inserting type-id assumption is wrong %x\n",
590 if (typeno
- FIRST_DEFINABLE_TYPE
>= cv_current_module
->num_defined_types
)
592 if (cv_current_module
->defined_types
)
594 cv_current_module
->num_defined_types
= max( cv_current_module
->num_defined_types
* 2,
595 typeno
- FIRST_DEFINABLE_TYPE
+ 1 );
596 cv_current_module
->defined_types
= HeapReAlloc(GetProcessHeap(),
597 HEAP_ZERO_MEMORY
, cv_current_module
->defined_types
,
598 cv_current_module
->num_defined_types
* sizeof(struct symt
*));
602 cv_current_module
->num_defined_types
= max( 256, typeno
- FIRST_DEFINABLE_TYPE
+ 1 );
603 cv_current_module
->defined_types
= HeapAlloc(GetProcessHeap(),
605 cv_current_module
->num_defined_types
* sizeof(struct symt
*));
607 if (cv_current_module
->defined_types
== NULL
) return FALSE
;
609 if (cv_current_module
->defined_types
[typeno
- FIRST_DEFINABLE_TYPE
])
611 if (cv_current_module
->defined_types
[typeno
- FIRST_DEFINABLE_TYPE
] != dt
)
612 FIXME("Overwriting at %x\n", typeno
);
614 cv_current_module
->defined_types
[typeno
- FIRST_DEFINABLE_TYPE
] = dt
;
618 static void codeview_clear_type_table(void)
622 for (i
= 0; i
< CV_MAX_MODULES
; i
++)
624 if (cv_zmodules
[i
].allowed
)
625 HeapFree(GetProcessHeap(), 0, cv_zmodules
[i
].defined_types
);
626 cv_zmodules
[i
].allowed
= FALSE
;
627 cv_zmodules
[i
].defined_types
= NULL
;
628 cv_zmodules
[i
].num_defined_types
= 0;
630 cv_current_module
= NULL
;
633 static struct symt
* codeview_parse_one_type(struct codeview_type_parse
* ctp
,
635 const union codeview_type
* type
, BOOL details
);
637 static void* codeview_cast_symt(struct symt
* symt
, enum SymTagEnum tag
)
639 if (symt
->tag
!= tag
)
641 FIXME("Bad tag. Expected %d, but got %d\n", tag
, symt
->tag
);
647 static struct symt
* codeview_fetch_type(struct codeview_type_parse
* ctp
,
648 unsigned typeno
, BOOL details
)
651 const union codeview_type
* p
;
653 if (!typeno
) return NULL
;
654 if ((symt
= codeview_get_type(typeno
, TRUE
))) return symt
;
656 /* forward declaration */
657 if (!(p
= codeview_jump_to_type(ctp
, typeno
)))
659 FIXME("Cannot locate type %x\n", typeno
);
662 symt
= codeview_parse_one_type(ctp
, typeno
, p
, details
);
663 if (!symt
) FIXME("Couldn't load forward type %x\n", typeno
);
667 static struct symt
* codeview_add_type_pointer(struct codeview_type_parse
* ctp
,
668 struct symt
* existing
,
669 unsigned int pointee_type
)
671 struct symt
* pointee
;
675 existing
= codeview_cast_symt(existing
, SymTagPointerType
);
678 pointee
= codeview_fetch_type(ctp
, pointee_type
, FALSE
);
679 return &symt_new_pointer(ctp
->module
, pointee
, ctp
->module
->cpu
->word_size
)->symt
;
682 static struct symt
* codeview_add_type_array(struct codeview_type_parse
* ctp
,
684 unsigned int elemtype
,
685 unsigned int indextype
,
686 unsigned int arr_len
)
688 struct symt
* elem
= codeview_fetch_type(ctp
, elemtype
, FALSE
);
689 struct symt
* index
= codeview_fetch_type(ctp
, indextype
, FALSE
);
693 if (symt_get_info(ctp
->module
, elem
, TI_GET_LENGTH
, &elem_size
) && elem_size
)
695 if (arr_len
% (DWORD
)elem_size
)
696 FIXME("array size should be a multiple of element size %u %I64u\n", arr_len
, elem_size
);
697 count
= arr_len
/ (unsigned)elem_size
;
699 return &symt_new_array(ctp
->module
, 0, count
, elem
, index
)->symt
;
702 static BOOL
codeview_add_type_enum_field_list(struct module
* module
,
703 struct symt_enum
* symt
,
704 const union codeview_reftype
* ref_type
)
706 const unsigned char* ptr
= ref_type
->fieldlist
.list
;
707 const unsigned char* last
= (const BYTE
*)ref_type
+ ref_type
->generic
.len
+ 2;
708 const union codeview_fieldtype
* type
;
712 if (*ptr
>= 0xf0) /* LF_PAD... */
718 type
= (const union codeview_fieldtype
*)ptr
;
720 switch (type
->generic
.id
)
722 case LF_ENUMERATE_V1
:
724 int value
, vlen
= numeric_leaf(&value
, &type
->enumerate_v1
.value
);
725 const struct p_string
* p_name
= (const struct p_string
*)((const unsigned char*)&type
->enumerate_v1
.value
+ vlen
);
727 symt_add_enum_element(module
, symt
, terminate_string(p_name
), value
);
728 ptr
+= 2 + 2 + vlen
+ (1 + p_name
->namelen
);
731 case LF_ENUMERATE_V3
:
733 int value
, vlen
= numeric_leaf(&value
, &type
->enumerate_v3
.value
);
734 const char* name
= (const char*)&type
->enumerate_v3
.value
+ vlen
;
736 symt_add_enum_element(module
, symt
, name
, value
);
737 ptr
+= 2 + 2 + vlen
+ (1 + strlen(name
));
742 FIXME("Unsupported type %04x in ENUM field list\n", type
->generic
.id
);
749 static void codeview_add_udt_element(struct codeview_type_parse
* ctp
,
750 struct symt_udt
* symt
, const char* name
,
751 int value
, unsigned type
)
753 struct symt
* subtype
;
754 const union codeview_reftype
*cv_type
;
756 if ((cv_type
= codeview_jump_to_type(ctp
, type
)))
758 switch (cv_type
->generic
.id
)
761 symt_add_udt_element(ctp
->module
, symt
, name
,
762 codeview_fetch_type(ctp
, cv_type
->bitfield_v1
.type
, FALSE
),
763 value
, cv_type
->bitfield_v1
.bitoff
,
764 cv_type
->bitfield_v1
.nbits
);
767 symt_add_udt_element(ctp
->module
, symt
, name
,
768 codeview_fetch_type(ctp
, cv_type
->bitfield_v2
.type
, FALSE
),
769 value
, cv_type
->bitfield_v2
.bitoff
,
770 cv_type
->bitfield_v2
.nbits
);
774 subtype
= codeview_fetch_type(ctp
, type
, FALSE
);
778 DWORD64 elem_size
= 0;
779 symt_get_info(ctp
->module
, subtype
, TI_GET_LENGTH
, &elem_size
);
780 symt_add_udt_element(ctp
->module
, symt
, name
, subtype
, value
, 0, 0);
784 static int codeview_add_type_struct_field_list(struct codeview_type_parse
* ctp
,
785 struct symt_udt
* symt
,
786 unsigned fieldlistno
)
788 const unsigned char* ptr
;
789 const unsigned char* last
;
791 const struct p_string
* p_name
;
793 const union codeview_reftype
*type_ref
;
794 const union codeview_fieldtype
* type
;
796 if (!fieldlistno
) return TRUE
;
797 type_ref
= codeview_jump_to_type(ctp
, fieldlistno
);
798 ptr
= type_ref
->fieldlist
.list
;
799 last
= (const BYTE
*)type_ref
+ type_ref
->generic
.len
+ 2;
803 if (*ptr
>= 0xf0) /* LF_PAD... */
809 type
= (const union codeview_fieldtype
*)ptr
;
811 switch (type
->generic
.id
)
814 leaf_len
= numeric_leaf(&value
, &type
->bclass_v1
.offset
);
816 /* FIXME: ignored for now */
818 ptr
+= 2 + 2 + 2 + leaf_len
;
822 leaf_len
= numeric_leaf(&value
, &type
->bclass_v2
.offset
);
824 /* FIXME: ignored for now */
826 ptr
+= 2 + 2 + 4 + leaf_len
;
832 const unsigned short int* p_vboff
;
834 leaf_len
= numeric_leaf(&value
, &type
->vbclass_v1
.vbpoff
);
835 p_vboff
= (const unsigned short int*)((const char*)&type
->vbclass_v1
.vbpoff
+ leaf_len
);
836 vplen
= numeric_leaf(&vpoff
, p_vboff
);
838 /* FIXME: ignored for now */
840 ptr
+= 2 + 2 + 2 + 2 + leaf_len
+ vplen
;
847 const unsigned short int* p_vboff
;
849 leaf_len
= numeric_leaf(&value
, &type
->vbclass_v2
.vbpoff
);
850 p_vboff
= (const unsigned short int*)((const char*)&type
->vbclass_v2
.vbpoff
+ leaf_len
);
851 vplen
= numeric_leaf(&vpoff
, p_vboff
);
853 /* FIXME: ignored for now */
855 ptr
+= 2 + 2 + 4 + 4 + leaf_len
+ vplen
;
860 leaf_len
= numeric_leaf(&value
, &type
->member_v1
.offset
);
861 p_name
= (const struct p_string
*)((const char*)&type
->member_v1
.offset
+ leaf_len
);
863 codeview_add_udt_element(ctp
, symt
, terminate_string(p_name
), value
,
864 type
->member_v1
.type
);
866 ptr
+= 2 + 2 + 2 + leaf_len
+ (1 + p_name
->namelen
);
870 leaf_len
= numeric_leaf(&value
, &type
->member_v2
.offset
);
871 p_name
= (const struct p_string
*)((const unsigned char*)&type
->member_v2
.offset
+ leaf_len
);
873 codeview_add_udt_element(ctp
, symt
, terminate_string(p_name
), value
,
874 type
->member_v2
.type
);
876 ptr
+= 2 + 2 + 4 + leaf_len
+ (1 + p_name
->namelen
);
880 leaf_len
= numeric_leaf(&value
, &type
->member_v3
.offset
);
881 c_name
= (const char*)&type
->member_v3
.offset
+ leaf_len
;
883 codeview_add_udt_element(ctp
, symt
, c_name
, value
, type
->member_v3
.type
);
885 ptr
+= 2 + 2 + 4 + leaf_len
+ (strlen(c_name
) + 1);
889 /* FIXME: ignored for now */
890 ptr
+= 2 + 2 + 2 + (1 + type
->stmember_v1
.p_name
.namelen
);
894 /* FIXME: ignored for now */
895 ptr
+= 2 + 4 + 2 + (1 + type
->stmember_v2
.p_name
.namelen
);
899 /* FIXME: ignored for now */
900 ptr
+= 2 + 4 + 2 + (strlen(type
->stmember_v3
.name
) + 1);
904 /* FIXME: ignored for now */
905 ptr
+= 2 + 2 + 2 + (1 + type
->method_v1
.p_name
.namelen
);
909 /* FIXME: ignored for now */
910 ptr
+= 2 + 2 + 4 + (1 + type
->method_v2
.p_name
.namelen
);
914 /* FIXME: ignored for now */
915 ptr
+= 2 + 2 + 4 + (strlen(type
->method_v3
.name
) + 1);
919 /* FIXME: ignored for now */
920 ptr
+= 2 + 2 + (1 + type
->nesttype_v1
.p_name
.namelen
);
924 /* FIXME: ignored for now */
925 ptr
+= 2 + 2 + 4 + (1 + type
->nesttype_v2
.p_name
.namelen
);
929 /* FIXME: ignored for now */
930 ptr
+= 2 + 2 + 4 + (strlen(type
->nesttype_v3
.name
) + 1);
934 /* FIXME: ignored for now */
939 /* FIXME: ignored for now */
943 case LF_ONEMETHOD_V1
:
944 /* FIXME: ignored for now */
945 switch ((type
->onemethod_v1
.attribute
>> 2) & 7)
947 case 4: case 6: /* (pure) introducing virtual method */
948 ptr
+= 2 + 2 + 2 + 4 + (1 + type
->onemethod_virt_v1
.p_name
.namelen
);
952 ptr
+= 2 + 2 + 2 + (1 + type
->onemethod_v1
.p_name
.namelen
);
957 case LF_ONEMETHOD_V2
:
958 /* FIXME: ignored for now */
959 switch ((type
->onemethod_v2
.attribute
>> 2) & 7)
961 case 4: case 6: /* (pure) introducing virtual method */
962 ptr
+= 2 + 2 + 4 + 4 + (1 + type
->onemethod_virt_v2
.p_name
.namelen
);
966 ptr
+= 2 + 2 + 4 + (1 + type
->onemethod_v2
.p_name
.namelen
);
971 case LF_ONEMETHOD_V3
:
972 /* FIXME: ignored for now */
973 switch ((type
->onemethod_v3
.attribute
>> 2) & 7)
975 case 4: case 6: /* (pure) introducing virtual method */
976 ptr
+= 2 + 2 + 4 + 4 + (strlen(type
->onemethod_virt_v3
.name
) + 1);
980 ptr
+= 2 + 2 + 4 + (strlen(type
->onemethod_v3
.name
) + 1);
986 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v1
.ref
))
992 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v2
.ref
))
998 FIXME("Unsupported type %04x in STRUCT field list\n", type
->generic
.id
);
1006 static struct symt
* codeview_add_type_enum(struct codeview_type_parse
* ctp
,
1007 struct symt
* existing
,
1009 unsigned fieldlistno
,
1012 struct symt_enum
* symt
;
1016 if (!(symt
= codeview_cast_symt(existing
, SymTagEnum
))) return NULL
;
1017 /* should also check that all fields are the same */
1021 symt
= symt_new_enum(ctp
->module
, name
,
1022 codeview_fetch_type(ctp
, basetype
, FALSE
));
1025 const union codeview_reftype
* fieldlist
;
1026 fieldlist
= codeview_jump_to_type(ctp
, fieldlistno
);
1027 codeview_add_type_enum_field_list(ctp
->module
, symt
, fieldlist
);
1033 static struct symt
* codeview_add_type_struct(struct codeview_type_parse
* ctp
,
1034 struct symt
* existing
,
1035 const char* name
, int structlen
,
1036 enum UdtKind kind
, unsigned property
)
1038 struct symt_udt
* symt
;
1040 /* if we don't have an existing type, try to find one with same name
1041 * FIXME: what to do when several types in different CUs have same name ?
1046 struct symt_ht
* type
;
1047 struct hash_table_iter hti
;
1049 hash_table_iter_init(&ctp
->module
->ht_types
, &hti
, name
);
1050 while ((ptr
= hash_table_iter_up(&hti
)))
1052 type
= CONTAINING_RECORD(ptr
, struct symt_ht
, hash_elt
);
1054 if (type
->symt
.tag
== SymTagUDT
&&
1055 type
->hash_elt
.name
&& !strcmp(type
->hash_elt
.name
, name
))
1057 existing
= &type
->symt
;
1064 if (!(symt
= codeview_cast_symt(existing
, SymTagUDT
))) return NULL
;
1065 /* should also check that all fields are the same */
1066 if (!(property
& 0x80)) /* 0x80 = forward declaration */
1068 if (!symt
->size
) /* likely prior forward declaration, set UDT size */
1069 symt_set_udt_size(ctp
->module
, symt
, structlen
);
1070 else /* different UDT with same name, create a new type */
1074 if (!existing
) symt
= symt_new_udt(ctp
->module
, name
, structlen
, kind
);
1079 static struct symt
* codeview_new_func_signature(struct codeview_type_parse
* ctp
,
1080 struct symt
* existing
,
1081 enum CV_call_e call_conv
)
1083 struct symt_function_signature
* sym
;
1087 sym
= codeview_cast_symt(existing
, SymTagFunctionType
);
1088 if (!sym
) return NULL
;
1092 sym
= symt_new_function_signature(ctp
->module
, NULL
, call_conv
);
1097 static void codeview_add_func_signature_args(struct codeview_type_parse
* ctp
,
1098 struct symt_function_signature
* sym
,
1102 const union codeview_reftype
* reftype
;
1104 sym
->rettype
= codeview_fetch_type(ctp
, ret_type
, FALSE
);
1105 if (args_list
&& (reftype
= codeview_jump_to_type(ctp
, args_list
)))
1108 switch (reftype
->generic
.id
)
1111 for (i
= 0; i
< reftype
->arglist_v1
.num
; i
++)
1112 symt_add_function_signature_parameter(ctp
->module
, sym
,
1113 codeview_fetch_type(ctp
, reftype
->arglist_v1
.args
[i
], FALSE
));
1116 for (i
= 0; i
< reftype
->arglist_v2
.num
; i
++)
1117 symt_add_function_signature_parameter(ctp
->module
, sym
,
1118 codeview_fetch_type(ctp
, reftype
->arglist_v2
.args
[i
], FALSE
));
1121 FIXME("Unexpected leaf %x for signature's pmt\n", reftype
->generic
.id
);
1126 static struct symt
* codeview_parse_one_type(struct codeview_type_parse
* ctp
,
1128 const union codeview_type
* type
, BOOL details
)
1131 int value
, leaf_len
;
1132 const struct p_string
* p_name
;
1134 struct symt
* existing
;
1136 existing
= codeview_get_type(curr_type
, TRUE
);
1138 switch (type
->generic
.id
)
1140 case LF_MODIFIER_V1
:
1141 /* FIXME: we don't handle modifiers,
1142 * but read previous type on the curr_type
1144 WARN("Modifier on %x: %s%s%s%s\n",
1145 type
->modifier_v1
.type
,
1146 type
->modifier_v1
.attribute
& 0x01 ? "const " : "",
1147 type
->modifier_v1
.attribute
& 0x02 ? "volatile " : "",
1148 type
->modifier_v1
.attribute
& 0x04 ? "unaligned " : "",
1149 type
->modifier_v1
.attribute
& ~0x07 ? "unknown " : "");
1150 symt
= codeview_fetch_type(ctp
, type
->modifier_v1
.type
, details
);
1152 case LF_MODIFIER_V2
:
1153 /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
1154 WARN("Modifier on %x: %s%s%s%s\n",
1155 type
->modifier_v2
.type
,
1156 type
->modifier_v2
.attribute
& 0x01 ? "const " : "",
1157 type
->modifier_v2
.attribute
& 0x02 ? "volatile " : "",
1158 type
->modifier_v2
.attribute
& 0x04 ? "unaligned " : "",
1159 type
->modifier_v2
.attribute
& ~0x07 ? "unknown " : "");
1160 symt
= codeview_fetch_type(ctp
, type
->modifier_v2
.type
, details
);
1164 symt
= codeview_add_type_pointer(ctp
, existing
, type
->pointer_v1
.datatype
);
1167 symt
= codeview_add_type_pointer(ctp
, existing
, type
->pointer_v2
.datatype
);
1171 if (existing
) symt
= codeview_cast_symt(existing
, SymTagArrayType
);
1174 leaf_len
= numeric_leaf(&value
, &type
->array_v1
.arrlen
);
1175 p_name
= (const struct p_string
*)((const unsigned char*)&type
->array_v1
.arrlen
+ leaf_len
);
1176 symt
= codeview_add_type_array(ctp
, terminate_string(p_name
),
1177 type
->array_v1
.elemtype
,
1178 type
->array_v1
.idxtype
, value
);
1182 if (existing
) symt
= codeview_cast_symt(existing
, SymTagArrayType
);
1185 leaf_len
= numeric_leaf(&value
, &type
->array_v2
.arrlen
);
1186 p_name
= (const struct p_string
*)((const unsigned char*)&type
->array_v2
.arrlen
+ leaf_len
);
1188 symt
= codeview_add_type_array(ctp
, terminate_string(p_name
),
1189 type
->array_v2
.elemtype
,
1190 type
->array_v2
.idxtype
, value
);
1194 if (existing
) symt
= codeview_cast_symt(existing
, SymTagArrayType
);
1197 leaf_len
= numeric_leaf(&value
, &type
->array_v3
.arrlen
);
1198 c_name
= (const char*)&type
->array_v3
.arrlen
+ leaf_len
;
1200 symt
= codeview_add_type_array(ctp
, c_name
,
1201 type
->array_v3
.elemtype
,
1202 type
->array_v3
.idxtype
, value
);
1206 case LF_STRUCTURE_V1
:
1208 leaf_len
= numeric_leaf(&value
, &type
->struct_v1
.structlen
);
1209 p_name
= (const struct p_string
*)((const unsigned char*)&type
->struct_v1
.structlen
+ leaf_len
);
1210 symt
= codeview_add_type_struct(ctp
, existing
, terminate_string(p_name
), value
,
1211 type
->generic
.id
== LF_CLASS_V1
? UdtClass
: UdtStruct
,
1212 type
->struct_v1
.property
);
1215 codeview_add_type(curr_type
, symt
);
1216 if (!(type
->struct_v1
.property
& 0x80)) /* 0x80 = forward declaration */
1217 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)symt
,
1218 type
->struct_v1
.fieldlist
);
1222 case LF_STRUCTURE_V2
:
1224 leaf_len
= numeric_leaf(&value
, &type
->struct_v2
.structlen
);
1225 p_name
= (const struct p_string
*)((const unsigned char*)&type
->struct_v2
.structlen
+ leaf_len
);
1226 symt
= codeview_add_type_struct(ctp
, existing
, terminate_string(p_name
), value
,
1227 type
->generic
.id
== LF_CLASS_V2
? UdtClass
: UdtStruct
,
1228 type
->struct_v2
.property
);
1231 codeview_add_type(curr_type
, symt
);
1232 if (!(type
->struct_v2
.property
& 0x80)) /* 0x80 = forward declaration */
1233 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)symt
,
1234 type
->struct_v2
.fieldlist
);
1238 case LF_STRUCTURE_V3
:
1240 leaf_len
= numeric_leaf(&value
, &type
->struct_v3
.structlen
);
1241 c_name
= (const char*)&type
->struct_v3
.structlen
+ leaf_len
;
1242 symt
= codeview_add_type_struct(ctp
, existing
, c_name
, value
,
1243 type
->generic
.id
== LF_CLASS_V3
? UdtClass
: UdtStruct
,
1244 type
->struct_v3
.property
);
1247 codeview_add_type(curr_type
, symt
);
1248 if (!(type
->struct_v3
.property
& 0x80)) /* 0x80 = forward declaration */
1249 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)symt
,
1250 type
->struct_v3
.fieldlist
);
1255 leaf_len
= numeric_leaf(&value
, &type
->union_v1
.un_len
);
1256 p_name
= (const struct p_string
*)((const unsigned char*)&type
->union_v1
.un_len
+ leaf_len
);
1257 symt
= codeview_add_type_struct(ctp
, existing
, terminate_string(p_name
),
1258 value
, UdtUnion
, type
->union_v1
.property
);
1261 codeview_add_type(curr_type
, symt
);
1262 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)symt
,
1263 type
->union_v1
.fieldlist
);
1268 leaf_len
= numeric_leaf(&value
, &type
->union_v2
.un_len
);
1269 p_name
= (const struct p_string
*)((const unsigned char*)&type
->union_v2
.un_len
+ leaf_len
);
1270 symt
= codeview_add_type_struct(ctp
, existing
, terminate_string(p_name
),
1271 value
, UdtUnion
, type
->union_v2
.property
);
1274 codeview_add_type(curr_type
, symt
);
1275 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)symt
,
1276 type
->union_v2
.fieldlist
);
1281 leaf_len
= numeric_leaf(&value
, &type
->union_v3
.un_len
);
1282 c_name
= (const char*)&type
->union_v3
.un_len
+ leaf_len
;
1283 symt
= codeview_add_type_struct(ctp
, existing
, c_name
,
1284 value
, UdtUnion
, type
->union_v3
.property
);
1287 codeview_add_type(curr_type
, symt
);
1288 codeview_add_type_struct_field_list(ctp
, (struct symt_udt
*)symt
,
1289 type
->union_v3
.fieldlist
);
1294 symt
= codeview_add_type_enum(ctp
, existing
,
1295 terminate_string(&type
->enumeration_v1
.p_name
),
1296 type
->enumeration_v1
.fieldlist
,
1297 type
->enumeration_v1
.type
);
1301 symt
= codeview_add_type_enum(ctp
, existing
,
1302 terminate_string(&type
->enumeration_v2
.p_name
),
1303 type
->enumeration_v2
.fieldlist
,
1304 type
->enumeration_v2
.type
);
1308 symt
= codeview_add_type_enum(ctp
, existing
, type
->enumeration_v3
.name
,
1309 type
->enumeration_v3
.fieldlist
,
1310 type
->enumeration_v3
.type
);
1313 case LF_PROCEDURE_V1
:
1314 symt
= codeview_new_func_signature(ctp
, existing
, type
->procedure_v1
.callconv
);
1317 codeview_add_type(curr_type
, symt
);
1318 codeview_add_func_signature_args(ctp
,
1319 (struct symt_function_signature
*)symt
,
1320 type
->procedure_v1
.rvtype
,
1321 type
->procedure_v1
.arglist
);
1324 case LF_PROCEDURE_V2
:
1325 symt
= codeview_new_func_signature(ctp
, existing
,type
->procedure_v2
.callconv
);
1328 codeview_add_type(curr_type
, symt
);
1329 codeview_add_func_signature_args(ctp
,
1330 (struct symt_function_signature
*)symt
,
1331 type
->procedure_v2
.rvtype
,
1332 type
->procedure_v2
.arglist
);
1336 case LF_MFUNCTION_V1
:
1337 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1338 * nor class information, this would just do for now
1340 symt
= codeview_new_func_signature(ctp
, existing
, type
->mfunction_v1
.callconv
);
1343 codeview_add_type(curr_type
, symt
);
1344 codeview_add_func_signature_args(ctp
,
1345 (struct symt_function_signature
*)symt
,
1346 type
->mfunction_v1
.rvtype
,
1347 type
->mfunction_v1
.arglist
);
1350 case LF_MFUNCTION_V2
:
1351 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1352 * nor class information, this would just do for now
1354 symt
= codeview_new_func_signature(ctp
, existing
, type
->mfunction_v2
.callconv
);
1357 codeview_add_type(curr_type
, symt
);
1358 codeview_add_func_signature_args(ctp
,
1359 (struct symt_function_signature
*)symt
,
1360 type
->mfunction_v2
.rvtype
,
1361 type
->mfunction_v2
.arglist
);
1366 /* this is an ugly hack... FIXME when we have C++ support */
1367 if (!(symt
= existing
))
1370 snprintf(buf
, sizeof(buf
), "__internal_vt_shape_%x\n", curr_type
);
1371 symt
= &symt_new_udt(ctp
->module
, buf
, 0, UdtStruct
)->symt
;
1375 FIXME("Unsupported type-id leaf %x\n", type
->generic
.id
);
1376 dump(type
, 2 + type
->generic
.len
);
1379 return codeview_add_type(curr_type
, symt
) ? symt
: NULL
;
1382 static BOOL
codeview_parse_type_table(struct codeview_type_parse
* ctp
)
1384 unsigned int curr_type
= FIRST_DEFINABLE_TYPE
;
1385 const union codeview_type
* type
;
1387 for (curr_type
= FIRST_DEFINABLE_TYPE
; curr_type
< FIRST_DEFINABLE_TYPE
+ ctp
->num
; curr_type
++)
1389 type
= codeview_jump_to_type(ctp
, curr_type
);
1391 /* type records we're interested in are the ones referenced by symbols
1392 * The known ranges are (X mark the ones we want):
1393 * X 0000-0016 for V1 types
1394 * 0200-020c for V1 types referenced by other types
1395 * 0400-040f for V1 types (complex lists & sets)
1396 * X 1000-100f for V2 types
1397 * 1200-120c for V2 types referenced by other types
1398 * 1400-140f for V1 types (complex lists & sets)
1399 * X 1500-150d for V3 types
1400 * 8000-8010 for numeric leafes
1402 if (!(type
->generic
.id
& 0x8600) || (type
->generic
.id
& 0x0100))
1403 codeview_parse_one_type(ctp
, curr_type
, type
, TRUE
);
1409 /*========================================================================
1410 * Process CodeView line number information.
1412 static ULONG_PTR
codeview_get_address(const struct msc_debug_info
* msc_dbg
,
1413 unsigned seg
, unsigned offset
);
1415 static void codeview_snarf_linetab(const struct msc_debug_info
* msc_dbg
, const BYTE
* linetab
,
1416 int size
, BOOL pascal_str
)
1418 const BYTE
* ptr
= linetab
;
1422 const unsigned int* filetab
;
1423 const unsigned int* lt_ptr
;
1424 const unsigned short* linenos
;
1425 const struct startend
* start
;
1427 ULONG_PTR addr
, func_addr0
;
1428 struct symt_function
* func
;
1429 const struct codeview_linetab_block
* ltb
;
1431 nfile
= *(const short*)linetab
;
1432 filetab
= (const unsigned int*)(linetab
+ 2 * sizeof(short));
1434 for (i
= 0; i
< nfile
; i
++)
1436 ptr
= linetab
+ filetab
[i
];
1437 nseg
= *(const short*)ptr
;
1438 lt_ptr
= (const unsigned int*)(ptr
+ 2 * sizeof(short));
1439 start
= (const struct startend
*)(lt_ptr
+ nseg
);
1442 * Now snarf the filename for all of the segments for this file.
1445 source
= source_new(msc_dbg
->module
, NULL
, terminate_string((const struct p_string
*)(start
+ nseg
)));
1447 source
= source_new(msc_dbg
->module
, NULL
, (const char*)(start
+ nseg
));
1449 for (j
= 0; j
< nseg
; j
++)
1451 ltb
= (const struct codeview_linetab_block
*)(linetab
+ *lt_ptr
++);
1452 linenos
= (const unsigned short*)<b
->offsets
[ltb
->num_lines
];
1453 func_addr0
= codeview_get_address(msc_dbg
, ltb
->seg
, start
[j
].start
);
1454 if (!func_addr0
) continue;
1455 for (func
= NULL
, k
= 0; k
< ltb
->num_lines
; k
++)
1457 /* now locate function (if any) */
1458 addr
= func_addr0
+ ltb
->offsets
[k
] - start
[j
].start
;
1459 /* unfortunately, we can have several functions in the same block, if there's no
1460 * gap between them... find the new function if needed
1462 if (!func
|| addr
>= func
->address
+ func
->size
)
1464 func
= (struct symt_function
*)symt_find_symbol_at(msc_dbg
->module
, addr
);
1465 /* FIXME: at least labels support line numbers */
1466 if (!symt_check_tag(&func
->symt
, SymTagFunction
) && !symt_check_tag(&func
->symt
, SymTagInlineSite
))
1468 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1469 ltb
->seg
, ltb
->offsets
[k
], addr
, func
? func
->symt
.tag
: -1);
1474 symt_add_func_line(msc_dbg
->module
, func
, source
, linenos
[k
], addr
);
1480 static void codeview_snarf_linetab2(const struct msc_debug_info
* msc_dbg
, const struct cv_module_snarf
* cvmod
)
1483 const void* hdr_last
= (const char*)cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
;
1484 const struct CV_DebugSSubsectionHeader_t
* hdr
;
1485 const struct CV_DebugSSubsectionHeader_t
* hdr_next
;
1486 const struct CV_DebugSSubsectionHeader_t
* hdr_files
= NULL
;
1487 const struct CV_DebugSLinesHeader_t
* lines_hdr
;
1488 const struct CV_DebugSLinesFileBlockHeader_t
* files_hdr
;
1489 const struct CV_Line_t
* lines
;
1490 const struct CV_Checksum_t
* chksms
;
1492 struct symt_function
* func
;
1494 /* locate DEBUG_S_FILECHKSMS (if any) */
1495 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, hdr_last
); hdr
= CV_RECORD_GAP(hdr
, hdr
->cbLen
))
1497 if (hdr
->type
== DEBUG_S_FILECHKSMS
)
1505 TRACE("No DEBUG_S_FILECHKSMS found\n");
1509 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, hdr_last
); hdr
= hdr_next
)
1511 hdr_next
= CV_RECORD_GAP(hdr
, hdr
->cbLen
);
1512 if (!(hdr
->type
& DEBUG_S_IGNORE
))
1514 ULONG_PTR lineblk_base
;
1515 /* FIXME: should also check that whole lines_blk fits in linetab + size */
1519 lines_hdr
= CV_RECORD_AFTER(hdr
);
1520 files_hdr
= CV_RECORD_AFTER(lines_hdr
);
1521 /* Skip blocks that are too small - Intel C Compiler generates these. */
1522 if (!CV_IS_INSIDE(files_hdr
, hdr_next
)) break;
1523 TRACE("block from %04x:%08x #%x\n",
1524 lines_hdr
->segCon
, lines_hdr
->offCon
, lines_hdr
->cbCon
);
1525 chksms
= CV_RECORD_GAP(hdr_files
, files_hdr
->offFile
);
1526 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
)))
1528 WARN("Corrupt PDB file: offset in CHKSMS subsection is invalid\n");
1531 source
= source_new(msc_dbg
->module
, NULL
,
1532 (chksms
->strOffset
< cvmod
->strsize
) ? cvmod
->strimage
+ chksms
->strOffset
: "<<stroutofbounds>>");
1533 lineblk_base
= codeview_get_address(msc_dbg
, lines_hdr
->segCon
, lines_hdr
->offCon
);
1534 lines
= CV_RECORD_AFTER(files_hdr
);
1535 for (i
= 0; i
< files_hdr
->nLines
; i
++)
1537 func
= (struct symt_function
*)symt_find_symbol_at(msc_dbg
->module
, lineblk_base
+ lines
[i
].offset
);
1538 /* FIXME: at least labels support line numbers */
1539 if (!symt_check_tag(&func
->symt
, SymTagFunction
) && !symt_check_tag(&func
->symt
, SymTagInlineSite
))
1541 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1542 lines_hdr
->segCon
, lines_hdr
->offCon
+ lines
[i
].offset
, lineblk_base
+ lines
[i
].offset
, func
? func
->symt
.tag
: -1);
1545 symt_add_func_line(msc_dbg
->module
, func
, source
,
1546 lines
[i
].linenumStart
, lineblk_base
+ lines
[i
].offset
);
1549 case DEBUG_S_FILECHKSMS
: /* skip */
1559 /*========================================================================
1560 * Process CodeView symbol information.
1563 static unsigned int codeview_map_offset(const struct msc_debug_info
* msc_dbg
,
1564 unsigned int offset
)
1566 int nomap
= msc_dbg
->nomap
;
1567 const OMAP
* omapp
= msc_dbg
->omapp
;
1570 if (!nomap
|| !omapp
) return offset
;
1572 /* FIXME: use binary search */
1573 for (i
= 0; i
< nomap
- 1; i
++)
1574 if (omapp
[i
].rva
<= offset
&& omapp
[i
+1].rva
> offset
)
1575 return !omapp
[i
].rvaTo
? 0 : omapp
[i
].rvaTo
+ (offset
- omapp
[i
].rva
);
1580 static ULONG_PTR
codeview_get_address(const struct msc_debug_info
* msc_dbg
,
1581 unsigned seg
, unsigned offset
)
1583 int nsect
= msc_dbg
->nsect
;
1584 const IMAGE_SECTION_HEADER
* sectp
= msc_dbg
->sectp
;
1586 if (!seg
|| seg
> nsect
) return 0;
1587 return msc_dbg
->module
->module
.BaseOfImage
+
1588 codeview_map_offset(msc_dbg
, sectp
[seg
-1].VirtualAddress
+ offset
);
1591 static BOOL
func_has_local(struct symt_function
* func
, const char* name
)
1595 for (i
= 0; i
< func
->vchildren
.num_elts
; ++i
)
1597 struct symt
* p
= *(struct symt
**)vector_at(&func
->vchildren
, i
);
1598 if (symt_check_tag(p
, SymTagData
) && !strcmp(((struct symt_data
*)p
)->hash_elt
.name
, name
))
1604 static const union codeview_symbol
* get_next_sym(const union codeview_symbol
* sym
)
1606 return (const union codeview_symbol
*)((const char*)sym
+ sym
->generic
.len
+ 2);
1609 static inline void codeview_add_variable(const struct msc_debug_info
* msc_dbg
,
1610 struct symt_compiland
* compiland
,
1612 unsigned segment
, unsigned offset
,
1613 unsigned symtype
, BOOL is_local
, BOOL in_tls
, BOOL force
)
1617 struct location loc
;
1619 loc
.kind
= in_tls
? loc_tlsrel
: loc_absolute
;
1621 loc
.offset
= in_tls
? offset
: codeview_get_address(msc_dbg
, segment
, offset
);
1622 if (force
|| in_tls
|| !symt_find_symbol_at(msc_dbg
->module
, loc
.offset
))
1624 symt_new_global_variable(msc_dbg
->module
, compiland
,
1625 name
, is_local
, loc
, 0,
1626 codeview_get_type(symtype
, FALSE
));
1631 struct cv_local_info
1633 unsigned short kind
; /* the S_DEFRANGE* */
1634 unsigned short ngaps
; /* number of gaps */
1636 unsigned short rangelen
; /* after start */
1639 struct cv_addr_gap gaps
[0];
1642 static const struct cv_addr_gap
* codeview_get_gaps(const union codeview_symbol
* symrange
)
1644 const struct cv_addr_gap
* gap
;
1645 switch (symrange
->generic
.id
)
1647 case S_DEFRANGE
: gap
= symrange
->defrange_v3
.gaps
; break;
1648 case S_DEFRANGE_SUBFIELD
: gap
= symrange
->defrange_subfield_v3
.gaps
; break;
1649 case S_DEFRANGE_REGISTER
: gap
= symrange
->defrange_register_v3
.gaps
; break;
1650 case S_DEFRANGE_FRAMEPOINTER_REL
: gap
= symrange
->defrange_frameptrrel_v3
.gaps
; break;
1651 case S_DEFRANGE_SUBFIELD_REGISTER
: gap
= symrange
->defrange_subfield_register_v3
.gaps
; break;
1652 case S_DEFRANGE_REGISTER_REL
: gap
= symrange
->defrange_registerrel_v3
.gaps
; break;
1653 /* no gaps for that one */
1654 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
1655 default: return NULL
;
1657 return gap
!= (const struct cv_addr_gap
*)get_next_sym(symrange
) ? gap
: NULL
;
1660 static void codeview_xform_range(const struct msc_debug_info
* msc_dbg
,
1661 struct cv_local_info
* locinfo
,
1662 const struct cv_addr_range
* adrange
)
1664 locinfo
->start
= codeview_get_address(msc_dbg
, adrange
->isectStart
, adrange
->offStart
);
1665 locinfo
->rangelen
= adrange
->cbRange
;
1668 static unsigned codeview_transform_defrange(const struct msc_debug_info
* msc_dbg
,
1669 struct symt_function
* curr_func
,
1670 const union codeview_symbol
* sym
,
1671 struct location
* loc
)
1673 const union codeview_symbol
* first_symrange
= get_next_sym(sym
);
1674 const union codeview_symbol
* symrange
;
1675 const struct cv_addr_gap
* gap
;
1676 unsigned len
, alloc
= sizeof(DWORD
); /* for terminating kind = 0 */
1679 /* we need to transform the cv_addr_range into cv_local_info */
1680 for (symrange
= first_symrange
;
1681 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1682 symrange
= get_next_sym(symrange
))
1684 gap
= codeview_get_gaps(symrange
);
1685 alloc
+= sizeof(struct cv_local_info
) +
1686 (gap
? (const char*)get_next_sym(symrange
) - (const char*)gap
: 0);
1688 /* total length of all S_DEFRANGE* records (in bytes) following S_LOCAL */
1689 len
= (const char*)symrange
- (const char*)first_symrange
;
1691 ptr
= pool_alloc(&msc_dbg
->module
->pool
, alloc
);
1694 struct cv_local_info
* locinfo
= (struct cv_local_info
*)ptr
;
1696 loc
->kind
= loc_cv_local_range
;
1697 loc
->offset
= (DWORD_PTR
)ptr
;
1698 /* transform the cv_addr_range into cv_local_info */
1699 for (symrange
= first_symrange
;
1700 symrange
->generic
.id
>= S_DEFRANGE
&& symrange
->generic
.id
<= S_DEFRANGE_REGISTER_REL
;
1701 symrange
= get_next_sym(symrange
))
1703 locinfo
->kind
= symrange
->generic
.id
;
1704 switch (symrange
->generic
.id
)
1707 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_v3
.range
);
1708 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1710 case S_DEFRANGE_SUBFIELD
:
1711 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_subfield_v3
.range
);
1712 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1714 case S_DEFRANGE_REGISTER
:
1715 locinfo
->reg
= symrange
->defrange_register_v3
.reg
;
1716 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_register_v3
.range
);
1718 case S_DEFRANGE_FRAMEPOINTER_REL
:
1719 locinfo
->offset
= symrange
->defrange_frameptrrel_v3
.offFramePointer
;
1720 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_frameptrrel_v3
.range
);
1722 case S_DEFRANGE_SUBFIELD_REGISTER
:
1723 locinfo
->reg
= symrange
->defrange_subfield_register_v3
.reg
;
1724 locinfo
->offset
= symrange
->defrange_subfield_register_v3
.offParent
;
1725 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_subfield_register_v3
.range
);
1727 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
1728 locinfo
->offset
= symrange
->defrange_frameptr_relfullscope_v3
.offFramePointer
;
1729 locinfo
->start
= curr_func
->address
;
1730 locinfo
->rangelen
= curr_func
->size
;
1732 case S_DEFRANGE_REGISTER_REL
:
1733 locinfo
->reg
= symrange
->defrange_registerrel_v3
.baseReg
;
1734 locinfo
->offset
= symrange
->defrange_registerrel_v3
.offBasePointer
;
1735 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_registerrel_v3
.range
);
1740 gap
= codeview_get_gaps(symrange
);
1743 unsigned gaplen
= (const char*)get_next_sym(symrange
) - (const char*)gap
;
1744 locinfo
->ngaps
= gaplen
/ sizeof(*gap
);
1745 memcpy(locinfo
->gaps
, gap
, gaplen
);
1746 locinfo
= (struct cv_local_info
*)((char*)(locinfo
+ 1) + gaplen
);
1754 *(DWORD
*)locinfo
= 0; /* store terminating kind == 0 */
1758 loc
->kind
= loc_error
;
1759 loc
->reg
= loc_err_internal
;
1764 static unsigned codeview_binannot_uncompress(const unsigned char** pptr
)
1766 unsigned res
= (unsigned)(-1);
1767 const unsigned char* ptr
= *pptr
;
1769 if ((*ptr
& 0x80) == 0x00)
1770 res
= (unsigned)(*ptr
++);
1771 else if ((*ptr
& 0xC0) == 0x80)
1773 res
= (unsigned)((*ptr
++ & 0x3f) << 8);
1776 else if ((*ptr
& 0xE0) == 0xC0)
1778 res
= (*ptr
++ & 0x1f) << 24;
1779 res
|= *ptr
++ << 16;
1783 else res
= (unsigned)(-1);
1790 const unsigned char* annot
; /* current pointer */
1791 const unsigned char* last_annot
; /* end of binary annotation stream (first byte after) */
1792 unsigned opcode
; /* last decoded opcode */
1793 unsigned arg1
, arg2
;
1796 static BOOL
codeview_advance_binannot(struct cv_binannot
* cvba
)
1798 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
1799 cvba
->opcode
= codeview_binannot_uncompress(&cvba
->annot
);
1800 if (cvba
->opcode
<= BA_OP_Invalid
|| cvba
->opcode
> BA_OP_ChangeColumnEnd
) return FALSE
;
1801 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
1802 cvba
->arg1
= codeview_binannot_uncompress(&cvba
->annot
);
1803 if (cvba
->opcode
== BA_OP_ChangeCodeOffsetAndLineOffset
)
1805 cvba
->arg2
= cvba
->arg1
>> 4;
1808 else if (cvba
->opcode
== BA_OP_ChangeCodeLengthAndCodeOffset
)
1810 if (cvba
->annot
>= cvba
->last_annot
) return FALSE
;
1811 cvba
->arg2
= codeview_binannot_uncompress(&cvba
->annot
);
1813 else cvba
->arg2
= 0;
1817 static inline int binannot_getsigned(unsigned i
)
1819 return (i
& 1) ? -(int)(i
>> 1) : (int)(i
>> 1);
1822 static BOOL
cv_dbgsubsect_find_inlinee(const struct msc_debug_info
* msc_dbg
,
1824 const struct cv_module_snarf
* cvmod
,
1825 const struct CV_DebugSSubsectionHeader_t
* hdr_files
,
1826 unsigned* srcfile
, unsigned* srcline
)
1828 const struct CV_DebugSSubsectionHeader_t
* hdr
;
1829 const struct CV_DebugSSubsectionHeader_t
* next_hdr
;
1830 const struct CV_InlineeSourceLine_t
* inlsrc
;
1831 const struct CV_InlineeSourceLineEx_t
* inlsrcex
;
1832 const struct CV_Checksum_t
* chksms
;
1834 for (hdr
= cvmod
->dbgsubsect
; CV_IS_INSIDE(hdr
, cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
); hdr
= next_hdr
)
1836 next_hdr
= CV_RECORD_GAP(hdr
, hdr
->cbLen
);
1837 if (hdr
->type
!= DEBUG_S_INLINEELINES
) continue;
1838 /* subsection starts with a DWORD signature */
1839 switch (*(DWORD
*)CV_RECORD_AFTER(hdr
))
1841 case CV_INLINEE_SOURCE_LINE_SIGNATURE
:
1842 inlsrc
= CV_RECORD_GAP(hdr
, sizeof(DWORD
));
1843 while (CV_IS_INSIDE(inlsrc
, next_hdr
))
1845 if (inlsrc
->inlinee
== inlineeid
)
1847 chksms
= CV_RECORD_GAP(hdr_files
, inlsrc
->fileId
);
1848 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))) return FALSE
;
1849 *srcfile
= source_new(msc_dbg
->module
, NULL
,
1850 (chksms
->strOffset
< cvmod
->strsize
) ? cvmod
->strimage
+ chksms
->strOffset
: "<<str-out-of-bounds>>");
1851 *srcline
= inlsrc
->sourceLineNum
;
1857 case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
:
1858 inlsrcex
= CV_RECORD_GAP(hdr
, sizeof(DWORD
));
1859 while (CV_IS_INSIDE(inlsrcex
, next_hdr
))
1861 if (inlsrcex
->inlinee
== inlineeid
)
1863 chksms
= CV_RECORD_GAP(hdr_files
, inlsrcex
->fileId
);
1864 if (!CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))) return FALSE
;
1865 *srcfile
= source_new(msc_dbg
->module
, NULL
,
1866 (chksms
->strOffset
< cvmod
->strsize
) ? cvmod
->strimage
+ chksms
->strOffset
: "<<str-out-of-bounds>>");
1867 *srcline
= inlsrcex
->sourceLineNum
;
1870 inlsrcex
= CV_RECORD_GAP(inlsrcex
, inlsrcex
->countOfExtraFiles
* sizeof(inlsrcex
->extraFileId
[0]));
1874 FIXME("Unknown signature %lx in INLINEELINES subsection\n", *(DWORD
*)CV_RECORD_AFTER(hdr
));
1881 static struct symt_inlinesite
* codeview_create_inline_site(const struct msc_debug_info
* msc_dbg
,
1882 const struct cv_module_snarf
* cvmod
,
1883 struct symt_function
* top_func
,
1884 struct symt
* container
,
1885 cv_itemid_t inlinee
,
1886 const unsigned char* annot
,
1887 const unsigned char* last_annot
)
1889 const struct CV_DebugSSubsectionHeader_t
* hdr_files
= NULL
;
1890 const union codeview_type
* cvt
;
1892 struct symt_inlinesite
* inlined
;
1893 struct cv_binannot cvba
;
1894 BOOL srcok
, found
= FALSE
;
1895 unsigned first
, offset
, length
, line
, srcfile
;
1896 const struct CV_Checksum_t
* chksms
;
1898 if (!cvmod
->ipi_ctp
|| !(cvt
= codeview_jump_to_type(cvmod
->ipi_ctp
, inlinee
)))
1900 FIXME("Couldn't find type %x in IPI stream\n", inlinee
);
1904 addr
= top_func
->address
;
1905 /* grasp first code offset in binary annotation to compute inline site start address */
1907 cvba
.last_annot
= last_annot
;
1908 while (codeview_advance_binannot(&cvba
))
1909 if (cvba
.opcode
== BA_OP_CodeOffset
||
1910 cvba
.opcode
== BA_OP_ChangeCodeOffset
||
1911 cvba
.opcode
== BA_OP_ChangeCodeOffsetAndLineOffset
)
1913 addr
+= first
= cvba
.arg1
;
1918 else if (cvba
.opcode
== BA_OP_ChangeCodeLengthAndCodeOffset
)
1920 addr
+= first
= cvba
.arg2
;
1929 WARN("Couldn't find start address of inlined\n");
1933 switch (cvt
->generic
.id
)
1936 inlined
= symt_new_inlinesite(msc_dbg
->module
, top_func
, container
,
1937 cvt
->func_id_v3
.name
, addr
,
1938 codeview_get_type(cvt
->func_id_v3
.type
, FALSE
));
1941 /* FIXME we just declare a function, not a method */
1942 inlined
= symt_new_inlinesite(msc_dbg
->module
, top_func
, container
,
1943 cvt
->mfunc_id_v3
.name
, addr
,
1944 codeview_get_type(cvt
->mfunc_id_v3
.type
, FALSE
));
1947 FIXME("unsupported inlinee kind %x\n", cvt
->generic
.id
);
1951 for (hdr_files
= cvmod
->dbgsubsect
;
1952 CV_IS_INSIDE(hdr_files
, cvmod
->dbgsubsect
+ cvmod
->dbgsubsect_size
);
1953 hdr_files
= CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
))
1955 if (hdr_files
->type
== DEBUG_S_FILECHKSMS
)
1958 if (!hdr_files
) return FALSE
;
1959 srcok
= cv_dbgsubsect_find_inlinee(msc_dbg
, inlinee
, cvmod
, hdr_files
, &srcfile
, &line
);
1962 symt_add_func_line(msc_dbg
->module
, &inlined
->func
, srcfile
, line
, top_func
->address
+ offset
);
1967 if (!codeview_advance_binannot(&cvba
)) break;
1968 switch (cvba
.opcode
)
1970 case BA_OP_CodeOffset
:
1971 first
= offset
= cvba
.arg1
;
1974 case BA_OP_ChangeCodeOffset
:
1975 offset
+= cvba
.arg1
;
1978 symt_add_func_line(msc_dbg
->module
, &inlined
->func
, srcfile
, line
, top_func
->address
+ offset
);
1980 case BA_OP_ChangeCodeLength
:
1983 case BA_OP_ChangeFile
:
1984 chksms
= CV_RECORD_GAP(hdr_files
, cvba
.arg1
);
1985 if (CV_IS_INSIDE(chksms
, CV_RECORD_GAP(hdr_files
, hdr_files
->cbLen
)))
1986 srcfile
= source_new(msc_dbg
->module
, NULL
,
1987 (chksms
->strOffset
< cvmod
->strsize
) ? cvmod
->strimage
+ chksms
->strOffset
: "<<str-out-of-bounds>>");
1989 case BA_OP_ChangeLineOffset
:
1990 line
+= binannot_getsigned(cvba
.arg1
);
1992 case BA_OP_ChangeCodeOffsetAndLineOffset
:
1994 symt_add_func_line(msc_dbg
->module
, &inlined
->func
, srcfile
, line
, top_func
->address
+ offset
);
1995 line
+= binannot_getsigned(cvba
.arg2
);
1996 offset
+= cvba
.arg1
;
1999 case BA_OP_ChangeCodeLengthAndCodeOffset
:
2000 offset
+= cvba
.arg2
;
2003 symt_add_func_line(msc_dbg
->module
, &inlined
->func
, srcfile
, line
, top_func
->address
+ offset
);
2006 WARN("Unsupported op %d\n", cvba
.opcode
);
2010 symt_add_inlinesite_range(msc_dbg
->module
, inlined
, top_func
->address
+ first
, top_func
->address
+ offset
+ length
);
2014 static BOOL
codeview_snarf(const struct msc_debug_info
* msc_dbg
,
2015 const BYTE
* root
, unsigned offset
, unsigned size
,
2016 const struct cv_module_snarf
* cvmod
,
2019 struct symt_function
* top_func
= NULL
;
2020 struct symt_function
* curr_func
= NULL
;
2022 struct symt_block
* block
= NULL
;
2024 struct symt_compiland
* compiland
= NULL
;
2025 struct location loc
;
2028 * Loop over the different types of records and whenever we
2029 * find something we are interested in, record it and move on.
2031 for (i
= offset
; i
< size
; i
+= length
)
2033 const union codeview_symbol
* sym
= (const union codeview_symbol
*)(root
+ i
);
2034 length
= sym
->generic
.len
+ 2;
2035 if (i
+ length
> size
) break;
2036 if (!sym
->generic
.id
|| length
< 4) break;
2037 if (length
& 3) FIXME("unpadded len %u\n", length
);
2039 switch (sym
->generic
.id
)
2042 * Global and local data symbols. We don't associate these
2043 * with any given source file.
2048 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->data_v1
.p_name
),
2049 sym
->data_v1
.segment
, sym
->data_v1
.offset
, sym
->data_v1
.symtype
,
2050 sym
->generic
.id
== S_LDATA32_16t
, FALSE
, TRUE
);
2055 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->data_v2
.p_name
),
2056 sym
->data_v2
.segment
, sym
->data_v2
.offset
, sym
->data_v2
.symtype
,
2057 sym
->generic
.id
== S_LDATA32_ST
, FALSE
, TRUE
);
2062 codeview_add_variable(msc_dbg
, compiland
, sym
->data_v3
.name
,
2063 sym
->data_v3
.segment
, sym
->data_v3
.offset
, sym
->data_v3
.symtype
,
2064 sym
->generic
.id
== S_LDATA32
, FALSE
, TRUE
);
2067 /* variables with thread storage */
2068 case S_GTHREAD32_16t
:
2069 case S_LTHREAD32_16t
:
2071 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->thread_v1
.p_name
),
2072 sym
->thread_v1
.segment
, sym
->thread_v1
.offset
, sym
->thread_v1
.symtype
,
2073 sym
->generic
.id
== S_LTHREAD32_16t
, TRUE
, TRUE
);
2075 case S_GTHREAD32_ST
:
2076 case S_LTHREAD32_ST
:
2078 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->thread_v2
.p_name
),
2079 sym
->thread_v2
.segment
, sym
->thread_v2
.offset
, sym
->thread_v2
.symtype
,
2080 sym
->generic
.id
== S_LTHREAD32_ST
, TRUE
, TRUE
);
2085 codeview_add_variable(msc_dbg
, compiland
, sym
->thread_v3
.name
,
2086 sym
->thread_v3
.segment
, sym
->thread_v3
.offset
, sym
->thread_v3
.symtype
,
2087 sym
->generic
.id
== S_LTHREAD32
, TRUE
, TRUE
);
2090 /* Public symbols */
2096 /* will be handled later on in codeview_snarf_public */
2100 * Sort of like a global function, but it just points
2101 * to a thunk, which is a stupid name for what amounts to
2102 * a PLT slot in the normal jargon that everyone else uses.
2105 symt_new_thunk(msc_dbg
->module
, compiland
,
2106 terminate_string(&sym
->thunk_v1
.p_name
), sym
->thunk_v1
.thtype
,
2107 codeview_get_address(msc_dbg
, sym
->thunk_v1
.segment
, sym
->thunk_v1
.offset
),
2108 sym
->thunk_v1
.thunk_len
);
2111 symt_new_thunk(msc_dbg
->module
, compiland
,
2112 sym
->thunk_v3
.name
, sym
->thunk_v3
.thtype
,
2113 codeview_get_address(msc_dbg
, sym
->thunk_v3
.segment
, sym
->thunk_v3
.offset
),
2114 sym
->thunk_v3
.thunk_len
);
2118 * Global and static functions.
2122 if (top_func
) FIXME("nested function\n");
2123 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2124 terminate_string(&sym
->proc_v1
.p_name
),
2125 codeview_get_address(msc_dbg
, sym
->proc_v1
.segment
, sym
->proc_v1
.offset
),
2126 sym
->proc_v1
.proc_len
,
2127 codeview_get_type(sym
->proc_v1
.proctype
, FALSE
));
2128 curr_func
= top_func
;
2129 loc
.kind
= loc_absolute
;
2130 loc
.offset
= sym
->proc_v1
.debug_start
;
2131 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2132 loc
.offset
= sym
->proc_v1
.debug_end
;
2133 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2137 if (top_func
) FIXME("nested function\n");
2138 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2139 terminate_string(&sym
->proc_v2
.p_name
),
2140 codeview_get_address(msc_dbg
, sym
->proc_v2
.segment
, sym
->proc_v2
.offset
),
2141 sym
->proc_v2
.proc_len
,
2142 codeview_get_type(sym
->proc_v2
.proctype
, FALSE
));
2143 curr_func
= top_func
;
2144 loc
.kind
= loc_absolute
;
2145 loc
.offset
= sym
->proc_v2
.debug_start
;
2146 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2147 loc
.offset
= sym
->proc_v2
.debug_end
;
2148 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2152 if (top_func
) FIXME("nested function\n");
2153 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
2155 codeview_get_address(msc_dbg
, sym
->proc_v3
.segment
, sym
->proc_v3
.offset
),
2156 sym
->proc_v3
.proc_len
,
2157 codeview_get_type(sym
->proc_v3
.proctype
, FALSE
));
2158 curr_func
= top_func
;
2159 loc
.kind
= loc_absolute
;
2160 loc
.offset
= sym
->proc_v3
.debug_start
;
2161 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugStart
, &loc
, NULL
);
2162 loc
.offset
= sym
->proc_v3
.debug_end
;
2163 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagFuncDebugEnd
, &loc
, NULL
);
2166 * Function parameters and stack variables.
2169 loc
.kind
= loc_regrel
;
2170 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2171 loc
.reg
= CV_REG_EBP
;
2172 loc
.offset
= sym
->stack_v1
.offset
;
2173 symt_add_func_local(msc_dbg
->module
, curr_func
,
2174 sym
->stack_v1
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2176 codeview_get_type(sym
->stack_v1
.symtype
, FALSE
),
2177 terminate_string(&sym
->stack_v1
.p_name
));
2180 loc
.kind
= loc_regrel
;
2181 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2182 loc
.reg
= CV_REG_EBP
;
2183 loc
.offset
= sym
->stack_v2
.offset
;
2184 symt_add_func_local(msc_dbg
->module
, curr_func
,
2185 sym
->stack_v2
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2187 codeview_get_type(sym
->stack_v2
.symtype
, FALSE
),
2188 terminate_string(&sym
->stack_v2
.p_name
));
2191 /* S_BPREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2192 if (func_has_local(curr_func
, sym
->stack_v3
.name
)) break;
2193 loc
.kind
= loc_regrel
;
2194 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2195 loc
.reg
= CV_REG_EBP
;
2196 loc
.offset
= sym
->stack_v3
.offset
;
2197 symt_add_func_local(msc_dbg
->module
, curr_func
,
2198 sym
->stack_v3
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2200 codeview_get_type(sym
->stack_v3
.symtype
, FALSE
),
2201 sym
->stack_v3
.name
);
2204 /* S_REGREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2205 if (func_has_local(curr_func
, sym
->regrel_v3
.name
)) break;
2206 loc
.kind
= loc_regrel
;
2207 loc
.reg
= sym
->regrel_v3
.reg
;
2208 loc
.offset
= sym
->regrel_v3
.offset
;
2209 symt_add_func_local(msc_dbg
->module
, curr_func
,
2210 /* FIXME this is wrong !!! */
2211 sym
->regrel_v3
.offset
> 0 ? DataIsParam
: DataIsLocal
,
2213 codeview_get_type(sym
->regrel_v3
.symtype
, FALSE
),
2214 sym
->regrel_v3
.name
);
2217 case S_REGISTER_16t
:
2218 loc
.kind
= loc_register
;
2219 loc
.reg
= sym
->register_v1
.reg
;
2221 symt_add_func_local(msc_dbg
->module
, curr_func
,
2223 block
, codeview_get_type(sym
->register_v1
.type
, FALSE
),
2224 terminate_string(&sym
->register_v1
.p_name
));
2227 loc
.kind
= loc_register
;
2228 loc
.reg
= sym
->register_v2
.reg
;
2230 symt_add_func_local(msc_dbg
->module
, curr_func
,
2232 block
, codeview_get_type(sym
->register_v2
.type
, FALSE
),
2233 terminate_string(&sym
->register_v2
.p_name
));
2236 /* S_REGISTER can be present after S_LOCAL; prefer S_LOCAL when present */
2237 if (func_has_local(curr_func
, sym
->register_v3
.name
)) break;
2238 loc
.kind
= loc_register
;
2239 loc
.reg
= sym
->register_v3
.reg
;
2241 symt_add_func_local(msc_dbg
->module
, curr_func
,
2243 block
, codeview_get_type(sym
->register_v3
.type
, FALSE
),
2244 sym
->register_v3
.name
);
2248 block
= symt_open_func_block(msc_dbg
->module
, curr_func
, block
,
2249 codeview_get_address(msc_dbg
, sym
->block_v1
.segment
, sym
->block_v1
.offset
) - curr_func
->address
,
2250 sym
->block_v1
.length
);
2253 block
= symt_open_func_block(msc_dbg
->module
, curr_func
, block
,
2254 codeview_get_address(msc_dbg
, sym
->block_v3
.segment
, sym
->block_v3
.offset
) - curr_func
->address
,
2255 sym
->block_v3
.length
);
2261 block
= symt_close_func_block(msc_dbg
->module
, curr_func
, block
, 0);
2265 if (curr_func
!= top_func
) FIXME("shouldn't close a top function with an opened inlined function\n");
2266 top_func
= curr_func
= NULL
;
2271 TRACE("S-Compile-V1 machine:%x language:%x %s\n",
2272 sym
->compile_v1
.machine
, sym
->compile_v1
.flags
.language
, terminate_string(&sym
->compile_v1
.p_name
));
2276 TRACE("S-Compile-V2 machine:%x language:%x %s\n",
2277 sym
->compile2_v2
.machine
, sym
->compile2_v2
.flags
.iLanguage
, terminate_string(&sym
->compile2_v2
.p_name
));
2281 TRACE("S-Compile-V3 machine:%x language:%x %s\n", sym
->compile2_v3
.machine
, sym
->compile2_v3
.flags
.iLanguage
, sym
->compile2_v3
.name
);
2285 TRACE("S-Compile3-V3 machine:%x language:%x %s\n", sym
->compile3_v3
.machine
, sym
->compile3_v3
.flags
.iLanguage
, sym
->compile3_v3
.name
);
2292 TRACE("S-ObjName-V3 %s\n", sym
->objname_v3
.name
);
2293 compiland
= symt_new_compiland(msc_dbg
->module
, 0 /* FIXME */,
2294 source_new(msc_dbg
->module
, NULL
,
2295 sym
->objname_v3
.name
));
2299 TRACE("S-ObjName-V1 %s\n", terminate_string(&sym
->objname_v1
.p_name
));
2300 compiland
= symt_new_compiland(msc_dbg
->module
, 0 /* FIXME */,
2301 source_new(msc_dbg
->module
, NULL
,
2302 terminate_string(&sym
->objname_v1
.p_name
)));
2308 loc
.kind
= loc_absolute
;
2309 loc
.offset
= codeview_get_address(msc_dbg
, sym
->label_v1
.segment
, sym
->label_v1
.offset
) - curr_func
->address
;
2310 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagLabel
, &loc
,
2311 terminate_string(&sym
->label_v1
.p_name
));
2313 else symt_new_label(msc_dbg
->module
, compiland
,
2314 terminate_string(&sym
->label_v1
.p_name
),
2315 codeview_get_address(msc_dbg
, sym
->label_v1
.segment
, sym
->label_v1
.offset
));
2320 loc
.kind
= loc_absolute
;
2321 loc
.offset
= codeview_get_address(msc_dbg
, sym
->label_v3
.segment
, sym
->label_v3
.offset
) - curr_func
->address
;
2322 symt_add_function_point(msc_dbg
->module
, curr_func
, SymTagLabel
,
2323 &loc
, sym
->label_v3
.name
);
2325 else symt_new_label(msc_dbg
->module
, compiland
, sym
->label_v3
.name
,
2326 codeview_get_address(msc_dbg
, sym
->label_v3
.segment
, sym
->label_v3
.offset
));
2329 case S_CONSTANT_16t
:
2332 const struct p_string
* name
;
2336 vlen
= leaf_as_variant(&v
, &sym
->constant_v1
.cvalue
);
2337 name
= (const struct p_string
*)((const char*)&sym
->constant_v1
.cvalue
+ vlen
);
2338 se
= codeview_get_type(sym
->constant_v1
.type
, FALSE
);
2340 TRACE("S-Constant-V1 %u %s %x\n",
2341 v
.n1
.n2
.n3
.intVal
, terminate_string(name
), sym
->constant_v1
.type
);
2342 symt_new_constant(msc_dbg
->module
, compiland
, terminate_string(name
),
2349 const struct p_string
* name
;
2353 vlen
= leaf_as_variant(&v
, &sym
->constant_v2
.cvalue
);
2354 name
= (const struct p_string
*)((const char*)&sym
->constant_v2
.cvalue
+ vlen
);
2355 se
= codeview_get_type(sym
->constant_v2
.type
, FALSE
);
2357 TRACE("S-Constant-V2 %u %s %x\n",
2358 v
.n1
.n2
.n3
.intVal
, terminate_string(name
), sym
->constant_v2
.type
);
2359 symt_new_constant(msc_dbg
->module
, compiland
, terminate_string(name
),
2370 vlen
= leaf_as_variant(&v
, &sym
->constant_v3
.cvalue
);
2371 name
= (const char*)&sym
->constant_v3
.cvalue
+ vlen
;
2372 se
= codeview_get_type(sym
->constant_v3
.type
, FALSE
);
2374 TRACE("S-Constant-V3 %u %s %x\n",
2375 v
.n1
.n2
.n3
.intVal
, name
, sym
->constant_v3
.type
);
2376 /* FIXME: we should add this as a constant value */
2377 symt_new_constant(msc_dbg
->module
, compiland
, name
, se
, &v
);
2382 if (sym
->udt_v1
.type
)
2384 if ((symt
= codeview_get_type(sym
->udt_v1
.type
, FALSE
)))
2385 symt_new_typedef(msc_dbg
->module
, symt
,
2386 terminate_string(&sym
->udt_v1
.p_name
));
2388 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2389 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
2393 if (sym
->udt_v2
.type
)
2395 if ((symt
= codeview_get_type(sym
->udt_v2
.type
, FALSE
)))
2396 symt_new_typedef(msc_dbg
->module
, symt
,
2397 terminate_string(&sym
->udt_v2
.p_name
));
2399 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2400 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
2404 if (sym
->udt_v3
.type
)
2406 if ((symt
= codeview_get_type(sym
->udt_v3
.type
, FALSE
)))
2407 symt_new_typedef(msc_dbg
->module
, symt
, sym
->udt_v3
.name
);
2409 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2410 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
2414 length
+= codeview_transform_defrange(msc_dbg
, curr_func
, sym
, &loc
);
2415 symt_add_func_local(msc_dbg
->module
, curr_func
,
2416 sym
->local_v3
.varflags
& 0x0001 ? DataIsParam
: DataIsLocal
,
2418 codeview_get_type(sym
->local_v3
.symtype
, FALSE
),
2419 sym
->local_v3
.name
);
2423 struct symt_inlinesite
* inlined
= codeview_create_inline_site(msc_dbg
, cvmod
, top_func
,
2424 block
? &block
->symt
: &curr_func
->symt
,
2425 sym
->inline_site_v3
.inlinee
,
2426 sym
->inline_site_v3
.binaryAnnotations
,
2427 (const unsigned char*)sym
+ length
);
2430 curr_func
= (struct symt_function
*)inlined
;
2435 /* skip all records until paired S_INLINESITE_END */
2436 sym
= (const union codeview_symbol
*)(root
+ sym
->inline_site_v3
.pEnd
);
2437 if (sym
->generic
.id
!= S_INLINESITE_END
) FIXME("complete wreckage\n");
2438 length
= sym
->inline_site_v3
.pEnd
- i
+ sym
->generic
.len
;
2444 struct symt_inlinesite
* inlined
= codeview_create_inline_site(msc_dbg
, cvmod
, top_func
,
2445 block
? &block
->symt
: &curr_func
->symt
,
2446 sym
->inline_site2_v3
.inlinee
,
2447 sym
->inline_site2_v3
.binaryAnnotations
,
2448 (const unsigned char*)sym
+ length
);
2451 curr_func
= (struct symt_function
*)inlined
;
2456 /* skip all records until paired S_INLINESITE_END */
2457 sym
= (const union codeview_symbol
*)(root
+ sym
->inline_site2_v3
.pEnd
);
2458 if (sym
->generic
.id
!= S_INLINESITE_END
) FIXME("complete wreckage\n");
2459 length
= sym
->inline_site_v3
.pEnd
- i
+ sym
->generic
.len
;
2464 case S_INLINESITE_END
:
2465 block
= symt_check_tag(curr_func
->container
, SymTagBlock
) ?
2466 (struct symt_block
*)curr_func
->container
: NULL
;
2467 curr_func
= (struct symt_function
*)symt_get_upper_inlined((struct symt_inlinesite
*)curr_func
);
2471 * These are special, in that they are always followed by an
2472 * additional length-prefixed string which is *not* included
2473 * into the symbol length count. We need to skip it.
2481 name
= (const char*)sym
+ length
;
2482 length
+= (*name
+ 1 + 3) & ~3;
2487 TRACE("Start search: seg=0x%x at offset 0x%08x\n",
2488 sym
->ssearch_v1
.segment
, sym
->ssearch_v1
.offset
);
2492 TRACE("S-Align V1\n");
2494 case S_HEAPALLOCSITE
:
2495 TRACE("S-heap site V3: offset=0x%08x at sect_idx 0x%04x, inst_len 0x%08x, index 0x%08x\n",
2496 sym
->heap_alloc_site_v3
.offset
, sym
->heap_alloc_site_v3
.sect_idx
,
2497 sym
->heap_alloc_site_v3
.inst_len
, sym
->heap_alloc_site_v3
.index
);
2503 ULONG_PTR parent_addr
= codeview_get_address(msc_dbg
, sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2504 struct symt_ht
* parent
= symt_find_symbol_at(msc_dbg
->module
, parent_addr
);
2505 if (symt_check_tag(&parent
->symt
, SymTagFunction
))
2507 struct symt_function
* pfunc
= (struct symt_function
*)parent
;
2508 top_func
= symt_new_function(msc_dbg
->module
, compiland
, pfunc
->hash_elt
.name
,
2509 codeview_get_address(msc_dbg
, sym
->sepcode_v3
.sect
, sym
->sepcode_v3
.off
),
2510 sym
->sepcode_v3
.length
, pfunc
->type
);
2511 curr_func
= top_func
;
2514 WARN("Couldn't find function referenced by S_SEPCODE at %04x:%08x\n",
2515 sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2518 FIXME("S_SEPCODE inside top-level function %s\n", top_func
->hash_elt
.name
);
2521 /* the symbols we can safely ignore for now */
2528 case S_CALLSITEINFO
:
2529 /* even if S_LOCAL groks all the S_DEFRANGE* records following itself,
2530 * those kinds of records can also be present after a S_FILESTATIC record
2531 * so silence them until (at least) S_FILESTATIC is supported
2533 case S_DEFRANGE_REGISTER
:
2534 case S_DEFRANGE_FRAMEPOINTER_REL
:
2535 case S_DEFRANGE_SUBFIELD_REGISTER
:
2536 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
2537 case S_DEFRANGE_REGISTER_REL
:
2545 TRACE("Unsupported symbol id %x\n", sym
->generic
.id
);
2549 FIXME("Unsupported symbol id %x\n", sym
->generic
.id
);
2550 dump(sym
, 2 + sym
->generic
.len
);
2554 if (cvmod
) codeview_snarf_linetab2(msc_dbg
, cvmod
);
2558 static BOOL
codeview_is_inside(const struct cv_local_info
* locinfo
, const struct symt_function
* func
, DWORD_PTR ip
)
2561 /* ip must be in local_info range, but not in any of its gaps */
2562 if (ip
< locinfo
->start
|| ip
>= locinfo
->start
+ locinfo
->rangelen
) return FALSE
;
2563 for (i
= 0; i
< locinfo
->ngaps
; ++i
)
2564 if (func
->address
+ locinfo
->gaps
[i
].gapStartOffset
<= ip
&&
2565 ip
< func
->address
+ locinfo
->gaps
[i
].gapStartOffset
+ locinfo
->gaps
[i
].cbRange
)
2570 static void pdb_location_compute(struct process
* pcs
,
2571 const struct module_format
* modfmt
,
2572 const struct symt_function
* func
,
2573 struct location
* loc
)
2575 const struct cv_local_info
* locinfo
;
2579 case loc_cv_local_range
:
2580 for (locinfo
= (const struct cv_local_info
*)loc
->offset
;
2582 locinfo
= (const struct cv_local_info
*)((const char*)(locinfo
+ 1) + locinfo
->ngaps
* sizeof(locinfo
->gaps
[0])))
2584 if (!codeview_is_inside(locinfo
, func
, pcs
->localscope_pc
)) continue;
2585 switch (locinfo
->kind
)
2588 case S_DEFRANGE_SUBFIELD
:
2590 FIXME("Unsupported defrange %d\n", locinfo
->kind
);
2591 loc
->kind
= loc_error
;
2592 loc
->reg
= loc_err_internal
;
2594 case S_DEFRANGE_SUBFIELD_REGISTER
:
2595 FIXME("sub-field part not handled\n");
2597 case S_DEFRANGE_REGISTER
:
2598 loc
->kind
= loc_register
;
2599 loc
->reg
= locinfo
->reg
;
2601 case S_DEFRANGE_REGISTER_REL
:
2602 loc
->kind
= loc_regrel
;
2603 loc
->reg
= locinfo
->reg
;
2604 loc
->offset
= locinfo
->offset
;
2606 case S_DEFRANGE_FRAMEPOINTER_REL
:
2607 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
2608 loc
->kind
= loc_regrel
;
2609 loc
->reg
= dbghelp_current_cpu
->frame_regno
;
2610 loc
->offset
= locinfo
->offset
;
2617 loc
->kind
= loc_error
;
2618 loc
->reg
= loc_err_internal
;
2621 static BOOL
codeview_snarf_public(const struct msc_debug_info
* msc_dbg
, const BYTE
* root
,
2622 int offset
, int size
)
2626 struct symt_compiland
* compiland
= NULL
;
2629 * Loop over the different types of records and whenever we
2630 * find something we are interested in, record it and move on.
2632 for (i
= offset
; i
< size
; i
+= length
)
2634 const union codeview_symbol
* sym
= (const union codeview_symbol
*)(root
+ i
);
2635 length
= sym
->generic
.len
+ 2;
2636 if (i
+ length
> size
) break;
2637 if (!sym
->generic
.id
|| length
< 4) break;
2638 if (length
& 3) FIXME("unpadded len %u\n", length
);
2640 switch (sym
->generic
.id
)
2643 if (!(dbghelp_options
& SYMOPT_NO_PUBLICS
))
2645 symt_new_public(msc_dbg
->module
, compiland
,
2646 terminate_string(&sym
->public_v1
.p_name
),
2647 sym
->public_v1
.pubsymflags
== SYMTYPE_FUNCTION
,
2648 codeview_get_address(msc_dbg
, sym
->public_v1
.segment
, sym
->public_v1
.offset
), 1);
2652 if (!(dbghelp_options
& SYMOPT_NO_PUBLICS
))
2654 symt_new_public(msc_dbg
->module
, compiland
,
2655 terminate_string(&sym
->public_v2
.p_name
),
2656 sym
->public_v2
.pubsymflags
== SYMTYPE_FUNCTION
,
2657 codeview_get_address(msc_dbg
, sym
->public_v2
.segment
, sym
->public_v2
.offset
), 1);
2662 if (!(dbghelp_options
& SYMOPT_NO_PUBLICS
))
2664 symt_new_public(msc_dbg
->module
, compiland
,
2665 sym
->public_v3
.name
,
2666 sym
->public_v3
.pubsymflags
== SYMTYPE_FUNCTION
,
2667 codeview_get_address(msc_dbg
, sym
->public_v3
.segment
, sym
->public_v3
.offset
), 1);
2671 case S_LPROCREF
: /* using a data_v3 isn't what we'd expect */
2673 /* FIXME: this is plain wrong (from a simple test) */
2674 if (!(dbghelp_options
& SYMOPT_NO_PUBLICS
))
2676 symt_new_public(msc_dbg
->module
, compiland
,
2678 codeview_get_address(msc_dbg
, sym
->data_v3
.segment
, sym
->data_v3
.offset
), 1);
2683 * Global and local data symbols. We don't associate these
2684 * with any given source file.
2688 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->data_v1
.p_name
),
2689 sym
->data_v1
.segment
, sym
->data_v1
.offset
, sym
->data_v1
.symtype
,
2690 sym
->generic
.id
== S_LDATA32_16t
, FALSE
, FALSE
);
2694 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->data_v2
.p_name
),
2695 sym
->data_v2
.segment
, sym
->data_v2
.offset
, sym
->data_v2
.symtype
,
2696 sym
->generic
.id
== S_LDATA32_ST
, FALSE
, FALSE
);
2700 codeview_add_variable(msc_dbg
, compiland
, sym
->data_v3
.name
,
2701 sym
->data_v3
.segment
, sym
->data_v3
.offset
, sym
->data_v3
.symtype
,
2702 sym
->generic
.id
== S_LDATA32
, FALSE
, FALSE
);
2705 /* variables with thread storage */
2706 case S_GTHREAD32_16t
:
2707 case S_LTHREAD32_16t
:
2708 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->thread_v1
.p_name
),
2709 sym
->thread_v1
.segment
, sym
->thread_v1
.offset
, sym
->thread_v1
.symtype
,
2710 sym
->generic
.id
== S_LTHREAD32_16t
, TRUE
, FALSE
);
2712 case S_GTHREAD32_ST
:
2713 case S_LTHREAD32_ST
:
2714 codeview_add_variable(msc_dbg
, compiland
, terminate_string(&sym
->thread_v2
.p_name
),
2715 sym
->thread_v2
.segment
, sym
->thread_v2
.offset
, sym
->thread_v2
.symtype
,
2716 sym
->generic
.id
== S_LTHREAD32_ST
, TRUE
, FALSE
);
2720 codeview_add_variable(msc_dbg
, compiland
, sym
->thread_v3
.name
,
2721 sym
->thread_v3
.segment
, sym
->thread_v3
.offset
, sym
->thread_v3
.symtype
,
2722 sym
->generic
.id
== S_LTHREAD32
, TRUE
, FALSE
);
2726 * These are special, in that they are always followed by an
2727 * additional length-prefixed string which is *not* included
2728 * into the symbol length count. We need to skip it.
2733 length
+= (((const char*)sym
)[length
] + 1 + 3) & ~3;
2736 msc_dbg
->module
->sortlist_valid
= TRUE
;
2738 msc_dbg
->module
->sortlist_valid
= FALSE
;
2742 /*========================================================================
2746 static void* pdb_jg_read(const struct PDB_JG_HEADER
* pdb
, const WORD
* block_list
,
2752 if (!size
) return NULL
;
2754 num_blocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
2755 buffer
= HeapAlloc(GetProcessHeap(), 0, num_blocks
* pdb
->block_size
);
2757 for (i
= 0; i
< num_blocks
; i
++)
2758 memcpy(buffer
+ i
* pdb
->block_size
,
2759 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
2764 static void* pdb_ds_read(const struct PDB_DS_HEADER
* pdb
, const UINT
*block_list
,
2770 if (!size
) return NULL
;
2772 num_blocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
2773 buffer
= HeapAlloc(GetProcessHeap(), 0, num_blocks
* pdb
->block_size
);
2775 for (i
= 0; i
< num_blocks
; i
++)
2776 memcpy(buffer
+ i
* pdb
->block_size
,
2777 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
2782 static void* pdb_read_jg_file(const struct PDB_JG_HEADER
* pdb
,
2783 const struct PDB_JG_TOC
* toc
, DWORD file_nr
)
2785 const WORD
* block_list
;
2788 if (!toc
|| file_nr
>= toc
->num_files
) return NULL
;
2790 block_list
= (const WORD
*) &toc
->file
[toc
->num_files
];
2791 for (i
= 0; i
< file_nr
; i
++)
2792 block_list
+= (toc
->file
[i
].size
+ pdb
->block_size
- 1) / pdb
->block_size
;
2794 return pdb_jg_read(pdb
, block_list
, toc
->file
[file_nr
].size
);
2797 static void* pdb_read_ds_file(const struct PDB_DS_HEADER
* pdb
,
2798 const struct PDB_DS_TOC
* toc
, DWORD file_nr
)
2800 const UINT
*block_list
;
2803 if (!toc
|| file_nr
>= toc
->num_files
) return NULL
;
2804 if (toc
->file_size
[file_nr
] == 0 || toc
->file_size
[file_nr
] == 0xFFFFFFFF) return NULL
;
2806 block_list
= &toc
->file_size
[toc
->num_files
];
2807 for (i
= 0; i
< file_nr
; i
++)
2808 block_list
+= (toc
->file_size
[i
] + pdb
->block_size
- 1) / pdb
->block_size
;
2810 return pdb_ds_read(pdb
, block_list
, toc
->file_size
[file_nr
]);
2813 static void* pdb_read_file(const struct pdb_file_info
* pdb_file
,
2816 switch (pdb_file
->kind
)
2819 return pdb_read_jg_file((const struct PDB_JG_HEADER
*)pdb_file
->image
,
2820 pdb_file
->u
.jg
.toc
, file_nr
);
2822 return pdb_read_ds_file((const struct PDB_DS_HEADER
*)pdb_file
->image
,
2823 pdb_file
->u
.ds
.toc
, file_nr
);
2828 static unsigned pdb_get_file_size(const struct pdb_file_info
* pdb_file
, DWORD file_nr
)
2830 switch (pdb_file
->kind
)
2832 case PDB_JG
: return pdb_file
->u
.jg
.toc
->file
[file_nr
].size
;
2833 case PDB_DS
: return pdb_file
->u
.ds
.toc
->file_size
[file_nr
];
2838 static void pdb_free(void* buffer
)
2840 HeapFree(GetProcessHeap(), 0, buffer
);
2843 static void pdb_free_file(struct pdb_file_info
* pdb_file
)
2845 switch (pdb_file
->kind
)
2848 pdb_free(pdb_file
->u
.jg
.toc
);
2849 pdb_file
->u
.jg
.toc
= NULL
;
2852 pdb_free(pdb_file
->u
.ds
.toc
);
2853 pdb_file
->u
.ds
.toc
= NULL
;
2856 HeapFree(GetProcessHeap(), 0, pdb_file
->stream_dict
);
2859 static BOOL
pdb_load_stream_name_table(struct pdb_file_info
* pdb_file
, const char* str
, unsigned cb
)
2867 pdw
= (DWORD
*)(str
+ cb
);
2871 pdb_file
->stream_dict
= HeapAlloc(GetProcessHeap(), 0, (numok
+ 1) * sizeof(struct pdb_stream_name
) + cb
);
2872 if (!pdb_file
->stream_dict
) return FALSE
;
2873 cpstr
= (char*)(pdb_file
->stream_dict
+ numok
+ 1);
2874 memcpy(cpstr
, str
, cb
);
2876 /* bitfield: first dword is len (in dword), then data */
2878 pdw
+= *ok_bits
++ + 1;
2881 FIXME("unexpected value\n");
2885 for (i
= j
= 0; i
< count
; i
++)
2887 if (ok_bits
[i
/ 32] & (1 << (i
% 32)))
2889 if (j
>= numok
) break;
2890 pdb_file
->stream_dict
[j
].name
= &cpstr
[*pdw
++];
2891 pdb_file
->stream_dict
[j
].index
= *pdw
++;
2896 pdb_file
->stream_dict
[numok
].name
= NULL
;
2897 pdb_file
->fpoext_stream
= -1;
2901 static unsigned pdb_get_stream_by_name(const struct pdb_file_info
* pdb_file
, const char* name
)
2903 struct pdb_stream_name
* psn
;
2905 for (psn
= pdb_file
->stream_dict
; psn
&& psn
->name
; psn
++)
2907 if (!strcmp(psn
->name
, name
)) return psn
->index
;
2912 static void* pdb_read_strings(const struct pdb_file_info
* pdb_file
)
2917 idx
= pdb_get_stream_by_name(pdb_file
, "/names");
2920 ret
= pdb_read_file( pdb_file
, idx
);
2921 if (ret
&& *(const DWORD
*)ret
== 0xeffeeffe) return ret
;
2924 WARN("string table not found\n");
2928 static void pdb_module_remove(struct process
* pcsn
, struct module_format
* modfmt
)
2932 for (i
= 0; i
< modfmt
->u
.pdb_info
->used_subfiles
; i
++)
2934 pdb_free_file(&modfmt
->u
.pdb_info
->pdb_files
[i
]);
2935 if (modfmt
->u
.pdb_info
->pdb_files
[i
].image
)
2936 UnmapViewOfFile(modfmt
->u
.pdb_info
->pdb_files
[i
].image
);
2937 if (modfmt
->u
.pdb_info
->pdb_files
[i
].hMap
)
2938 CloseHandle(modfmt
->u
.pdb_info
->pdb_files
[i
].hMap
);
2940 HeapFree(GetProcessHeap(), 0, modfmt
);
2943 static void pdb_convert_types_header(PDB_TYPES
* types
, const BYTE
* image
)
2945 memset(types
, 0, sizeof(PDB_TYPES
));
2948 if (*(const DWORD
*)image
< 19960000) /* FIXME: correct version? */
2950 /* Old version of the types record header */
2951 const PDB_TYPES_OLD
* old
= (const PDB_TYPES_OLD
*)image
;
2952 types
->version
= old
->version
;
2953 types
->type_offset
= sizeof(PDB_TYPES_OLD
);
2954 types
->type_size
= old
->type_size
;
2955 types
->first_index
= old
->first_index
;
2956 types
->last_index
= old
->last_index
;
2957 types
->file
= old
->file
;
2961 /* New version of the types record header */
2962 *types
= *(const PDB_TYPES
*)image
;
2966 static void pdb_convert_symbols_header(PDB_SYMBOLS
* symbols
,
2967 int* header_size
, const BYTE
* image
)
2969 memset(symbols
, 0, sizeof(PDB_SYMBOLS
));
2972 if (*(const DWORD
*)image
!= 0xffffffff)
2974 /* Old version of the symbols record header */
2975 const PDB_SYMBOLS_OLD
* old
= (const PDB_SYMBOLS_OLD
*)image
;
2976 symbols
->version
= 0;
2977 symbols
->module_size
= old
->module_size
;
2978 symbols
->offset_size
= old
->offset_size
;
2979 symbols
->hash_size
= old
->hash_size
;
2980 symbols
->srcmodule_size
= old
->srcmodule_size
;
2981 symbols
->pdbimport_size
= 0;
2982 symbols
->global_file
= old
->global_file
;
2983 symbols
->public_file
= old
->public_file
;
2984 symbols
->gsym_file
= old
->gsym_file
;
2986 *header_size
= sizeof(PDB_SYMBOLS_OLD
);
2990 /* New version of the symbols record header */
2991 *symbols
= *(const PDB_SYMBOLS
*)image
;
2992 *header_size
= sizeof(PDB_SYMBOLS
);
2996 static void pdb_convert_symbol_file(const PDB_SYMBOLS
* symbols
,
2997 PDB_SYMBOL_FILE_EX
* sfile
,
2998 unsigned* size
, const void* image
)
3001 if (symbols
->version
< 19970000)
3003 const PDB_SYMBOL_FILE
*sym_file
= image
;
3004 memset(sfile
, 0, sizeof(*sfile
));
3005 sfile
->file
= sym_file
->file
;
3006 sfile
->range
.index
= sym_file
->range
.index
;
3007 sfile
->symbol_size
= sym_file
->symbol_size
;
3008 sfile
->lineno_size
= sym_file
->lineno_size
;
3009 sfile
->lineno2_size
= sym_file
->lineno2_size
;
3010 *size
= sizeof(PDB_SYMBOL_FILE
) - 1;
3014 memcpy(sfile
, image
, sizeof(PDB_SYMBOL_FILE_EX
));
3015 *size
= sizeof(PDB_SYMBOL_FILE_EX
) - 1;
3019 static HANDLE
map_pdb_file(const struct process
* pcs
,
3020 const struct pdb_lookup
* lookup
,
3021 struct module
* module
)
3023 HANDLE hFile
, hMap
= NULL
;
3024 WCHAR dbg_file_path
[MAX_PATH
];
3027 switch (lookup
->kind
)
3030 ret
= path_find_symbol_file(pcs
, module
, lookup
->filename
, DMT_PDB
, NULL
, lookup
->timestamp
,
3031 lookup
->age
, dbg_file_path
, &module
->module
.PdbUnmatched
);
3034 ret
= path_find_symbol_file(pcs
, module
, lookup
->filename
, DMT_PDB
, &lookup
->guid
, 0,
3035 lookup
->age
, dbg_file_path
, &module
->module
.PdbUnmatched
);
3040 WARN("\tCouldn't find %s\n", lookup
->filename
);
3043 if ((hFile
= CreateFileW(dbg_file_path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
3044 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
)) != INVALID_HANDLE_VALUE
)
3046 hMap
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3052 static BOOL
pdb_init_type_parse(const struct msc_debug_info
* msc_dbg
,
3053 struct codeview_type_parse
* ctp
,
3061 pdb_convert_types_header(&types
, image
);
3063 /* Check for unknown versions */
3064 switch (types
.version
)
3066 case 19950410: /* VC 4.0 */
3068 case 19961031: /* VC 5.0 / 6.0 */
3069 case 19990903: /* VC 7.0 */
3070 case 20040203: /* VC 8.0 */
3073 ERR("-Unknown type info version %d\n", types
.version
);
3077 ctp
->module
= msc_dbg
->module
;
3078 /* reconstruct the types offset...
3079 * FIXME: maybe it's present in the newest PDB_TYPES structures
3081 total
= types
.last_index
- types
.first_index
+ 1;
3082 offset
= HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD
) * total
);
3083 if (!offset
) return FALSE
;
3084 ctp
->table
= ptr
= image
+ types
.type_offset
;
3086 while (ptr
< ctp
->table
+ types
.type_size
&& ctp
->num
< total
)
3088 offset
[ctp
->num
++] = ptr
- ctp
->table
;
3089 ptr
+= ((const union codeview_type
*)ptr
)->generic
.len
+ 2;
3091 ctp
->offset
= offset
;
3095 static void pdb_process_types(const struct msc_debug_info
* msc_dbg
,
3096 const struct pdb_file_info
* pdb_file
)
3098 struct codeview_type_parse ctp
;
3099 BYTE
* types_image
= pdb_read_file(pdb_file
, 2);
3103 if (pdb_init_type_parse(msc_dbg
, &ctp
, types_image
))
3105 /* Read type table */
3106 codeview_parse_type_table(&ctp
);
3107 HeapFree(GetProcessHeap(), 0, (DWORD
*)ctp
.offset
);
3109 pdb_free(types_image
);
3113 static const char PDB_JG_IDENT
[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0";
3114 static const char PDB_DS_IDENT
[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
3116 /******************************************************************
3119 * Tries to load a pdb file
3120 * 'matched' is filled with the number of correct matches for this file:
3121 * - age counts for one
3122 * - timestamp or guid depending on kind counts for one
3123 * a wrong kind of file returns FALSE (FIXME ?)
3125 static BOOL
pdb_init(const struct pdb_lookup
* pdb_lookup
, struct pdb_file_info
* pdb_file
,
3126 const char* image
, unsigned* matched
)
3130 /* check the file header, and if ok, load the TOC */
3131 TRACE("PDB(%s): %.40s\n", pdb_lookup
->filename
, debugstr_an(image
, 40));
3134 if (!memcmp(image
, PDB_JG_IDENT
, sizeof(PDB_JG_IDENT
)))
3136 const struct PDB_JG_HEADER
* pdb
= (const struct PDB_JG_HEADER
*)image
;
3137 struct PDB_JG_ROOT
* root
;
3139 pdb_file
->u
.jg
.toc
= pdb_jg_read(pdb
, pdb
->toc_block
, pdb
->toc
.size
);
3140 root
= pdb_read_jg_file(pdb
, pdb_file
->u
.jg
.toc
, 1);
3143 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup
->filename
);
3146 switch (root
->Version
)
3148 case 19950623: /* VC 4.0 */
3150 case 19960307: /* VC 5.0 */
3151 case 19970604: /* VC 6.0 */
3154 ERR("-Unknown root block version %d\n", root
->Version
);
3156 if (pdb_lookup
->kind
!= PDB_JG
)
3158 WARN("Found %s, but wrong PDB kind\n", pdb_lookup
->filename
);
3162 pdb_file
->kind
= PDB_JG
;
3163 pdb_file
->u
.jg
.timestamp
= root
->TimeDateStamp
;
3164 pdb_file
->age
= root
->Age
;
3165 if (root
->TimeDateStamp
== pdb_lookup
->timestamp
) (*matched
)++;
3166 else WARN("Found %s, but wrong signature: %08x %08x\n",
3167 pdb_lookup
->filename
, root
->TimeDateStamp
, pdb_lookup
->timestamp
);
3168 if (root
->Age
== pdb_lookup
->age
) (*matched
)++;
3169 else WARN("Found %s, but wrong age: %08x %08x\n",
3170 pdb_lookup
->filename
, root
->Age
, pdb_lookup
->age
);
3171 TRACE("found JG for %s: age=%x timestamp=%x\n",
3172 pdb_lookup
->filename
, root
->Age
, root
->TimeDateStamp
);
3173 ret
= pdb_load_stream_name_table(pdb_file
, &root
->names
[0], root
->cbNames
);
3176 else if (!memcmp(image
, PDB_DS_IDENT
, sizeof(PDB_DS_IDENT
)))
3178 const struct PDB_DS_HEADER
* pdb
= (const struct PDB_DS_HEADER
*)image
;
3179 struct PDB_DS_ROOT
* root
;
3181 pdb_file
->u
.ds
.toc
=
3182 pdb_ds_read(pdb
, (const UINT
*)((const char*)pdb
+ pdb
->toc_page
* pdb
->block_size
),
3184 root
= pdb_read_ds_file(pdb
, pdb_file
->u
.ds
.toc
, 1);
3187 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup
->filename
);
3190 switch (root
->Version
)
3195 ERR("-Unknown root block version %u\n", root
->Version
);
3197 pdb_file
->kind
= PDB_DS
;
3198 pdb_file
->u
.ds
.guid
= root
->guid
;
3199 pdb_file
->age
= root
->Age
;
3200 if (!memcmp(&root
->guid
, &pdb_lookup
->guid
, sizeof(GUID
))) (*matched
)++;
3201 else WARN("Found %s, but wrong GUID: %s %s\n",
3202 pdb_lookup
->filename
, debugstr_guid(&root
->guid
),
3203 debugstr_guid(&pdb_lookup
->guid
));
3204 if (root
->Age
== pdb_lookup
->age
) (*matched
)++;
3205 else WARN("Found %s, but wrong age: %08x %08x\n",
3206 pdb_lookup
->filename
, root
->Age
, pdb_lookup
->age
);
3207 TRACE("found DS for %s: age=%x guid=%s\n",
3208 pdb_lookup
->filename
, root
->Age
, debugstr_guid(&root
->guid
));
3209 ret
= pdb_load_stream_name_table(pdb_file
, &root
->names
[0], root
->cbNames
);
3214 if (0) /* some tool to dump the internal files from a PDB file */
3218 switch (pdb_file
->kind
)
3220 case PDB_JG
: num_files
= pdb_file
->u
.jg
.toc
->num_files
; break;
3221 case PDB_DS
: num_files
= pdb_file
->u
.ds
.toc
->num_files
; break;
3224 for (i
= 1; i
< num_files
; i
++)
3226 unsigned char* x
= pdb_read_file(pdb_file
, i
);
3227 FIXME("********************** [%u]: size=%08x\n",
3228 i
, pdb_get_file_size(pdb_file
, i
));
3229 dump(x
, pdb_get_file_size(pdb_file
, i
));
3236 static BOOL
pdb_process_internal(const struct process
* pcs
,
3237 const struct msc_debug_info
* msc_dbg
,
3238 const struct pdb_lookup
* pdb_lookup
,
3239 struct pdb_module_info
* pdb_module_info
,
3240 unsigned module_index
);
3242 static void pdb_process_symbol_imports(const struct process
* pcs
,
3243 const struct msc_debug_info
* msc_dbg
,
3244 const PDB_SYMBOLS
* symbols
,
3245 const void* symbols_image
,
3247 const struct pdb_lookup
* pdb_lookup
,
3248 struct pdb_module_info
* pdb_module_info
,
3249 unsigned module_index
)
3251 if (module_index
== -1 && symbols
&& symbols
->pdbimport_size
)
3253 const PDB_SYMBOL_IMPORT
*imp
;
3258 struct pdb_file_info sf0
= pdb_module_info
->pdb_files
[0];
3260 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)symbols_image
+ sizeof(PDB_SYMBOLS
) +
3261 symbols
->module_size
+ symbols
->offset_size
+
3262 symbols
->hash_size
+ symbols
->srcmodule_size
);
3264 last
= (const char*)imp
+ symbols
->pdbimport_size
;
3265 while (imp
< (const PDB_SYMBOL_IMPORT
*)last
)
3267 ptr
= (const char*)imp
+ sizeof(*imp
) + strlen(imp
->filename
);
3268 if (i
>= CV_MAX_MODULES
) FIXME("Out of bounds!!!\n");
3269 if (!stricmp(pdb_lookup
->filename
, imp
->filename
))
3271 if (module_index
!= -1) FIXME("Twice the entry\n");
3272 else module_index
= i
;
3273 pdb_module_info
->pdb_files
[i
] = sf0
;
3277 struct pdb_lookup imp_pdb_lookup
;
3279 /* FIXME: this is an import of a JG PDB file
3280 * how's a DS PDB handled ?
3282 imp_pdb_lookup
.filename
= imp
->filename
;
3283 imp_pdb_lookup
.kind
= PDB_JG
;
3284 imp_pdb_lookup
.timestamp
= imp
->TimeDateStamp
;
3285 imp_pdb_lookup
.age
= imp
->Age
;
3286 TRACE("got for %s: age=%u ts=%x\n",
3287 imp
->filename
, imp
->Age
, imp
->TimeDateStamp
);
3288 pdb_process_internal(pcs
, msc_dbg
, &imp_pdb_lookup
, pdb_module_info
, i
);
3291 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)first
+ ((ptr
- (const char*)first
+ strlen(ptr
) + 1 + 3) & ~3));
3293 pdb_module_info
->used_subfiles
= i
;
3295 if (module_index
== -1)
3298 pdb_module_info
->used_subfiles
= 1;
3300 cv_current_module
= &cv_zmodules
[module_index
];
3301 if (cv_current_module
->allowed
) FIXME("Already allowed??\n");
3302 cv_current_module
->allowed
= TRUE
;
3305 static BOOL
pdb_process_internal(const struct process
* pcs
,
3306 const struct msc_debug_info
* msc_dbg
,
3307 const struct pdb_lookup
* pdb_lookup
,
3308 struct pdb_module_info
* pdb_module_info
,
3309 unsigned module_index
)
3313 BYTE
* symbols_image
= NULL
;
3314 char* files_image
= NULL
;
3315 DWORD files_size
= 0;
3317 struct pdb_file_info
* pdb_file
;
3319 TRACE("Processing PDB file %s\n", pdb_lookup
->filename
);
3321 pdb_file
= &pdb_module_info
->pdb_files
[module_index
== -1 ? 0 : module_index
];
3322 /* Open and map() .PDB file */
3323 if ((hMap
= map_pdb_file(pcs
, pdb_lookup
, msc_dbg
->module
)) == NULL
||
3324 ((image
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) == NULL
))
3326 WARN("Unable to open .PDB file: %s\n", pdb_lookup
->filename
);
3330 if (!pdb_init(pdb_lookup
, pdb_file
, image
, &matched
) || matched
!= 2)
3333 UnmapViewOfFile(image
);
3337 pdb_file
->hMap
= hMap
;
3338 pdb_file
->image
= image
;
3339 symbols_image
= pdb_read_file(pdb_file
, 3);
3342 PDB_SYMBOLS symbols
;
3346 struct codeview_type_parse ipi_ctp
;
3348 int header_size
= 0;
3349 PDB_STREAM_INDEXES
* psi
;
3352 pdb_convert_symbols_header(&symbols
, &header_size
, symbols_image
);
3353 switch (symbols
.version
)
3355 case 0: /* VC 4.0 */
3356 case 19960307: /* VC 5.0 */
3357 case 19970606: /* VC 6.0 */
3361 ERR("-Unknown symbol info version %u %08x\n",
3362 symbols
.version
, symbols
.version
);
3365 switch (symbols
.stream_index_size
)
3368 case sizeof(PDB_STREAM_INDEXES_OLD
):
3369 /* no fpo ext stream in this case */
3371 case sizeof(PDB_STREAM_INDEXES
):
3372 psi
= (PDB_STREAM_INDEXES
*)((const char*)symbols_image
+ sizeof(PDB_SYMBOLS
) +
3373 symbols
.module_size
+ symbols
.offset_size
+
3374 symbols
.hash_size
+ symbols
.srcmodule_size
+
3375 symbols
.pdbimport_size
+ symbols
.unknown2_size
);
3376 pdb_file
->fpoext_stream
= psi
->FPO_EXT
;
3379 FIXME("Unknown PDB_STREAM_INDEXES size (%u)\n", symbols
.stream_index_size
);
3380 pdb_free(symbols_image
);
3383 files_image
= pdb_read_strings(pdb_file
);
3384 if (files_image
) files_size
= *(const DWORD
*)(files_image
+ 8);
3386 pdb_process_symbol_imports(pcs
, msc_dbg
, &symbols
, symbols_image
, image
,
3387 pdb_lookup
, pdb_module_info
, module_index
);
3388 pdb_process_types(msc_dbg
, pdb_file
);
3390 ipi_image
= pdb_read_file(pdb_file
, 4);
3391 ipi_ok
= pdb_init_type_parse(msc_dbg
, &ipi_ctp
, ipi_image
);
3393 /* Read global symbol table */
3394 globalimage
= pdb_read_file(pdb_file
, symbols
.gsym_file
);
3397 codeview_snarf(msc_dbg
, globalimage
, 0, pdb_get_file_size(pdb_file
, symbols
.gsym_file
),
3401 /* Read per-module symbols' tables */
3402 file
= symbols_image
+ header_size
;
3403 while (file
- symbols_image
< header_size
+ symbols
.module_size
)
3405 PDB_SYMBOL_FILE_EX sfile
;
3406 const char* file_name
;
3409 HeapValidate(GetProcessHeap(), 0, NULL
);
3410 pdb_convert_symbol_file(&symbols
, &sfile
, &size
, file
);
3412 modimage
= pdb_read_file(pdb_file
, sfile
.file
);
3415 struct cv_module_snarf cvmod
= {ipi_ok
? &ipi_ctp
: NULL
, (const void*)(modimage
+ sfile
.symbol_size
), sfile
.lineno2_size
,
3416 files_image
+ 12, files_size
};
3417 codeview_snarf(msc_dbg
, modimage
, sizeof(DWORD
), sfile
.symbol_size
,
3420 if (sfile
.lineno_size
&& sfile
.lineno2_size
)
3421 FIXME("Both line info present... only supporting second\n");
3422 else if (sfile
.lineno_size
)
3423 codeview_snarf_linetab(msc_dbg
,
3424 modimage
+ sfile
.symbol_size
,
3426 pdb_file
->kind
== PDB_JG
);
3430 file_name
= (const char*)file
+ size
;
3431 file_name
+= strlen(file_name
) + 1;
3432 file
= (BYTE
*)((DWORD_PTR
)(file_name
+ strlen(file_name
) + 1 + 3) & ~3);
3434 /* finish the remaining public and global information */
3437 codeview_snarf_public(msc_dbg
, globalimage
, 0,
3438 pdb_get_file_size(pdb_file
, symbols
.gsym_file
));
3439 pdb_free(globalimage
);
3441 HeapFree(GetProcessHeap(), 0, (DWORD
*)ipi_ctp
.offset
);
3442 pdb_free(ipi_image
);
3445 pdb_process_symbol_imports(pcs
, msc_dbg
, NULL
, NULL
, image
,
3446 pdb_lookup
, pdb_module_info
, module_index
);
3448 pdb_free(symbols_image
);
3449 pdb_free(files_image
);
3454 static BOOL
pdb_process_file(const struct process
* pcs
,
3455 const struct msc_debug_info
* msc_dbg
,
3456 struct pdb_lookup
* pdb_lookup
)
3459 struct module_format
* modfmt
;
3460 struct pdb_module_info
* pdb_module_info
;
3462 modfmt
= HeapAlloc(GetProcessHeap(), 0,
3463 sizeof(struct module_format
) + sizeof(struct pdb_module_info
));
3464 if (!modfmt
) return FALSE
;
3466 pdb_module_info
= (void*)(modfmt
+ 1);
3467 msc_dbg
->module
->format_info
[DFI_PDB
] = modfmt
;
3468 modfmt
->module
= msc_dbg
->module
;
3469 modfmt
->remove
= pdb_module_remove
;
3470 modfmt
->loc_compute
= pdb_location_compute
;
3471 modfmt
->u
.pdb_info
= pdb_module_info
;
3473 memset(cv_zmodules
, 0, sizeof(cv_zmodules
));
3474 codeview_init_basic_types(msc_dbg
->module
);
3475 ret
= pdb_process_internal(pcs
, msc_dbg
, pdb_lookup
,
3476 msc_dbg
->module
->format_info
[DFI_PDB
]->u
.pdb_info
, -1);
3477 codeview_clear_type_table();
3480 struct pdb_module_info
* pdb_info
= msc_dbg
->module
->format_info
[DFI_PDB
]->u
.pdb_info
;
3481 msc_dbg
->module
->module
.SymType
= SymPdb
;
3482 if (pdb_info
->pdb_files
[0].kind
== PDB_JG
)
3483 msc_dbg
->module
->module
.PdbSig
= pdb_info
->pdb_files
[0].u
.jg
.timestamp
;
3485 msc_dbg
->module
->module
.PdbSig70
= pdb_info
->pdb_files
[0].u
.ds
.guid
;
3486 msc_dbg
->module
->module
.PdbAge
= pdb_info
->pdb_files
[0].age
;
3487 MultiByteToWideChar(CP_ACP
, 0, pdb_lookup
->filename
, -1,
3488 msc_dbg
->module
->module
.LoadedPdbName
,
3489 ARRAY_SIZE(msc_dbg
->module
->module
.LoadedPdbName
));
3490 /* FIXME: we could have a finer grain here */
3491 msc_dbg
->module
->module
.LineNumbers
= TRUE
;
3492 msc_dbg
->module
->module
.GlobalSymbols
= TRUE
;
3493 msc_dbg
->module
->module
.TypeInfo
= TRUE
;
3494 msc_dbg
->module
->module
.SourceIndexed
= TRUE
;
3495 msc_dbg
->module
->module
.Publics
= TRUE
;
3499 msc_dbg
->module
->format_info
[DFI_PDB
] = NULL
;
3500 HeapFree(GetProcessHeap(), 0, modfmt
);
3505 BOOL
pdb_fetch_file_info(const struct pdb_lookup
* pdb_lookup
, unsigned* matched
)
3507 HANDLE hFile
, hMap
= NULL
;
3510 struct pdb_file_info pdb_file
;
3512 if ((hFile
= CreateFileA(pdb_lookup
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
3513 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
)) == INVALID_HANDLE_VALUE
||
3514 ((hMap
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
)) == NULL
) ||
3515 ((image
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) == NULL
))
3517 WARN("Unable to open .PDB file: %s\n", pdb_lookup
->filename
);
3522 ret
= pdb_init(pdb_lookup
, &pdb_file
, image
, matched
);
3523 pdb_free_file(&pdb_file
);
3526 if (image
) UnmapViewOfFile(image
);
3527 if (hMap
) CloseHandle(hMap
);
3528 if (hFile
!= INVALID_HANDLE_VALUE
) CloseHandle(hFile
);
3533 /*========================================================================
3534 * FPO unwinding code
3537 /* Stack unwinding is based on postfixed operations.
3538 * Let's define our Postfix EValuator
3540 #define PEV_MAX_LEN 32
3543 struct cpu_stack_walk
* csw
;
3545 struct vector stack
;
3547 struct hash_table values
;
3554 struct hash_table_elt elt
;
3557 #define PEV_ERROR(pev, msg) snprintf((pev)->error, sizeof((pev)->error), "%s", (msg))
3558 #define PEV_ERROR1(pev, msg, pmt) snprintf((pev)->error, sizeof((pev)->error), (msg), (pmt))
3561 static void pev_dump_stack(struct pevaluator
* pev
)
3564 FIXME("stack #%d\n", pev
->stk_index
);
3565 for (i
= 0; i
< pev
->stk_index
; i
++)
3567 FIXME("\t%d) %s\n", i
, *(char**)vector_at(&pev
->stack
, i
));
3572 /* get the value out of an operand (variable or literal) */
3573 static BOOL
pev_get_val(struct pevaluator
* pev
, const char* str
, DWORD_PTR
* val
)
3576 struct hash_table_iter hti
;
3583 hash_table_iter_init(&pev
->values
, &hti
, str
);
3584 while ((ptr
= hash_table_iter_up(&hti
)))
3586 if (!strcmp(CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->elt
.name
, str
))
3588 *val
= CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->value
;
3592 return PEV_ERROR1(pev
, "get_zvalue: no value found (%s)", str
);
3594 *val
= strtol(str
, &n
, 10);
3595 if (n
== str
|| *n
!= '\0')
3596 return PEV_ERROR1(pev
, "get_val: not a literal (%s)", str
);
3601 /* push an operand onto the stack */
3602 static BOOL
pev_push(struct pevaluator
* pev
, const char* elt
)
3605 if (pev
->stk_index
< vector_length(&pev
->stack
))
3606 at
= vector_at(&pev
->stack
, pev
->stk_index
);
3608 at
= vector_add(&pev
->stack
, &pev
->pool
);
3609 if (!at
) return PEV_ERROR(pev
, "push: out of memory");
3610 *at
= pool_strdup(&pev
->pool
, elt
);
3615 /* pop an operand from the stack */
3616 static BOOL
pev_pop(struct pevaluator
* pev
, char* elt
)
3618 char** at
= vector_at(&pev
->stack
, --pev
->stk_index
);
3619 if (!at
) return PEV_ERROR(pev
, "pop: stack empty");
3624 /* pop an operand from the stack, and gets its value */
3625 static BOOL
pev_pop_val(struct pevaluator
* pev
, DWORD_PTR
* val
)
3627 char p
[PEV_MAX_LEN
];
3629 return pev_pop(pev
, p
) && pev_get_val(pev
, p
, val
);
3632 /* set var 'name' a new value (creates the var if it doesn't exist) */
3633 static BOOL
pev_set_value(struct pevaluator
* pev
, const char* name
, DWORD_PTR val
)
3635 struct hash_table_iter hti
;
3638 hash_table_iter_init(&pev
->values
, &hti
, name
);
3639 while ((ptr
= hash_table_iter_up(&hti
)))
3641 if (!strcmp(CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->elt
.name
, name
))
3643 CONTAINING_RECORD(ptr
, struct zvalue
, elt
)->value
= val
;
3649 struct zvalue
* zv
= pool_alloc(&pev
->pool
, sizeof(*zv
));
3650 if (!zv
) return PEV_ERROR(pev
, "set_value: out of memory");
3653 zv
->elt
.name
= pool_strdup(&pev
->pool
, name
);
3654 hash_table_add(&pev
->values
, &zv
->elt
);
3659 /* execute a binary operand from the two top most values on the stack.
3660 * puts result on top of the stack */
3661 static BOOL
pev_binop(struct pevaluator
* pev
, char op
)
3663 char res
[PEV_MAX_LEN
];
3664 DWORD_PTR v1
, v2
, c
;
3666 if (!pev_pop_val(pev
, &v1
) || !pev_pop_val(pev
, &v2
)) return FALSE
;
3669 case '+': c
= v1
+ v2
; break;
3670 case '-': c
= v1
- v2
; break;
3671 case '*': c
= v1
* v2
; break;
3672 case '/': c
= v1
/ v2
; break;
3673 case '%': c
= v1
% v2
; break;
3674 default: return PEV_ERROR1(pev
, "binop: unknown op (%c)", op
);
3676 snprintf(res
, sizeof(res
), "%Id", c
);
3681 /* pops top most operand, dereference it, on pushes the result on top of the stack */
3682 static BOOL
pev_deref(struct pevaluator
* pev
)
3684 char res
[PEV_MAX_LEN
];
3685 DWORD_PTR v1
, v2
= 0;
3687 if (!pev_pop_val(pev
, &v1
)) return FALSE
;
3688 if (!sw_read_mem(pev
->csw
, v1
, &v2
, pev
->csw
->cpu
->word_size
))
3689 return PEV_ERROR1(pev
, "deref: cannot read mem at %Ix\n", v1
);
3690 snprintf(res
, sizeof(res
), "%Id", v2
);
3695 /* assign value to variable (from two top most operands) */
3696 static BOOL
pev_assign(struct pevaluator
* pev
)
3698 char p2
[PEV_MAX_LEN
];
3701 if (!pev_pop_val(pev
, &v1
) || !pev_pop(pev
, p2
)) return FALSE
;
3702 if (p2
[0] != '$') return PEV_ERROR1(pev
, "assign: %s isn't a variable", p2
);
3703 pev_set_value(pev
, p2
, v1
);
3708 /* initializes the postfix evaluator */
3709 static void pev_init(struct pevaluator
* pev
, struct cpu_stack_walk
* csw
,
3710 PDB_FPO_DATA
* fpoext
, struct pdb_cmd_pair
* cpair
)
3713 pool_init(&pev
->pool
, 512);
3714 vector_init(&pev
->stack
, sizeof(char*), 8);
3716 hash_table_init(&pev
->pool
, &pev
->values
, 8);
3717 pev
->error
[0] = '\0';
3718 for (; cpair
->name
; cpair
++)
3719 pev_set_value(pev
, cpair
->name
, *cpair
->pvalue
);
3720 pev_set_value(pev
, ".raSearchStart", fpoext
->start
);
3721 pev_set_value(pev
, ".cbLocals", fpoext
->locals_size
);
3722 pev_set_value(pev
, ".cbParams", fpoext
->params_size
);
3723 pev_set_value(pev
, ".cbSavedRegs", fpoext
->savedregs_size
);
3726 static BOOL
pev_free(struct pevaluator
* pev
, struct pdb_cmd_pair
* cpair
)
3730 if (cpair
) for (; cpair
->name
; cpair
++)
3732 if (pev_get_val(pev
, cpair
->name
, &val
))
3733 *cpair
->pvalue
= val
;
3735 pool_destroy(&pev
->pool
);
3739 static BOOL
pdb_parse_cmd_string(struct cpu_stack_walk
* csw
, PDB_FPO_DATA
* fpoext
,
3740 const char* cmd
, struct pdb_cmd_pair
* cpair
)
3742 char token
[PEV_MAX_LEN
];
3746 struct pevaluator pev
;
3748 pev_init(&pev
, csw
, fpoext
, cpair
);
3749 for (ptr
= cmd
; !over
; ptr
++)
3751 if (*ptr
== ' ' || (over
= *ptr
== '\0'))
3755 if (!strcmp(token
, "+") || !strcmp(token
, "-") || !strcmp(token
, "*") ||
3756 !strcmp(token
, "/") || !strcmp(token
, "%"))
3758 if (!pev_binop(&pev
, token
[0])) goto done
;
3760 else if (!strcmp(token
, "^"))
3762 if (!pev_deref(&pev
)) goto done
;
3764 else if (!strcmp(token
, "="))
3766 if (!pev_assign(&pev
)) goto done
;
3770 if (!pev_push(&pev
, token
)) goto done
;
3776 if (ptok
- token
>= PEV_MAX_LEN
- 1)
3778 PEV_ERROR1(&pev
, "parse: token too long (%s)", ptr
- (ptok
- token
));
3784 pev_free(&pev
, cpair
);
3787 FIXME("Couldn't evaluate %s => %s\n", wine_dbgstr_a(cmd
), pev
.error
);
3788 pev_free(&pev
, NULL
);
3792 BOOL
pdb_virtual_unwind(struct cpu_stack_walk
*csw
, DWORD_PTR ip
,
3793 union ctx
*context
, struct pdb_cmd_pair
*cpair
)
3795 struct module_pair pair
;
3796 struct pdb_module_info
* pdb_info
;
3797 PDB_FPO_DATA
* fpoext
;
3798 unsigned i
, size
, strsize
;
3802 if (!module_init_pair(&pair
, csw
->hProcess
, ip
)) return FALSE
;
3803 if (!pair
.effective
->format_info
[DFI_PDB
]) return FALSE
;
3804 pdb_info
= pair
.effective
->format_info
[DFI_PDB
]->u
.pdb_info
;
3805 TRACE("searching %Ix => %Ix\n", ip
, ip
- (DWORD_PTR
)pair
.effective
->module
.BaseOfImage
);
3806 ip
-= (DWORD_PTR
)pair
.effective
->module
.BaseOfImage
;
3808 strbase
= pdb_read_strings(&pdb_info
->pdb_files
[0]);
3809 if (!strbase
) return FALSE
;
3810 strsize
= *(const DWORD
*)(strbase
+ 8);
3811 fpoext
= pdb_read_file(&pdb_info
->pdb_files
[0], pdb_info
->pdb_files
[0].fpoext_stream
);
3812 size
= pdb_get_file_size(&pdb_info
->pdb_files
[0], pdb_info
->pdb_files
[0].fpoext_stream
);
3813 if (fpoext
&& (size
% sizeof(*fpoext
)) == 0)
3815 size
/= sizeof(*fpoext
);
3816 for (i
= 0; i
< size
; i
++)
3818 if (fpoext
[i
].start
<= ip
&& ip
< fpoext
[i
].start
+ fpoext
[i
].func_size
)
3820 TRACE("\t%08x %08x %8x %8x %4x %4x %4x %08x %s\n",
3821 fpoext
[i
].start
, fpoext
[i
].func_size
, fpoext
[i
].locals_size
,
3822 fpoext
[i
].params_size
, fpoext
[i
].maxstack_size
, fpoext
[i
].prolog_size
,
3823 fpoext
[i
].savedregs_size
, fpoext
[i
].flags
,
3824 fpoext
[i
].str_offset
< strsize
?
3825 wine_dbgstr_a(strbase
+ 12 + fpoext
[i
].str_offset
) : "<out of bounds>");
3826 if (fpoext
[i
].str_offset
< strsize
)
3827 ret
= pdb_parse_cmd_string(csw
, &fpoext
[i
], strbase
+ 12 + fpoext
[i
].str_offset
, cpair
);
3841 /*========================================================================
3842 * Process CodeView debug information.
3845 #define MAKESIG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
3846 #define CODEVIEW_NB09_SIG MAKESIG('N','B','0','9')
3847 #define CODEVIEW_NB10_SIG MAKESIG('N','B','1','0')
3848 #define CODEVIEW_NB11_SIG MAKESIG('N','B','1','1')
3849 #define CODEVIEW_RSDS_SIG MAKESIG('R','S','D','S')
3851 static BOOL
codeview_process_info(const struct process
* pcs
,
3852 const struct msc_debug_info
* msc_dbg
)
3854 const DWORD
* signature
= (const DWORD
*)msc_dbg
->root
;
3856 struct pdb_lookup pdb_lookup
;
3858 TRACE("Processing signature %.4s\n", (const char*)signature
);
3862 case CODEVIEW_NB09_SIG
:
3863 case CODEVIEW_NB11_SIG
:
3865 const OMFSignature
* cv
= (const OMFSignature
*)msc_dbg
->root
;
3866 const OMFDirHeader
* hdr
= (const OMFDirHeader
*)(msc_dbg
->root
+ cv
->filepos
);
3867 const OMFDirEntry
* ent
;
3868 const OMFDirEntry
* prev
;
3869 const OMFDirEntry
* next
;
3872 codeview_init_basic_types(msc_dbg
->module
);
3874 for (i
= 0; i
< hdr
->cDir
; i
++)
3876 ent
= (const OMFDirEntry
*)((const BYTE
*)hdr
+ hdr
->cbDirHeader
+ i
* hdr
->cbDirEntry
);
3877 if (ent
->SubSection
== sstGlobalTypes
)
3879 const OMFGlobalTypes
* types
;
3880 struct codeview_type_parse ctp
;
3882 types
= (const OMFGlobalTypes
*)(msc_dbg
->root
+ ent
->lfo
);
3883 ctp
.module
= msc_dbg
->module
;
3884 ctp
.offset
= (const DWORD
*)(types
+ 1);
3885 ctp
.num
= types
->cTypes
;
3886 ctp
.table
= (const BYTE
*)(ctp
.offset
+ types
->cTypes
);
3888 cv_current_module
= &cv_zmodules
[0];
3889 if (cv_current_module
->allowed
) FIXME("Already allowed??\n");
3890 cv_current_module
->allowed
= TRUE
;
3892 codeview_parse_type_table(&ctp
);
3897 ent
= (const OMFDirEntry
*)((const BYTE
*)hdr
+ hdr
->cbDirHeader
);
3898 for (i
= 0; i
< hdr
->cDir
; i
++, ent
= next
)
3900 next
= (i
== hdr
->cDir
-1) ? NULL
:
3901 (const OMFDirEntry
*)((const BYTE
*)ent
+ hdr
->cbDirEntry
);
3902 prev
= (i
== 0) ? NULL
:
3903 (const OMFDirEntry
*)((const BYTE
*)ent
- hdr
->cbDirEntry
);
3905 if (ent
->SubSection
== sstAlignSym
)
3907 codeview_snarf(msc_dbg
, msc_dbg
->root
+ ent
->lfo
, sizeof(DWORD
), ent
->cb
,
3911 * Check the next and previous entry. If either is a
3912 * sstSrcModule, it contains the line number info for
3915 * FIXME: This is not a general solution!
3917 if (next
&& next
->iMod
== ent
->iMod
&& next
->SubSection
== sstSrcModule
)
3918 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ next
->lfo
,
3921 if (prev
&& prev
->iMod
== ent
->iMod
&& prev
->SubSection
== sstSrcModule
)
3922 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ prev
->lfo
,
3928 msc_dbg
->module
->module
.SymType
= SymCv
;
3929 /* FIXME: we could have a finer grain here */
3930 msc_dbg
->module
->module
.LineNumbers
= TRUE
;
3931 msc_dbg
->module
->module
.GlobalSymbols
= TRUE
;
3932 msc_dbg
->module
->module
.TypeInfo
= TRUE
;
3933 msc_dbg
->module
->module
.SourceIndexed
= TRUE
;
3934 msc_dbg
->module
->module
.Publics
= TRUE
;
3935 codeview_clear_type_table();
3940 case CODEVIEW_NB10_SIG
:
3942 const CODEVIEW_PDB_DATA
* pdb
= (const CODEVIEW_PDB_DATA
*)msc_dbg
->root
;
3943 pdb_lookup
.filename
= pdb
->name
;
3944 pdb_lookup
.kind
= PDB_JG
;
3945 pdb_lookup
.timestamp
= pdb
->timestamp
;
3946 pdb_lookup
.age
= pdb
->age
;
3947 ret
= pdb_process_file(pcs
, msc_dbg
, &pdb_lookup
);
3950 case CODEVIEW_RSDS_SIG
:
3952 const OMFSignatureRSDS
* rsds
= (const OMFSignatureRSDS
*)msc_dbg
->root
;
3954 TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
3955 wine_dbgstr_guid(&rsds
->guid
), rsds
->age
, rsds
->name
);
3956 pdb_lookup
.filename
= rsds
->name
;
3957 pdb_lookup
.kind
= PDB_DS
;
3958 pdb_lookup
.guid
= rsds
->guid
;
3959 pdb_lookup
.age
= rsds
->age
;
3960 ret
= pdb_process_file(pcs
, msc_dbg
, &pdb_lookup
);
3964 ERR("Unknown CODEVIEW signature %08lx in module %s\n",
3965 *signature
, debugstr_w(msc_dbg
->module
->modulename
));
3970 msc_dbg
->module
->module
.CVSig
= *signature
;
3971 memcpy(msc_dbg
->module
->module
.CVData
, msc_dbg
->root
,
3972 sizeof(msc_dbg
->module
->module
.CVData
));
3977 /*========================================================================
3978 * Process debug directory.
3980 BOOL
pe_load_debug_directory(const struct process
* pcs
, struct module
* module
,
3981 const BYTE
* mapping
,
3982 const IMAGE_SECTION_HEADER
* sectp
, DWORD nsect
,
3983 const IMAGE_DEBUG_DIRECTORY
* dbg
, int nDbg
)
3987 struct msc_debug_info msc_dbg
;
3989 msc_dbg
.module
= module
;
3990 msc_dbg
.nsect
= nsect
;
3991 msc_dbg
.sectp
= sectp
;
3993 msc_dbg
.omapp
= NULL
;
3999 /* First, watch out for OMAP data */
4000 for (i
= 0; i
< nDbg
; i
++)
4002 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_OMAP_FROM_SRC
)
4004 msc_dbg
.nomap
= dbg
[i
].SizeOfData
/ sizeof(OMAP
);
4005 msc_dbg
.omapp
= (const OMAP
*)(mapping
+ dbg
[i
].PointerToRawData
);
4010 /* Now, try to parse CodeView debug info */
4011 for (i
= 0; i
< nDbg
; i
++)
4013 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
4015 msc_dbg
.root
= mapping
+ dbg
[i
].PointerToRawData
;
4016 if ((ret
= codeview_process_info(pcs
, &msc_dbg
))) goto done
;
4020 /* If not found, try to parse COFF debug info */
4021 for (i
= 0; i
< nDbg
; i
++)
4023 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_COFF
)
4025 msc_dbg
.root
= mapping
+ dbg
[i
].PointerToRawData
;
4026 if ((ret
= coff_process_info(&msc_dbg
))) goto done
;
4030 /* FIXME: this should be supported... this is the debug information for
4031 * functions compiled without a frame pointer (FPO = frame pointer omission)
4032 * the associated data helps finding out the relevant information
4034 for (i
= 0; i
< nDbg
; i
++)
4035 if (dbg
[i
].Type
== IMAGE_DEBUG_TYPE_FPO
)
4036 FIXME("This guy has FPO information\n");
4040 #define FRAME_TRAP 1
4043 typedef struct _FPO_DATA
4045 DWORD ulOffStart
; /* offset 1st byte of function code */
4046 DWORD cbProcSize
; /* # bytes in function */
4047 DWORD cdwLocals
; /* # bytes in locals/4 */
4048 WORD cdwParams
; /* # bytes in params/4 */
4050 WORD cbProlog
: 8; /* # bytes in prolog */
4051 WORD cbRegs
: 3; /* # regs saved */
4052 WORD fHasSEH
: 1; /* TRUE if SEH in func */
4053 WORD fUseBP
: 1; /* TRUE if EBP has been allocated */
4054 WORD reserved
: 1; /* reserved for future use */
4055 WORD cbFrame
: 2; /* frame type */
4062 ERR("Got a page fault while loading symbols\n");