Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winedump/msc.c
8736 views
1
/*
2
* MS debug info dumping utility
3
*
4
* Copyright 2006 Eric Pouech
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include "config.h"
22
23
#include <stdlib.h>
24
#include <stdarg.h>
25
#include <stdio.h>
26
#include <time.h>
27
#include <fcntl.h>
28
29
#include "windef.h"
30
#include "winbase.h"
31
#include "winedump.h"
32
#include "cvconst.h"
33
34
#define PSTRING(adr, ofs) \
35
((const struct p_string*)((const char*)(adr) + (ofs)))
36
37
static const char* p_string(const struct p_string* s)
38
{
39
static char tmp[256 + 1];
40
memcpy(tmp, s->name, s->namelen);
41
tmp[s->namelen] = '\0';
42
return tmp;
43
}
44
45
struct full_value
46
{
47
enum {fv_integer, fv_longlong} type;
48
union
49
{
50
int i;
51
long long unsigned llu;
52
} v;
53
};
54
55
static int full_numeric_leaf(struct full_value *fv, const unsigned char *leaf)
56
{
57
unsigned short int type = *(const unsigned short *)leaf;
58
int length = 2;
59
60
leaf += length;
61
fv->type = fv_integer;
62
if (type < LF_NUMERIC)
63
{
64
fv->v.i = type;
65
}
66
else
67
{
68
switch (type)
69
{
70
case LF_CHAR:
71
length += 1;
72
fv->v.i = *(const char*)leaf;
73
break;
74
75
case LF_SHORT:
76
length += 2;
77
fv->v.i = *(const short*)leaf;
78
break;
79
80
case LF_USHORT:
81
length += 2;
82
fv->v.i = *(const unsigned short*)leaf;
83
break;
84
85
case LF_LONG:
86
length += 4;
87
fv->v.i = *(const int*)leaf;
88
break;
89
90
case LF_ULONG:
91
length += 4;
92
fv->v.i = *(const unsigned int*)leaf;
93
break;
94
95
case LF_QUADWORD:
96
length += 8;
97
fv->type = fv_longlong;
98
fv->v.llu = *(const long long int*)leaf;
99
break;
100
101
case LF_UQUADWORD:
102
length += 8;
103
fv->type = fv_longlong;
104
fv->v.llu = *(const long long unsigned int*)leaf;
105
break;
106
107
case LF_REAL32:
108
length += 4;
109
printf(">>> unsupported leaf value %04x\n", type);
110
fv->v.i = 0; /* FIXME */
111
break;
112
113
case LF_REAL48:
114
length += 6;
115
fv->v.i = 0; /* FIXME */
116
printf(">>> unsupported leaf value %04x\n", type);
117
break;
118
119
case LF_REAL64:
120
length += 8;
121
fv->v.i = 0; /* FIXME */
122
printf(">>> unsupported leaf value %04x\n", type);
123
break;
124
125
case LF_REAL80:
126
length += 10;
127
fv->v.i = 0; /* FIXME */
128
printf(">>> unsupported leaf value %04x\n", type);
129
break;
130
131
case LF_REAL128:
132
length += 16;
133
fv->v.i = 0; /* FIXME */
134
printf(">>> unsupported leaf value %04x\n", type);
135
break;
136
137
case LF_COMPLEX32:
138
length += 4;
139
fv->v.i = 0; /* FIXME */
140
printf(">>> unsupported leaf value %04x\n", type);
141
break;
142
143
case LF_COMPLEX64:
144
length += 8;
145
fv->v.i = 0; /* FIXME */
146
printf(">>> unsupported leaf value %04x\n", type);
147
break;
148
149
case LF_COMPLEX80:
150
length += 10;
151
fv->v.i = 0; /* FIXME */
152
printf(">>> unsupported leaf value %04x\n", type);
153
break;
154
155
case LF_COMPLEX128:
156
length += 16;
157
fv->v.i = 0; /* FIXME */
158
printf(">>> unsupported leaf value %04x\n", type);
159
break;
160
161
case LF_VARSTRING:
162
length += 2 + *leaf;
163
fv->v.i = 0; /* FIXME */
164
printf(">>> unsupported leaf value %04x\n", type);
165
break;
166
167
default:
168
printf(">>> Unsupported numeric leaf-id %04x\n", type);
169
fv->v.i = 0;
170
break;
171
}
172
}
173
return length;
174
}
175
176
static const char* full_value_string(const struct full_value* fv)
177
{
178
static char tmp[128];
179
180
switch (fv->type)
181
{
182
case fv_integer: sprintf(tmp, "0x%x", fv->v.i); break;
183
case fv_longlong: sprintf(tmp, "0x%x%08x", (unsigned)(fv->v.llu >> 32), (unsigned)fv->v.llu); break;
184
}
185
return tmp;
186
}
187
188
static int numeric_leaf(int* value, const unsigned char* leaf)
189
{
190
struct full_value fv;
191
int len = full_numeric_leaf(&fv, leaf);
192
193
switch (fv.type)
194
{
195
case fv_integer: *value = fv.v.i; break;
196
case fv_longlong: *value = (unsigned)fv.v.llu; printf("bad conversion\n"); break;
197
default: assert( 0 ); *value = 0;
198
}
199
return len;
200
}
201
202
static const char* get_attr(unsigned attr)
203
{
204
static char tmp[256];
205
206
switch (attr & 3)
207
{
208
case 0: strcpy(tmp, ""); break;
209
case 1: strcpy(tmp, "private "); break;
210
case 2: strcpy(tmp, "protected "); break;
211
case 3: strcpy(tmp, "public "); break;
212
}
213
switch ((attr >> 2) & 7)
214
{
215
case 0: strcat(tmp, ""); break;
216
case 1: strcat(tmp, "virtual "); break;
217
case 2: strcat(tmp, "static "); break;
218
case 3: strcat(tmp, "friend "); break;
219
case 4: strcat(tmp, "introducing virtual "); break;
220
case 5: strcat(tmp, "pure virtual "); break;
221
case 6: strcat(tmp, "pure introducing virtual "); break;
222
case 7: strcat(tmp, "reserved "); break;
223
}
224
if ((attr >> 5) & 1) strcat(tmp, "pseudo ");
225
if ((attr >> 6) & 1) strcat(tmp, "no-inherit ");
226
if ((attr >> 7) & 1) strcat(tmp, "no-construct ");
227
return tmp;
228
}
229
230
static const char* get_property(cv_property_t prop)
231
{
232
static char tmp[1024];
233
unsigned pos = 0;
234
235
#define X(s) {if (pos) tmp[pos++] = ';'; strcpy(tmp + pos, s); pos += strlen(s);}
236
if (prop.is_packed) X("packed");
237
if (prop.has_ctor) X("w/{cd}tor");
238
if (prop.has_overloaded_operator) X("w/overloaded-ops");
239
if (prop.is_nested) X("nested-class");
240
if (prop.has_nested) X("has-nested-classes");
241
if (prop.has_overloaded_assign) X("w/overloaded-assign");
242
if (prop.has_operator_cast) X("w/casting-methods");
243
if (prop.is_forward_defn) X("forward");
244
if (prop.is_scoped) X("scoped");
245
if (prop.has_decorated_name) X("decorated-name");
246
if (prop.is_sealed) X("sealed");
247
if (prop.hfa) pos += sprintf(tmp, "hfa%x", prop.hfa);
248
if (prop.is_intrinsic) X("intrinsic");
249
if (prop.mocom) pos += sprintf(tmp, "mocom%x", prop.mocom);
250
#undef X
251
if (!pos) return "none";
252
253
tmp[pos] = '\0';
254
assert(pos < sizeof(tmp));
255
256
return tmp;
257
}
258
259
static const char* get_funcattr(unsigned attr)
260
{
261
static char tmp[1024];
262
unsigned pos = 0;
263
264
if (!attr) return "none";
265
#define X(s) {if (pos) tmp[pos++] = ';'; strcpy(tmp + pos, s); pos += strlen(s);}
266
if (attr & 0x0001) X("C++ReturnUDT");
267
if (attr & 0x0002) X("Ctor");
268
if (attr & 0x0004) X("Ctor-w/virtualbase");
269
if (attr & 0xfff8) pos += sprintf(tmp, "unk:%x", attr & 0xfff8);
270
#undef X
271
272
tmp[pos] = '\0';
273
assert(pos < sizeof(tmp));
274
275
return tmp;
276
}
277
278
static const char* get_varflags(struct cv_local_varflag flags)
279
{
280
static char tmp[1024];
281
unsigned pos = 0;
282
283
#define X(s) {if (pos) tmp[pos++] = ';'; strcpy(tmp + pos, s); pos += strlen(s);}
284
if (flags.is_param) X("param");
285
if (flags.address_taken) X("addr-taken");
286
if (flags.from_compiler) X("compiler-gen");
287
if (flags.is_aggregate) X("aggregated");
288
if (flags.from_aggregate) X("in-aggregate");
289
if (flags.is_aliased) X("aliased");
290
if (flags.from_alias) X("alias");
291
if (flags.is_return_value) X("retval");
292
if (flags.optimized_out) X("optimized-out");
293
if (flags.enreg_global) X("enreg-global");
294
if (flags.enreg_static) X("enreg-static");
295
if (flags.unused) pos += sprintf(tmp, "unk:%x", flags.unused);
296
#undef X
297
298
if (!pos) return "none";
299
tmp[pos] = '\0';
300
assert(pos < sizeof(tmp));
301
302
return tmp;
303
}
304
305
static const char* get_machine(unsigned m)
306
{
307
const char* machine;
308
309
switch (m)
310
{
311
case CV_CFL_8080: machine = "Intel 8080"; break;
312
case CV_CFL_8086: machine = "Intel 8086"; break;
313
case CV_CFL_80286: machine = "Intel 80286"; break;
314
case CV_CFL_80386: machine = "Intel 80386"; break;
315
case CV_CFL_80486: machine = "Intel 80486"; break;
316
case CV_CFL_PENTIUM: machine = "Intel Pentium"; break;
317
case CV_CFL_PENTIUMII: machine = "Intel Pentium II"; break;
318
case CV_CFL_PENTIUMIII: machine = "Intel Pentium III"; break;
319
320
case CV_CFL_MIPS: machine = "MIPS R4000"; break;
321
case CV_CFL_MIPS16: machine = "MIPS16"; break;
322
case CV_CFL_MIPS32: machine = "MIPS32"; break;
323
case CV_CFL_MIPS64: machine = "MIPS64"; break;
324
case CV_CFL_MIPSI: machine = "MIPS I"; break;
325
case CV_CFL_MIPSII: machine = "MIPS II"; break;
326
case CV_CFL_MIPSIII: machine = "MIPS III"; break;
327
case CV_CFL_MIPSIV: machine = "MIPS IV"; break;
328
case CV_CFL_MIPSV: machine = "MIPS V"; break;
329
330
case CV_CFL_M68000: machine = "M68000"; break;
331
case CV_CFL_M68010: machine = "M68010"; break;
332
case CV_CFL_M68020: machine = "M68020"; break;
333
case CV_CFL_M68030: machine = "M68030"; break;
334
case CV_CFL_M68040: machine = "M68040"; break;
335
336
case CV_CFL_ALPHA_21064: machine = "Alpha 21064"; break;
337
case CV_CFL_ALPHA_21164: machine = "Alpha 21164"; break;
338
case CV_CFL_ALPHA_21164A: machine = "Alpha 21164A"; break;
339
case CV_CFL_ALPHA_21264: machine = "Alpha 21264"; break;
340
case CV_CFL_ALPHA_21364: machine = "Alpha 21364"; break;
341
342
case CV_CFL_PPC601: machine = "PowerPC 601"; break;
343
case CV_CFL_PPC603: machine = "PowerPC 603"; break;
344
case CV_CFL_PPC604: machine = "PowerPC 604"; break;
345
case CV_CFL_PPC620: machine = "PowerPC 620"; break;
346
case CV_CFL_PPCFP: machine = "PowerPC FP"; break;
347
348
case CV_CFL_SH3: machine = "SH3"; break;
349
case CV_CFL_SH3E: machine = "SH3E"; break;
350
case CV_CFL_SH3DSP: machine = "SH3DSP"; break;
351
case CV_CFL_SH4: machine = "SH4"; break;
352
case CV_CFL_SHMEDIA: machine = "SHMEDIA"; break;
353
354
case CV_CFL_ARM3: machine = "ARM 3"; break;
355
case CV_CFL_ARM4: machine = "ARM 4"; break;
356
case CV_CFL_ARM4T: machine = "ARM 4T"; break;
357
case CV_CFL_ARM5: machine = "ARM 5"; break;
358
case CV_CFL_ARM5T: machine = "ARM 5T"; break;
359
case CV_CFL_ARM6: machine = "ARM 6"; break;
360
case CV_CFL_ARM_XMAC: machine = "ARM XMAC"; break;
361
case CV_CFL_ARM_WMMX: machine = "ARM WMMX"; break;
362
case CV_CFL_ARM7: machine = "ARM 7"; break;
363
364
case CV_CFL_OMNI: machine = "OMNI"; break;
365
366
case CV_CFL_IA64_1: machine = "Itanium"; break;
367
case CV_CFL_IA64_2: machine = "Itanium 2"; break;
368
369
case CV_CFL_CEE: machine = "CEE"; break;
370
371
case CV_CFL_AM33: machine = "AM33"; break;
372
373
case CV_CFL_M32R: machine = "M32R"; break;
374
375
case CV_CFL_TRICORE: machine = "TRICORE"; break;
376
377
case CV_CFL_X64: machine = "x86_64"; break;
378
379
case CV_CFL_EBC: machine = "EBC"; break;
380
381
case CV_CFL_THUMB: machine = "Thumb"; break;
382
case CV_CFL_ARMNT: machine = "ARM NT"; break;
383
case CV_CFL_ARM64: machine = "ARM 64"; break;
384
385
case CV_CFL_D3D11_SHADER: machine = "D3D11 shader"; break;
386
default:
387
{
388
static char tmp[16];
389
sprintf(tmp, "machine=%x", m);
390
machine = tmp;
391
}
392
break;
393
}
394
return machine;
395
}
396
397
static const char* get_language(unsigned l)
398
{
399
const char* lang;
400
401
switch (l)
402
{
403
case CV_CFL_C: lang = "C"; break;
404
case CV_CFL_CXX: lang = "C++"; break;
405
case CV_CFL_FORTRAN: lang = "Fortran"; break;
406
case CV_CFL_MASM: lang = "Masm"; break;
407
case CV_CFL_PASCAL: lang = "Pascal"; break;
408
case CV_CFL_BASIC: lang = "Basic"; break;
409
case CV_CFL_COBOL: lang = "Cobol"; break;
410
case CV_CFL_LINK: lang = "Link"; break;
411
case CV_CFL_CVTRES: lang = "Resource"; break;
412
case CV_CFL_CVTPGD: lang = "PoGo"; break;
413
case CV_CFL_CSHARP: lang = "C#"; break;
414
case CV_CFL_VB: lang = "VisualBasic"; break;
415
case CV_CFL_ILASM: lang = "IL ASM"; break;
416
case CV_CFL_JAVA: lang = "Java"; break;
417
case CV_CFL_JSCRIPT: lang = "JavaScript"; break;
418
case CV_CFL_MSIL: lang = "MSIL"; break;
419
case CV_CFL_HLSL: lang = "HLSL"; break;
420
default:
421
{
422
static char tmp[16];
423
sprintf(tmp, "lang=%x", l);
424
lang = tmp;
425
}
426
break;
427
}
428
return lang;
429
}
430
431
static const char* get_callconv(unsigned cc)
432
{
433
const char* callconv;
434
435
switch (cc)
436
{
437
case CV_CALL_NEAR_C: callconv = "near C"; break;
438
case CV_CALL_FAR_C: callconv = "far C"; break;
439
case CV_CALL_NEAR_PASCAL: callconv = "near pascal"; break;
440
case CV_CALL_FAR_PASCAL: callconv = "far pascal"; break;
441
case CV_CALL_NEAR_FAST: callconv = "near fast"; break;
442
case CV_CALL_FAR_FAST: callconv = "far fast"; break;
443
case CV_CALL_SKIPPED: callconv = "skipped"; break;
444
case CV_CALL_NEAR_STD: callconv = "near std"; break;
445
case CV_CALL_FAR_STD: callconv = "far std"; break;
446
case CV_CALL_NEAR_SYS: callconv = "near sys"; break;
447
case CV_CALL_FAR_SYS: callconv = "far sys"; break;
448
case CV_CALL_THISCALL: callconv = "this call"; break;
449
case CV_CALL_MIPSCALL: callconv = "mips call"; break;
450
case CV_CALL_GENERIC: callconv = "generic"; break;
451
case CV_CALL_ALPHACALL: callconv = "alpha call"; break;
452
case CV_CALL_PPCCALL: callconv = "ppc call"; break;
453
case CV_CALL_SHCALL: callconv = "sh call"; break;
454
case CV_CALL_ARMCALL: callconv = "arm call"; break;
455
case CV_CALL_AM33CALL: callconv = "am33 call"; break;
456
case CV_CALL_TRICALL: callconv = "tri call"; break;
457
case CV_CALL_SH5CALL: callconv = "sh5 call"; break;
458
case CV_CALL_M32RCALL: callconv = "m32r call"; break;
459
case CV_CALL_CLRCALL: callconv = "clr call"; break;
460
case CV_CALL_INLINE: callconv = "inline"; break;
461
case CV_CALL_NEAR_VECTOR: callconv = "near vector"; break;
462
case CV_CALL_RESERVED: callconv = "reserved"; break;
463
default:
464
{
465
static char tmp[20];
466
sprintf(tmp, "callconv=%x", cc);
467
callconv = tmp;
468
}
469
break;
470
}
471
return callconv;
472
}
473
474
static const char* get_pubflags(unsigned flags)
475
{
476
static char ret[32];
477
478
ret[0] = '\0';
479
#define X(s) {if (ret[0]) strcat(ret, ";"); strcat(ret, s);}
480
if (flags & 1) X("code");
481
if (flags & 2) X("func");
482
if (flags & 4) X("manage");
483
if (flags & 8) X("msil");
484
#undef X
485
return ret;
486
}
487
488
static void do_field(const unsigned char* start, const unsigned char* end)
489
{
490
/*
491
* A 'field list' is a CodeView-specific data type which doesn't
492
* directly correspond to any high-level data type. It is used
493
* to hold the collection of members of a struct, class, union
494
* or enum type. The actual definition of that type will follow
495
* later, and refer to the field list definition record.
496
*
497
* As we don't have a field list type ourselves, we look ahead
498
* in the field list to try to find out whether this field list
499
* will be used for an enum or struct type, and create a dummy
500
* type of the corresponding sort. Later on, the definition of
501
* the 'real' type will copy the member / enumeration data.
502
*/
503
const unsigned char* ptr = start;
504
const char* cstr;
505
const struct p_string* pstr;
506
int leaf_len, value;
507
struct full_value full_value;
508
509
while (ptr < end)
510
{
511
const union codeview_fieldtype* fieldtype = (const union codeview_fieldtype*)ptr;
512
513
if (*ptr >= 0xf0) /* LF_PAD... */
514
{
515
ptr +=* ptr & 0x0f;
516
continue;
517
}
518
519
switch (fieldtype->generic.id)
520
{
521
case LF_ENUMERATE_V1:
522
leaf_len = full_numeric_leaf(&full_value, fieldtype->enumerate_v1.data);
523
pstr = (const struct p_string*)&fieldtype->enumerate_v1.data[leaf_len];
524
printf("\t\tEnumerate V1: '%s' value:%s\n",
525
p_string(pstr), full_value_string(&full_value));
526
ptr += 2 + 2 + leaf_len + 1 + pstr->namelen;
527
break;
528
529
case LF_ENUMERATE_V3:
530
leaf_len = full_numeric_leaf(&full_value, fieldtype->enumerate_v3.data);
531
cstr = (const char*)&fieldtype->enumerate_v3.data[leaf_len];
532
printf("\t\tEnumerate V3: '%s' value:%s\n",
533
cstr, full_value_string(&full_value));
534
ptr += 2 + 2 + leaf_len + strlen(cstr) + 1;
535
break;
536
537
case LF_MEMBER_V1:
538
leaf_len = numeric_leaf(&value, fieldtype->member_v1.data);
539
pstr = (const struct p_string *)&fieldtype->member_v1.data[leaf_len];
540
printf("\t\tMember V1: '%s' type:%x attr:%s @%d\n",
541
p_string(pstr), fieldtype->member_v1.type,
542
get_attr(fieldtype->member_v1.attribute), value);
543
ptr += 2 + 2 + 2 + leaf_len + 1 + pstr->namelen;
544
break;
545
546
case LF_MEMBER_V2:
547
leaf_len = numeric_leaf(&value, fieldtype->member_v2.data);
548
pstr = (const struct p_string *)&fieldtype->member_v2.data[leaf_len];
549
printf("\t\tMember V2: '%s' type:%x attr:%s @%d\n",
550
p_string(pstr), fieldtype->member_v2.type,
551
get_attr(fieldtype->member_v2.attribute), value);
552
ptr += 2 + 2 + 4 + leaf_len + 1 + pstr->namelen;
553
break;
554
555
case LF_MEMBER_V3:
556
leaf_len = numeric_leaf(&value, fieldtype->member_v3.data);
557
cstr = (const char*)&fieldtype->member_v3.data[leaf_len];
558
printf("\t\tMember V3: '%s' type:%x attr:%s @%d\n",
559
cstr, fieldtype->member_v3.type,
560
get_attr(fieldtype->member_v3.attribute), value);
561
ptr += 2 + 2 + 4 + leaf_len + strlen(cstr) + 1;
562
break;
563
564
case LF_ONEMETHOD_V1:
565
switch ((fieldtype->onemethod_v1.attribute >> 2) & 7)
566
{
567
case 4: case 6:
568
printf("\t\tVirtual-method V1: '%s' attr:%s type:%x vtable_offset:%u\n",
569
p_string(&fieldtype->onemethod_virt_v1.p_name),
570
get_attr(fieldtype->onemethod_virt_v1.attribute),
571
fieldtype->onemethod_virt_v1.type,
572
fieldtype->onemethod_virt_v1.vtab_offset);
573
ptr += 2 + 2 + 2 + 4 + (1 + fieldtype->onemethod_virt_v1.p_name.namelen);
574
break;
575
576
default:
577
printf("\t\tMethod V1: '%s' attr:%s type:%x\n",
578
p_string(&fieldtype->onemethod_v1.p_name),
579
get_attr(fieldtype->onemethod_v1.attribute),
580
fieldtype->onemethod_v1.type);
581
ptr += 2 + 2 + 2 + (1 + fieldtype->onemethod_v1.p_name.namelen);
582
break;
583
}
584
break;
585
586
case LF_ONEMETHOD_V2:
587
switch ((fieldtype->onemethod_v2.attribute >> 2) & 7)
588
{
589
case 4: case 6:
590
printf("\t\tVirtual-method V2: '%s' attr:%s type:%x vtable_offset:%u\n",
591
p_string(&fieldtype->onemethod_virt_v2.p_name),
592
get_attr(fieldtype->onemethod_virt_v2.attribute),
593
fieldtype->onemethod_virt_v2.type,
594
fieldtype->onemethod_virt_v2.vtab_offset);
595
ptr += 2 + 2 + 4 + 4 + (1 + fieldtype->onemethod_virt_v2.p_name.namelen);
596
break;
597
598
default:
599
printf("\t\tMethod V2: '%s' attr:%s type:%x\n",
600
p_string(&fieldtype->onemethod_v2.p_name),
601
get_attr(fieldtype->onemethod_v2.attribute),
602
fieldtype->onemethod_v2.type);
603
ptr += 2 + 2 + 4 + (1 + fieldtype->onemethod_v2.p_name.namelen);
604
break;
605
}
606
break;
607
608
case LF_ONEMETHOD_V3:
609
switch ((fieldtype->onemethod_v3.attribute >> 2) & 7)
610
{
611
case 4: case 6:
612
printf("\t\tVirtual-method V3: '%s' attr:%s type:%x vtable_offset:%u\n",
613
fieldtype->onemethod_virt_v3.name,
614
get_attr(fieldtype->onemethod_virt_v3.attribute),
615
fieldtype->onemethod_virt_v3.type,
616
fieldtype->onemethod_virt_v3.vtab_offset);
617
ptr += 2 + 2 + 4 + 4 + (strlen(fieldtype->onemethod_virt_v3.name) + 1);
618
break;
619
620
default:
621
printf("\t\tMethod V3: '%s' attr:%s type:%x\n",
622
fieldtype->onemethod_v3.name,
623
get_attr(fieldtype->onemethod_v3.attribute),
624
fieldtype->onemethod_v3.type);
625
ptr += 2 + 2 + 4 + (strlen(fieldtype->onemethod_v3.name) + 1);
626
break;
627
}
628
break;
629
630
case LF_METHOD_V1:
631
printf("\t\tMethod V1: '%s' overloaded=#%d method-list=%x\n",
632
p_string(&fieldtype->method_v1.p_name),
633
fieldtype->method_v1.count, fieldtype->method_v1.mlist);
634
ptr += 2 + 2 + 2 + (1 + fieldtype->method_v1.p_name.namelen);
635
break;
636
637
case LF_METHOD_V2:
638
printf("\t\tMethod V2: '%s' overloaded=#%d method-list=%x\n",
639
p_string(&fieldtype->method_v2.p_name),
640
fieldtype->method_v2.count, fieldtype->method_v2.mlist);
641
ptr += 2 + 2 + 4 + (1 + fieldtype->method_v2.p_name.namelen);
642
break;
643
644
case LF_METHOD_V3:
645
printf("\t\tMethod V3: '%s' overloaded=#%d method-list=%x\n",
646
fieldtype->method_v3.name,
647
fieldtype->method_v3.count, fieldtype->method_v3.mlist);
648
ptr += 2 + 2 + 4 + (strlen(fieldtype->method_v3.name) + 1);
649
break;
650
651
case LF_STMEMBER_V1:
652
printf("\t\tStatic member V1: '%s' attr:%s type:%x\n",
653
p_string(&fieldtype->stmember_v1.p_name),
654
get_attr(fieldtype->stmember_v1.attribute),
655
fieldtype->stmember_v1.type);
656
ptr += 2 + 2 + 2 + (1 + fieldtype->stmember_v1.p_name.namelen);
657
break;
658
659
case LF_STMEMBER_V2:
660
printf("\t\tStatic member V2: '%s' attr:%s type:%x\n",
661
p_string(&fieldtype->stmember_v2.p_name),
662
get_attr(fieldtype->stmember_v2.attribute),
663
fieldtype->stmember_v2.type);
664
ptr += 2 + 2 + 4 + (1 + fieldtype->stmember_v2.p_name.namelen);
665
break;
666
667
case LF_STMEMBER_V3:
668
printf("\t\tStatic member V3: '%s' attr:%s type:%x\n",
669
fieldtype->stmember_v3.name,
670
get_attr(fieldtype->stmember_v3.attribute),
671
fieldtype->stmember_v3.type);
672
ptr += 2 + 2 + 4 + (strlen(fieldtype->stmember_v3.name) + 1);
673
break;
674
675
case LF_FRIENDFCN_V1:
676
printf("\t\tFriend function V1: '%s' type:%x\n",
677
p_string(&fieldtype->friendfcn_v1.p_name),
678
fieldtype->friendfcn_v1.type);
679
ptr += 2 + 2 + (1 + fieldtype->friendfcn_v1.p_name.namelen);
680
break;
681
682
case LF_FRIENDFCN_V2:
683
printf("\t\tFriend function V2: '%s' type:%x\n",
684
p_string(&fieldtype->friendfcn_v2.p_name),
685
fieldtype->friendfcn_v2.type);
686
ptr += 2 + 2 + 4 + (1 + fieldtype->friendfcn_v2.p_name.namelen);
687
break;
688
689
case LF_FRIENDFCN_V3:
690
printf("\t\tFriend function V3: '%s' type:%x\n",
691
fieldtype->friendfcn_v3.name,
692
fieldtype->friendfcn_v3.type);
693
ptr += 2 + 2 + 4 + (strlen(fieldtype->friendfcn_v3.name) + 1);
694
break;
695
696
case LF_BCLASS_V1:
697
leaf_len = numeric_leaf(&value, fieldtype->bclass_v1.data);
698
printf("\t\tBase class V1: type:%x attr:%s @%d\n",
699
fieldtype->bclass_v1.type,
700
get_attr(fieldtype->bclass_v1.attribute), value);
701
ptr += 2 + 2 + 2 + leaf_len;
702
break;
703
704
case LF_BCLASS_V2:
705
leaf_len = numeric_leaf(&value, fieldtype->bclass_v2.data);
706
printf("\t\tBase class V2: type:%x attr:%s @%d\n",
707
fieldtype->bclass_v2.type,
708
get_attr(fieldtype->bclass_v2.attribute), value);
709
ptr += 2 + 2 + 4 + leaf_len;
710
break;
711
712
case LF_VBCLASS_V1:
713
case LF_IVBCLASS_V1:
714
leaf_len = numeric_leaf(&value, fieldtype->vbclass_v1.data);
715
printf("\t\t%sirtual base class V1: type:%x (ptr:%x) attr:%s vbpoff:%d ",
716
(fieldtype->generic.id == LF_VBCLASS_V1) ? "V" : "Indirect v",
717
fieldtype->vbclass_v1.btype, fieldtype->vbclass_v1.vbtype,
718
get_attr(fieldtype->vbclass_v1.attribute), value);
719
ptr += 2 + 2 + 2 + 2 + leaf_len;
720
leaf_len = numeric_leaf(&value, ptr);
721
printf("vboff:%d\n", value);
722
ptr += leaf_len;
723
break;
724
725
case LF_VBCLASS_V2:
726
case LF_IVBCLASS_V2:
727
leaf_len = numeric_leaf(&value, fieldtype->vbclass_v2.data);
728
printf("\t\t%sirtual base class V2: type:%x (ptr:%x) attr:%s vbpoff:%d ",
729
(fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v",
730
fieldtype->vbclass_v2.btype, fieldtype->vbclass_v2.vbtype,
731
get_attr(fieldtype->vbclass_v2.attribute), value);
732
ptr += 2 + 2 + 4 + 4 + leaf_len;
733
leaf_len = numeric_leaf(&value, ptr);
734
printf("vboff:%d\n", value);
735
ptr += leaf_len;
736
break;
737
738
case LF_FRIENDCLS_V1:
739
printf("\t\tFriend class V1: type:%x\n", fieldtype->friendcls_v1.type);
740
ptr += 2 + 2;
741
break;
742
743
case LF_FRIENDCLS_V2:
744
printf("\t\tFriend class V2: type:%x\n", fieldtype->friendcls_v2.type);
745
ptr += 2 + 2 + 4;
746
break;
747
748
case LF_NESTTYPE_V1:
749
printf("\t\tNested type V1: '%s' type:%x\n",
750
p_string(&fieldtype->nesttype_v1.p_name),
751
fieldtype->nesttype_v1.type);
752
ptr += 2 + 2 + (1 + fieldtype->nesttype_v1.p_name.namelen);
753
break;
754
755
case LF_NESTTYPE_V2:
756
printf("\t\tNested type V2: '%s' pad0:%u type:%x\n",
757
p_string(&fieldtype->nesttype_v2.p_name),
758
fieldtype->nesttype_v2._pad0, fieldtype->nesttype_v2.type);
759
ptr += 2 + 2 + 4 + (1 + fieldtype->nesttype_v2.p_name.namelen);
760
break;
761
762
case LF_NESTTYPE_V3:
763
printf("\t\tNested type V3: '%s' pad0:%u type:%x\n",
764
fieldtype->nesttype_v3.name,
765
fieldtype->nesttype_v3._pad0, fieldtype->nesttype_v3.type);
766
ptr += 2 + 2 + 4 + (strlen(fieldtype->nesttype_v3.name) + 1);
767
break;
768
769
case LF_VFUNCTAB_V1:
770
printf("\t\tVirtual function table V1: type:%x\n",
771
fieldtype->vfunctab_v1.type);
772
ptr += 2 + 2;
773
break;
774
775
case LF_VFUNCTAB_V2:
776
printf("\t\tVirtual function table V2: type:%x\n",
777
fieldtype->vfunctab_v2.type);
778
ptr += 2 + 2 + 4;
779
break;
780
781
case LF_VFUNCOFF_V1:
782
printf("\t\tVirtual function table offset V1: type:%x offset:%x\n",
783
fieldtype->vfuncoff_v1.type, fieldtype->vfuncoff_v1.offset);
784
ptr += 2 + 2 + 4;
785
break;
786
787
case LF_VFUNCOFF_V2:
788
printf("\t\tVirtual function table offset V2: type:%x offset:%x\n",
789
fieldtype->vfuncoff_v2.type, fieldtype->vfuncoff_v2.offset);
790
ptr += 2 + 2 + 4 + 4;
791
break;
792
793
case LF_INDEX_V1:
794
printf("\t\tIndex V1: index:%x\n", fieldtype->index_v1.ref);
795
ptr += 2 + 2;
796
break;
797
798
case LF_INDEX_V2:
799
printf("\t\tIndex V2: index:%x\n", fieldtype->index_v2.ref);
800
ptr += 2 + 2 + 4;
801
break;
802
803
default:
804
printf(">>> Unsupported field-id %x\n", fieldtype->generic.id);
805
dump_data((const void*)fieldtype, 0x30, "\t");
806
break;
807
}
808
}
809
}
810
811
static void codeview_dump_one_type(unsigned curr_type, const union codeview_type* type)
812
{
813
const union codeview_reftype* reftype = (const union codeview_reftype*)type;
814
int i, leaf_len, value;
815
unsigned int j;
816
const char* str;
817
818
switch (type->generic.id)
819
{
820
/* types from TPI (aka #2) stream */
821
case LF_POINTER_V1:
822
printf("\t%x => Pointer V1 to type:%x\n",
823
curr_type, type->pointer_v1.datatype);
824
break;
825
case LF_POINTER_V2:
826
printf("\t%x => Pointer V2 to type:%x\n",
827
curr_type, type->pointer_v2.datatype);
828
break;
829
case LF_ARRAY_V1:
830
leaf_len = numeric_leaf(&value, type->array_v1.data);
831
printf("\t%x => Array V1-'%s'[%u type:%x] type:%x\n",
832
curr_type, p_string((const struct p_string *)&type->array_v1.data[leaf_len]),
833
value, type->array_v1.idxtype, type->array_v1.elemtype);
834
break;
835
case LF_ARRAY_V2:
836
leaf_len = numeric_leaf(&value, type->array_v2.data);
837
printf("\t%x => Array V2-'%s'[%u type:%x] type:%x\n",
838
curr_type, p_string((const struct p_string *)&type->array_v2.data[leaf_len]),
839
value, type->array_v2.idxtype, type->array_v2.elemtype);
840
break;
841
case LF_ARRAY_V3:
842
leaf_len = numeric_leaf(&value, type->array_v3.data);
843
str = (const char*)&type->array_v3.data[leaf_len];
844
printf("\t%x => Array V3-'%s'[%u type:%x] type:%x\n",
845
curr_type, str, value,
846
type->array_v3.idxtype, type->array_v3.elemtype);
847
break;
848
849
/* a bitfields is a CodeView specific data type which represent a bitfield
850
* in a structure or a class. For now, we store it in a SymTag-like type
851
* (so that the rest of the process is seamless), but check at udt inclusion
852
* type for its presence
853
*/
854
case LF_BITFIELD_V1:
855
printf("\t%x => Bitfield V1:%x offset:%u #bits:%u\n",
856
curr_type, reftype->bitfield_v1.type, reftype->bitfield_v1.bitoff,
857
reftype->bitfield_v1.nbits);
858
break;
859
860
case LF_BITFIELD_V2:
861
printf("\t%x => Bitfield V2:%x offset:%u #bits:%u\n",
862
curr_type, reftype->bitfield_v2.type, reftype->bitfield_v2.bitoff,
863
reftype->bitfield_v2.nbits);
864
break;
865
866
case LF_FIELDLIST_V1:
867
case LF_FIELDLIST_V2:
868
printf("\t%x => Fieldlist\n", curr_type);
869
do_field(reftype->fieldlist.list, (const BYTE*)type + reftype->generic.len + 2);
870
break;
871
872
case LF_STRUCTURE_V1:
873
case LF_CLASS_V1:
874
leaf_len = numeric_leaf(&value, type->struct_v1.data);
875
printf("\t%x => %s V1 '%s' elts:%u property:%s fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
876
curr_type, type->generic.id == LF_CLASS_V1 ? "Class" : "Struct",
877
p_string((const struct p_string *)&type->struct_v1.data[leaf_len]),
878
type->struct_v1.n_element, get_property(type->struct_v1.property),
879
type->struct_v1.fieldlist, type->struct_v1.derived,
880
type->struct_v1.vshape, value);
881
break;
882
883
case LF_STRUCTURE_V2:
884
case LF_CLASS_V2:
885
leaf_len = numeric_leaf(&value, type->struct_v2.data);
886
printf("\t%x => %s V2 '%s' elts:%u property:%s\n"
887
" fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
888
curr_type, type->generic.id == LF_CLASS_V2 ? "Class" : "Struct",
889
p_string((const struct p_string *)&type->struct_v2.data[leaf_len]),
890
type->struct_v2.n_element, get_property(type->struct_v2.property),
891
type->struct_v2.fieldlist, type->struct_v2.derived,
892
type->struct_v2.vshape, value);
893
break;
894
895
case LF_STRUCTURE_V3:
896
case LF_CLASS_V3:
897
leaf_len = numeric_leaf(&value, type->struct_v3.data);
898
str = (const char*)&type->struct_v3.data[leaf_len];
899
printf("\t%x => %s V3 '%s' elts:%u property:%s\n"
900
" fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
901
curr_type, type->generic.id == LF_CLASS_V3 ? "Class" : "Struct",
902
str, type->struct_v3.n_element, get_property(type->struct_v3.property),
903
type->struct_v3.fieldlist, type->struct_v3.derived,
904
type->struct_v3.vshape, value);
905
if (type->struct_v3.property.has_decorated_name)
906
printf("\t\tDecorated name:%s\n", str + strlen(str) + 1);
907
break;
908
909
case LF_UNION_V1:
910
leaf_len = numeric_leaf(&value, type->union_v1.data);
911
printf("\t%x => Union V1 '%s' count:%u property:%s fieldlist-type:%x size:%u\n",
912
curr_type, p_string((const struct p_string *)&type->union_v1.data[leaf_len]),
913
type->union_v1.count, get_property(type->union_v1.property),
914
type->union_v1.fieldlist, value);
915
break;
916
917
case LF_UNION_V2:
918
leaf_len = numeric_leaf(&value, type->union_v2.data);
919
printf("\t%x => Union V2 '%s' count:%u property:%s fieldlist-type:%x size:%u\n",
920
curr_type, p_string((const struct p_string *)&type->union_v2.data[leaf_len]),
921
type->union_v2.count, get_property(type->union_v2.property),
922
type->union_v2.fieldlist, value);
923
break;
924
925
case LF_UNION_V3:
926
leaf_len = numeric_leaf(&value, type->union_v3.data);
927
str = (const char*)&type->union_v3.data[leaf_len];
928
printf("\t%x => Union V3 '%s' count:%u property:%s fieldlist-type:%x size:%u\n",
929
curr_type, str, type->union_v3.count,
930
get_property(type->union_v3.property),
931
type->union_v3.fieldlist, value);
932
if (type->union_v3.property.has_decorated_name)
933
printf("\t\tDecorated name:%s\n", str + strlen(str) + 1);
934
break;
935
936
case LF_ENUM_V1:
937
printf("\t%x => Enum V1 '%s' type:%x field-type:%x count:%u property:%s\n",
938
curr_type, p_string(&type->enumeration_v1.p_name),
939
type->enumeration_v1.type,
940
type->enumeration_v1.fieldlist,
941
type->enumeration_v1.count,
942
get_property(type->enumeration_v1.property));
943
break;
944
945
case LF_ENUM_V2:
946
printf("\t%x => Enum V2 '%s' type:%x field-type:%x count:%u property:%s\n",
947
curr_type, p_string(&type->enumeration_v2.p_name),
948
type->enumeration_v2.type,
949
type->enumeration_v2.fieldlist,
950
type->enumeration_v2.count,
951
get_property(type->enumeration_v2.property));
952
break;
953
954
case LF_ENUM_V3:
955
printf("\t%x => Enum V3 '%s' type:%x field-type:%x count:%u property:%s\n",
956
curr_type, type->enumeration_v3.name,
957
type->enumeration_v3.type,
958
type->enumeration_v3.fieldlist,
959
type->enumeration_v3.count,
960
get_property(type->enumeration_v3.property));
961
if (type->enumeration_v3.property.has_decorated_name)
962
printf("\t\tDecorated name:%s\n", type->enumeration_v3.name + strlen(type->enumeration_v3.name) + 1);
963
break;
964
965
case LF_ARGLIST_V1:
966
printf("\t%x => Arglist V1(#%u):", curr_type, reftype->arglist_v1.num);
967
for (i = 0; i < reftype->arglist_v1.num; i++)
968
{
969
printf(" %x", reftype->arglist_v1.args[i]);
970
}
971
printf("\n");
972
break;
973
974
case LF_ARGLIST_V2:
975
printf("\t%x => Arglist V2(#%u):", curr_type, reftype->arglist_v2.num);
976
for (j = 0; j < reftype->arglist_v2.num; j++)
977
{
978
printf("\t %x", reftype->arglist_v2.args[j]);
979
}
980
printf("\t\n");
981
break;
982
983
case LF_PROCEDURE_V1:
984
printf("\t%x => Procedure V1 ret_type:%x callconv:%s attr:%s (#%u args_type:%x)\n",
985
curr_type, type->procedure_v1.rvtype,
986
get_callconv(type->procedure_v1.callconv), get_funcattr(type->procedure_v1.funcattr),
987
type->procedure_v1.params, type->procedure_v1.arglist);
988
break;
989
990
case LF_PROCEDURE_V2:
991
printf("\t%x => Procedure V2 ret_type:%x callconv:%s attr:%s (#%u args_type:%x)\n",
992
curr_type, type->procedure_v2.rvtype,
993
get_callconv(type->procedure_v2.callconv), get_funcattr(type->procedure_v2.funcattr),
994
type->procedure_v2.params, type->procedure_v2.arglist);
995
break;
996
997
case LF_MFUNCTION_V2:
998
printf("\t%x => MFunction V2 ret-type:%x callconv:%s class-type:%x this-type:%x attr:%s\n"
999
"\t\t#args:%x args-type:%x this_adjust:%x\n",
1000
curr_type,
1001
type->mfunction_v2.rvtype,
1002
get_callconv(type->mfunction_v2.callconv),
1003
type->mfunction_v2.class_type,
1004
type->mfunction_v2.this_type,
1005
get_funcattr(type->mfunction_v2.funcattr),
1006
type->mfunction_v2.params,
1007
type->mfunction_v2.arglist,
1008
type->mfunction_v2.this_adjust);
1009
break;
1010
1011
case LF_MODIFIER_V1:
1012
printf("\t%x => Modifier V1 type:%x modif:%x%s%s%s\n",
1013
curr_type, type->modifier_v1.type, type->modifier_v1.attribute,
1014
(type->modifier_v1.attribute & 1) ? "-const" : "",
1015
(type->modifier_v1.attribute & 2) ? "-volatile" : "",
1016
(type->modifier_v1.attribute & 4) ? "-unaligned" : "");
1017
break;
1018
1019
case LF_MODIFIER_V2:
1020
printf("\t%x => Modifier V2 type:%x modif:%x%s%s%s\n",
1021
curr_type, type->modifier_v2.type, type->modifier_v2.attribute,
1022
(type->modifier_v2.attribute & 1) ? "-const" : "",
1023
(type->modifier_v2.attribute & 2) ? "-volatile" : "",
1024
(type->modifier_v2.attribute & 4) ? "-unaligned" : "");
1025
break;
1026
1027
case LF_METHODLIST_V1:
1028
{
1029
const unsigned short* pattr = (const unsigned short*)((const char*)type + 4);
1030
1031
printf("\t%x => Method list\n", curr_type);
1032
while ((const char*)pattr < (const char*)type + type->generic.len + 2)
1033
{
1034
switch ((*pattr >> 2) & 7)
1035
{
1036
case 4: case 6:
1037
printf("\t\t\tattr:%s type:%x vtab-offset:%x\n",
1038
get_attr(pattr[0]), pattr[1],
1039
*(const unsigned*)(&pattr[2]));
1040
pattr += 3;
1041
break;
1042
default:
1043
printf("\t\t\tattr:%s type:%x\n",
1044
get_attr(pattr[0]), pattr[1]);
1045
pattr += 2;
1046
}
1047
}
1048
}
1049
break;
1050
1051
case LF_METHODLIST_V2:
1052
{
1053
const unsigned* pattr = (const unsigned*)((const char*)type + 4);
1054
1055
printf("\t%x => Method list\n", curr_type);
1056
while ((const char*)pattr < (const char*)type + type->generic.len + 2)
1057
{
1058
switch ((*pattr >> 2) & 7)
1059
{
1060
case 4: case 6:
1061
printf("\t\t\tattr:%s type:%x vtab-offset:%x\n",
1062
get_attr(pattr[0]), pattr[1], pattr[2]);
1063
pattr += 3;
1064
break;
1065
default:
1066
printf("\t\t\tattr:%s type:%x\n",
1067
get_attr(pattr[0]), pattr[1]);
1068
pattr += 2;
1069
}
1070
}
1071
}
1072
break;
1073
1074
case LF_VTSHAPE_V1:
1075
{
1076
int count = *(const unsigned short*)((const char*)type + 4);
1077
int shift = 0;
1078
const char* ptr = (const char*)type + 6;
1079
const char* desc[] = {"Near", "Far", "Thin", "Disp to outermost",
1080
"Pointer to metaclass", "Near32", "Far32"};
1081
printf("\t%x => VT Shape #%d: ", curr_type, count);
1082
while (count--)
1083
{
1084
if (((*ptr << shift) & 0xF) <= 6)
1085
printf("%s ", desc[(*ptr << shift) & 0xF]);
1086
else
1087
printf("%x ", (*ptr << shift) & 0xF);
1088
if (shift == 0) shift = 4; else {shift = 0; ptr++;}
1089
}
1090
printf("\n");
1091
}
1092
break;
1093
1094
case LF_DERIVED_V1:
1095
printf("\t%x => Derived V1(#%u):", curr_type, reftype->derived_v1.num);
1096
for (i = 0; i < reftype->derived_v1.num; i++)
1097
{
1098
printf(" %x", reftype->derived_v1.drvdcls[i]);
1099
}
1100
printf("\n");
1101
break;
1102
1103
case LF_DERIVED_V2:
1104
printf("\t%x => Derived V2(#%u):", curr_type, reftype->derived_v2.num);
1105
for (j = 0; j < reftype->derived_v2.num; j++)
1106
{
1107
printf(" %x", reftype->derived_v2.drvdcls[j]);
1108
}
1109
printf("\n");
1110
break;
1111
1112
case LF_VFTABLE_V3:
1113
printf("\t%x => VFTable V3 base:%x baseVfTable:%x offset%u\n",
1114
curr_type, reftype->vftable_v3.type, reftype->vftable_v3.baseVftable, reftype->vftable_v3.offsetInObjectLayout);
1115
{
1116
const char* str = reftype->vftable_v3.names;
1117
const char* last = str + reftype->vftable_v3.cbstr;
1118
while (str < last)
1119
{
1120
printf("\t\t%s\n", str);
1121
str += strlen(str) + 1;
1122
}
1123
}
1124
break;
1125
1126
/* types from IPI (aka #4) stream */
1127
case LF_FUNC_ID:
1128
printf("\t%x => FuncId %s scopeId:%04x type:%04x\n",
1129
curr_type, type->func_id_v3.name,
1130
type->func_id_v3.scopeId, type->func_id_v3.type);
1131
break;
1132
case LF_MFUNC_ID:
1133
printf("\t%x => MFuncId %s parent:%04x type:%04x\n",
1134
curr_type, type->mfunc_id_v3.name,
1135
type->mfunc_id_v3.parentType, type->mfunc_id_v3.type);
1136
break;
1137
case LF_BUILDINFO:
1138
printf("\t%x => BuildInfo count:%d\n", curr_type, type->buildinfo_v3.count);
1139
if (type->buildinfo_v3.count >= 1) printf("\t\tcurrent dir: %04x\n", type->buildinfo_v3.arg[0]);
1140
if (type->buildinfo_v3.count >= 2) printf("\t\tbuild tool: %04x\n", type->buildinfo_v3.arg[1]);
1141
if (type->buildinfo_v3.count >= 3) printf("\t\tsource file: %04x\n", type->buildinfo_v3.arg[2]);
1142
if (type->buildinfo_v3.count >= 4) printf("\t\tPDB file: %04x\n", type->buildinfo_v3.arg[3]);
1143
if (type->buildinfo_v3.count >= 5) printf("\t\tArguments: %04x\n", type->buildinfo_v3.arg[4]);
1144
break;
1145
case LF_SUBSTR_LIST:
1146
printf("\t%x => SubstrList V3(#%u):", curr_type, reftype->arglist_v2.num);
1147
for (j = 0; j < reftype->arglist_v2.num; j++)
1148
{
1149
printf("\t %x", reftype->arglist_v2.args[j]);
1150
}
1151
printf("\t\n");
1152
break;
1153
case LF_STRING_ID:
1154
printf("\t%x => StringId %s strid:%04x\n",
1155
curr_type, type->string_id_v3.name, type->string_id_v3.strid);
1156
break;
1157
case LF_UDT_SRC_LINE:
1158
printf("\t%x => Udt-SrcLine type:%04x src:%04x line:%d\n",
1159
curr_type, type->udt_src_line_v3.type,
1160
type->udt_src_line_v3.src, type->udt_src_line_v3.line);
1161
break;
1162
case LF_UDT_MOD_SRC_LINE:
1163
printf("\t%x => Udt-ModSrcLine type:%04x src:%04x line:%d mod:%d\n",
1164
curr_type, type->udt_mod_src_line_v3.type,
1165
type->udt_mod_src_line_v3.src, type->udt_mod_src_line_v3.line,
1166
type->udt_mod_src_line_v3.imod);
1167
break;
1168
1169
default:
1170
printf(">>> Unsupported type-id %x for %x\n", type->generic.id, curr_type);
1171
dump_data((const void*)type, type->generic.len + 2, "");
1172
break;
1173
}
1174
}
1175
1176
BOOL codeview_dump_types_from_offsets(const void* table, const DWORD* offsets, unsigned num_types)
1177
{
1178
unsigned long i;
1179
1180
for (i = 0; i < num_types; i++)
1181
{
1182
codeview_dump_one_type(0x1000 + i,
1183
(const union codeview_type*)((const char*)table + offsets[i]));
1184
}
1185
1186
return TRUE;
1187
}
1188
1189
BOOL codeview_dump_types_from_block(const void* table, unsigned long len, unsigned int from, unsigned int to)
1190
{
1191
unsigned int curr_type = 0x1000;
1192
const unsigned char*ptr = table;
1193
1194
while (ptr - (const unsigned char*)table < len)
1195
{
1196
const union codeview_type* type = (const union codeview_type*)ptr;
1197
1198
if (from <= curr_type && curr_type < to)
1199
codeview_dump_one_type(curr_type, type);
1200
curr_type++;
1201
ptr += type->generic.len + 2;
1202
}
1203
1204
return TRUE;
1205
}
1206
1207
static void dump_defrange(const struct cv_addr_range* range, const void* last, unsigned indent)
1208
{
1209
const struct cv_addr_gap* gap;
1210
1211
printf("%*s\\- %04x:%08x range:#%x\n", indent, "", range->isectStart, range->offStart, range->cbRange);
1212
for (gap = (const struct cv_addr_gap*)(range + 1); (const void*)(gap + 1) <= last; ++gap)
1213
printf("%*s | offset:%x range:#%x\n", indent, "", gap->gapStartOffset, gap->cbRange);
1214
}
1215
1216
/* return address of first byte after the symbol */
1217
static inline const char* get_last(const union codeview_symbol* sym)
1218
{
1219
return (const char*)sym + sym->generic.len + 2;
1220
}
1221
1222
static unsigned binannot_uncompress(const unsigned char** pptr)
1223
{
1224
unsigned res = (unsigned)(-1);
1225
const unsigned char* ptr = *pptr;
1226
1227
if ((*ptr & 0x80) == 0x00)
1228
res = (unsigned)(*ptr++);
1229
else if ((*ptr & 0xC0) == 0x80)
1230
{
1231
res = (unsigned)((*ptr++ & 0x3f) << 8);
1232
res |= *ptr++;
1233
}
1234
else if ((*ptr & 0xE0) == 0xC0)
1235
{
1236
res = (*ptr++ & 0x1f) << 24;
1237
res |= *ptr++ << 16;
1238
res |= *ptr++ << 8;
1239
res |= *ptr++;
1240
}
1241
else res = (unsigned)(-1);
1242
*pptr = ptr;
1243
return res;
1244
}
1245
1246
static inline int binannot_getsigned(unsigned i)
1247
{
1248
return (i & 1) ? -(int)(i >> 1) : (i >> 1);
1249
}
1250
1251
static void dump_binannot(const unsigned char* ba, const char* last, unsigned indent)
1252
{
1253
while (ba < (const unsigned char*)last)
1254
{
1255
unsigned opcode = binannot_uncompress(&ba);
1256
switch (opcode)
1257
{
1258
case BA_OP_Invalid:
1259
/* not clear if param? */
1260
printf("%*s | Invalid\n", indent, "");
1261
break;
1262
case BA_OP_CodeOffset:
1263
printf("%*s | CodeOffset %u\n", indent, "", binannot_uncompress(&ba));
1264
break;
1265
case BA_OP_ChangeCodeOffsetBase:
1266
printf("%*s | ChangeCodeOffsetBase %u\n", indent, "", binannot_uncompress(&ba));
1267
break;
1268
case BA_OP_ChangeCodeOffset:
1269
printf("%*s | ChangeCodeOffset %u\n", indent, "", binannot_uncompress(&ba));
1270
break;
1271
case BA_OP_ChangeCodeLength:
1272
printf("%*s | ChangeCodeLength %u\n", indent, "", binannot_uncompress(&ba));
1273
break;
1274
case BA_OP_ChangeFile:
1275
printf("%*s | ChangeFile %u\n", indent, "", binannot_uncompress(&ba));
1276
break;
1277
case BA_OP_ChangeLineOffset:
1278
printf("%*s | ChangeLineOffset %d\n", indent, "", binannot_getsigned(binannot_uncompress(&ba)));
1279
break;
1280
case BA_OP_ChangeLineEndDelta:
1281
printf("%*s | ChangeLineEndDelta %u\n", indent, "", binannot_uncompress(&ba));
1282
break;
1283
case BA_OP_ChangeRangeKind:
1284
printf("%*s | ChangeRangeKind %u\n", indent, "", binannot_uncompress(&ba));
1285
break;
1286
case BA_OP_ChangeColumnStart:
1287
printf("%*s | ChangeColumnStart %u\n", indent, "", binannot_uncompress(&ba));
1288
break;
1289
case BA_OP_ChangeColumnEndDelta:
1290
printf("%*s | ChangeColumnEndDelta %u\n", indent, "", binannot_uncompress(&ba));
1291
break;
1292
case BA_OP_ChangeCodeOffsetAndLineOffset:
1293
{
1294
unsigned p1 = binannot_uncompress(&ba);
1295
printf("%*s | ChangeCodeOffsetAndLineOffset %u %d (0x%x)\n", indent, "", p1 & 0xf, binannot_getsigned(p1 >> 4), p1);
1296
}
1297
break;
1298
case BA_OP_ChangeCodeLengthAndCodeOffset:
1299
{
1300
unsigned p1 = binannot_uncompress(&ba);
1301
unsigned p2 = binannot_uncompress(&ba);
1302
printf("%*s | ChangeCodeLengthAndCodeOffset %u %u\n", indent, "", p1, p2);
1303
}
1304
break;
1305
case BA_OP_ChangeColumnEnd:
1306
printf("%*s | ChangeColumnEnd %u\n", indent, "", binannot_uncompress(&ba));
1307
break;
1308
1309
default: printf(">>> Unsupported op %d %x\n", opcode, opcode); /* may cause issues because of param */
1310
}
1311
}
1312
}
1313
1314
struct symbol_dumper
1315
{
1316
unsigned depth;
1317
unsigned alloc;
1318
struct
1319
{
1320
unsigned end;
1321
const union codeview_symbol* sym;
1322
}* stack;
1323
};
1324
1325
static void init_symbol_dumper(struct symbol_dumper* sd)
1326
{
1327
sd->depth = 0;
1328
sd->alloc = 16;
1329
sd->stack = xmalloc(sd->alloc * sizeof(sd->stack[0]));
1330
}
1331
1332
static void push_symbol_dumper(struct symbol_dumper* sd, const union codeview_symbol* sym, unsigned end)
1333
{
1334
if (!sd->stack) return;
1335
if (sd->depth >= sd->alloc) sd->stack = xrealloc(sd->stack, (sd->alloc *= 2) * sizeof(sd->stack[0]));
1336
sd->stack[sd->depth].end = end;
1337
sd->stack[sd->depth].sym = sym;
1338
sd->depth++;
1339
}
1340
1341
static unsigned short pop_symbol_dumper(struct symbol_dumper* sd, unsigned end)
1342
{
1343
if (!sd->stack) return 0;
1344
if (!sd->depth)
1345
{
1346
printf(">>> Error in stack\n");
1347
return 0;
1348
}
1349
sd->depth--;
1350
if (sd->stack[sd->depth].end != end)
1351
printf(">>> Wrong end reference\n");
1352
return sd->stack[sd->depth].sym->generic.id;
1353
}
1354
1355
static void dispose_symbol_dumper(struct symbol_dumper* sd)
1356
{
1357
free(sd->stack);
1358
}
1359
1360
BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long size)
1361
{
1362
unsigned int i;
1363
int length;
1364
struct symbol_dumper sd;
1365
1366
if (start == sizeof(unsigned))
1367
printf(" [header: %x]\n", *((unsigned*)root));
1368
1369
init_symbol_dumper(&sd);
1370
/*
1371
* Loop over the different types of records and whenever we
1372
* find something we are interested in, record it and move on.
1373
*/
1374
for (i = start; i < size; i += length)
1375
{
1376
const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i);
1377
unsigned indent, ref;
1378
1379
length = sym->generic.len + 2;
1380
if (!sym->generic.id || length < 4) break;
1381
indent = printf(" %04x => ", i);
1382
1383
switch (sym->generic.id)
1384
{
1385
case S_END:
1386
case S_INLINESITE_END:
1387
indent += printf("%*s", 2 * sd.depth - 2, "");
1388
break;
1389
default:
1390
indent += printf("%*s", 2 * sd.depth, "");
1391
break;
1392
}
1393
1394
switch (sym->generic.id)
1395
{
1396
/*
1397
* Global and local data symbols. We don't associate these
1398
* with any given source file.
1399
*/
1400
case S_GDATA32_ST:
1401
case S_LDATA32_ST:
1402
printf("%s-Data V2 '%s' %04x:%08x type:%08x\n",
1403
sym->generic.id == S_GDATA32_ST ? "Global" : "Local",
1404
get_symbol_str(p_string(&sym->data_v2.p_name)),
1405
sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype);
1406
break;
1407
1408
case S_LDATA32:
1409
case S_GDATA32:
1410
/* EPP case S_DATA32: */
1411
printf("%s-Data V3 '%s' (%04x:%08x) type:%08x\n",
1412
sym->generic.id == S_GDATA32 ? "Global" : "Local",
1413
get_symbol_str(sym->data_v3.name),
1414
sym->data_v3.segment, sym->data_v3.offset,
1415
sym->data_v3.symtype);
1416
break;
1417
1418
case S_PUB32_16t:
1419
printf("Public V1 '%s' %04x:%08x flags:%s\n",
1420
get_symbol_str(p_string(&sym->public_v1.p_name)),
1421
sym->public_v1.segment, sym->public_v1.offset,
1422
get_pubflags(sym->public_v1.pubsymflags));
1423
break;
1424
1425
case S_PUB32_ST:
1426
printf("Public V2 '%s' %04x:%08x flags:%s\n",
1427
get_symbol_str(p_string(&sym->public_v2.p_name)),
1428
sym->public_v2.segment, sym->public_v2.offset,
1429
get_pubflags(sym->public_v2.pubsymflags));
1430
break;
1431
1432
case S_PUB32:
1433
printf("Public V3 '%s' %04x:%08x flags:%s\n",
1434
get_symbol_str(sym->public_v3.name),
1435
sym->public_v3.segment, sym->public_v3.offset,
1436
get_pubflags(sym->public_v3.pubsymflags));
1437
break;
1438
1439
case S_DATAREF:
1440
case S_PROCREF:
1441
case S_LPROCREF:
1442
case S_TOKENREF:
1443
case S_ANNOTATIONREF:
1444
{
1445
const char *kind;
1446
switch (sym->generic.id)
1447
{
1448
case S_DATAREF: kind = "Data"; break;
1449
case S_PROCREF: kind = "Proc"; break;
1450
case S_LPROCREF: kind = "LProc"; break;
1451
case S_TOKENREF: kind = "Token"; break;
1452
case S_ANNOTATIONREF: kind = "Annotation"; break;
1453
default: kind = "----"; break;
1454
}
1455
printf("%sref V3 '%s' %04x:%08x name:%08x\n", kind, get_symbol_str(sym->refsym2_v3.name),
1456
sym->refsym2_v3.imod, sym->refsym2_v3.ibSym, sym->refsym2_v3.sumName);
1457
}
1458
break;
1459
1460
/*
1461
* Sort of like a global function, but it just points
1462
* to a thunk, which is a stupid name for what amounts to
1463
* a PLT slot in the normal jargon that everyone else uses.
1464
*/
1465
case S_THUNK32_ST:
1466
printf("Thunk V1 '%s' (%04x:%08x#%x) type:%x\n",
1467
p_string(&sym->thunk_v1.p_name),
1468
sym->thunk_v1.segment, sym->thunk_v1.offset,
1469
sym->thunk_v1.thunk_len, sym->thunk_v1.thtype);
1470
push_symbol_dumper(&sd, sym, sym->thunk_v1.pend);
1471
break;
1472
1473
case S_THUNK32:
1474
printf("Thunk V3 '%s' (%04x:%08x#%x) type:%x\n",
1475
sym->thunk_v3.name,
1476
sym->thunk_v3.segment, sym->thunk_v3.offset,
1477
sym->thunk_v3.thunk_len, sym->thunk_v3.thtype);
1478
push_symbol_dumper(&sd, sym, sym->thunk_v3.pend);
1479
break;
1480
1481
/* Global and static functions */
1482
case S_GPROC32_16t:
1483
case S_LPROC32_16t:
1484
printf("%s-Proc V1: '%s' (%04x:%08x#%x) type:%x attr:%x\n",
1485
sym->generic.id == S_GPROC32_16t ? "Global" : "Local",
1486
p_string(&sym->proc_v1.p_name),
1487
sym->proc_v1.segment, sym->proc_v1.offset,
1488
sym->proc_v1.proc_len, sym->proc_v1.proctype,
1489
sym->proc_v1.flags);
1490
printf("%*s\\- Debug: start=%08x end=%08x\n",
1491
indent, "", sym->proc_v1.debug_start, sym->proc_v1.debug_end);
1492
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
1493
indent, "", sym->proc_v1.pparent, sym->proc_v1.pend, sym->proc_v1.next);
1494
push_symbol_dumper(&sd, sym, sym->proc_v1.pend);
1495
break;
1496
1497
case S_GPROC32_ST:
1498
case S_LPROC32_ST:
1499
printf("%s-Proc V2: '%s' (%04x:%08x#%x) type:%x attr:%x\n",
1500
sym->generic.id == S_GPROC32_ST ? "Global" : "Local",
1501
p_string(&sym->proc_v2.p_name),
1502
sym->proc_v2.segment, sym->proc_v2.offset,
1503
sym->proc_v2.proc_len, sym->proc_v2.proctype,
1504
sym->proc_v2.flags);
1505
printf("%*s\\- Debug: start=%08x end=%08x\n",
1506
indent, "", sym->proc_v2.debug_start, sym->proc_v2.debug_end);
1507
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
1508
indent, "", sym->proc_v2.pparent, sym->proc_v2.pend, sym->proc_v2.next);
1509
push_symbol_dumper(&sd, sym, sym->proc_v2.pend);
1510
break;
1511
1512
case S_LPROC32:
1513
case S_GPROC32:
1514
printf("%s-Procedure V3 '%s' (%04x:%08x#%x) type:%x attr:%x\n",
1515
sym->generic.id == S_GPROC32 ? "Global" : "Local",
1516
sym->proc_v3.name,
1517
sym->proc_v3.segment, sym->proc_v3.offset,
1518
sym->proc_v3.proc_len, sym->proc_v3.proctype,
1519
sym->proc_v3.flags);
1520
printf("%*s\\- Debug: start=%08x end=%08x\n",
1521
indent, "", sym->proc_v3.debug_start, sym->proc_v3.debug_end);
1522
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
1523
indent, "", sym->proc_v3.pparent, sym->proc_v3.pend, sym->proc_v3.next);
1524
push_symbol_dumper(&sd, sym, sym->proc_v3.pend);
1525
break;
1526
1527
/* Function parameters and stack variables */
1528
case S_BPREL32_16t:
1529
printf("BP-relative V1: '%s' @%d type:%x\n",
1530
p_string(&sym->stack_v1.p_name),
1531
sym->stack_v1.offset, sym->stack_v1.symtype);
1532
break;
1533
1534
case S_BPREL32_ST:
1535
printf("BP-relative V2: '%s' @%d type:%x\n",
1536
p_string(&sym->stack_v2.p_name),
1537
sym->stack_v2.offset, sym->stack_v2.symtype);
1538
break;
1539
1540
case S_BPREL32:
1541
printf("BP-relative V3: '%s' @%d type:%x\n",
1542
sym->stack_v3.name, sym->stack_v3.offset,
1543
sym->stack_v3.symtype);
1544
break;
1545
1546
case S_REGREL32:
1547
printf("Reg-relative V3: '%s' @%d type:%x reg:%x\n",
1548
sym->regrel_v3.name, sym->regrel_v3.offset,
1549
sym->regrel_v3.symtype, sym->regrel_v3.reg);
1550
break;
1551
1552
case S_REGISTER_16t:
1553
printf("Register V1 '%s' type:%x register:%x\n",
1554
p_string(&sym->register_v1.p_name),
1555
sym->register_v1.reg, sym->register_v1.type);
1556
break;
1557
1558
case S_REGISTER_ST:
1559
printf("Register V2 '%s' type:%x register:%x\n",
1560
p_string(&sym->register_v2.p_name),
1561
sym->register_v2.reg, sym->register_v2.type);
1562
break;
1563
1564
case S_REGISTER:
1565
printf("Register V3 '%s' type:%x register:%x\n",
1566
sym->register_v3.name, sym->register_v3.reg, sym->register_v3.type);
1567
break;
1568
1569
case S_BLOCK32_ST:
1570
printf("Block V1 '%s' (%04x:%08x#%08x)\n",
1571
p_string(&sym->block_v1.p_name),
1572
sym->block_v1.segment, sym->block_v1.offset,
1573
sym->block_v1.length);
1574
push_symbol_dumper(&sd, sym, sym->block_v1.end);
1575
break;
1576
1577
case S_BLOCK32:
1578
printf("Block V3 '%s' (%04x:%08x#%08x) parent:<%u> end:<%x>\n",
1579
sym->block_v3.name,
1580
sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length,
1581
sym->block_v3.parent, sym->block_v3.end);
1582
push_symbol_dumper(&sd, sym, sym->block_v3.end);
1583
break;
1584
1585
/* Additional function information */
1586
case S_FRAMEPROC:
1587
printf("Frame-Info V2: frame-size:%x unk2:%x unk3:%x saved-regs-sz:%x eh(%04x:%08x) flags:%08x\n",
1588
sym->frame_info_v2.sz_frame,
1589
sym->frame_info_v2.unknown2,
1590
sym->frame_info_v2.unknown3,
1591
sym->frame_info_v2.sz_saved_regs,
1592
sym->frame_info_v2.eh_sect,
1593
sym->frame_info_v2.eh_offset,
1594
sym->frame_info_v2.flags);
1595
break;
1596
1597
case S_FRAMECOOKIE:
1598
printf("Security Cookie V3 @%d unk:%x\n",
1599
sym->security_cookie_v3.offset, sym->security_cookie_v3.unknown);
1600
break;
1601
1602
case S_END:
1603
ref = sd.depth ? (const char*)sd.stack[sd.depth - 1].sym - (const char*)root : 0;
1604
switch (pop_symbol_dumper(&sd, i))
1605
{
1606
case S_BLOCK32_ST:
1607
case S_BLOCK32:
1608
printf("End-Of block <%x>\n", ref);
1609
break;
1610
default:
1611
printf("End-Of <%x>\n", ref);
1612
break;
1613
}
1614
break;
1615
1616
case S_COMPILE:
1617
printf("Compile V1 machine:%s lang:%s _unk:%x '%s'\n",
1618
get_machine(sym->compile_v1.machine),
1619
get_language(sym->compile_v1.flags.language),
1620
sym->compile_v1.flags._dome,
1621
p_string(&sym->compile_v1.p_name));
1622
break;
1623
1624
case S_COMPILE2_ST:
1625
printf("Compile2-V2 lang:%s machine:%s _unk:%x front-end:%d.%d.%d back-end:%d.%d.%d '%s'\n",
1626
get_language(sym->compile2_v2.flags.iLanguage),
1627
get_machine(sym->compile2_v2.machine),
1628
sym->compile2_v2.flags._dome,
1629
sym->compile2_v2.fe_major, sym->compile2_v2.fe_minor, sym->compile2_v2.fe_build,
1630
sym->compile2_v2.be_major, sym->compile2_v2.be_minor, sym->compile2_v2.be_build,
1631
p_string(&sym->compile2_v2.p_name));
1632
{
1633
const char* ptr = sym->compile2_v2.p_name.name + sym->compile2_v2.p_name.namelen;
1634
while (*ptr)
1635
{
1636
printf("%*s| %s => ", indent, "", ptr); ptr += strlen(ptr) + 1;
1637
printf("%s\n", ptr); ptr += strlen(ptr) + 1;
1638
}
1639
}
1640
break;
1641
1642
case S_COMPILE2:
1643
printf("Compile2-V3 lang:%s machine:%s _unk:%x front-end:%d.%d.%d back-end:%d.%d.%d '%s'\n",
1644
get_language(sym->compile2_v3.flags.iLanguage),
1645
get_machine(sym->compile2_v3.machine),
1646
sym->compile2_v3.flags._dome,
1647
sym->compile2_v3.fe_major, sym->compile2_v3.fe_minor, sym->compile2_v3.fe_build,
1648
sym->compile2_v3.be_major, sym->compile2_v3.be_minor, sym->compile2_v3.be_build,
1649
sym->compile2_v3.name);
1650
{
1651
const char* ptr = sym->compile2_v3.name + strlen(sym->compile2_v3.name) + 1;
1652
while (*ptr)
1653
{
1654
printf("%*s| %s => ", indent, "", ptr); ptr += strlen(ptr) + 1;
1655
printf("%s\n", ptr); ptr += strlen(ptr) + 1;
1656
}
1657
}
1658
break;
1659
1660
case S_COMPILE3:
1661
printf("Compile3-V3 lang:%s machine:%s _unk:%x front-end:%d.%d.%d back-end:%d.%d.%d '%s'\n",
1662
get_language(sym->compile3_v3.flags.iLanguage),
1663
get_machine(sym->compile3_v3.machine),
1664
sym->compile3_v3.flags._dome,
1665
sym->compile3_v3.fe_major, sym->compile3_v3.fe_minor, sym->compile3_v3.fe_build,
1666
sym->compile3_v3.be_major, sym->compile3_v3.be_minor, sym->compile3_v3.be_build,
1667
sym->compile3_v3.name);
1668
break;
1669
1670
case S_ENVBLOCK:
1671
{
1672
const char* x1 = (const char*)sym + 4 + 1;
1673
const char* x2;
1674
1675
printf("Tool conf V3\n");
1676
while (*x1)
1677
{
1678
x2 = x1 + strlen(x1) + 1;
1679
if (!*x2) break;
1680
printf("%*s| %s: %s\n", indent, "", x1, x2);
1681
x1 = x2 + strlen(x2) + 1;
1682
}
1683
}
1684
break;
1685
1686
case S_OBJNAME:
1687
printf("ObjName V3 sig:%x '%s'\n",
1688
sym->objname_v3.signature, sym->objname_v3.name);
1689
break;
1690
1691
case S_OBJNAME_ST:
1692
printf("ObjName V1 sig:%x '%s'\n",
1693
sym->objname_v1.signature, p_string(&sym->objname_v1.p_name));
1694
break;
1695
1696
case S_TRAMPOLINE:
1697
printf("Trampoline V3 kind:%u %04x:%08x#%x -> %04x:%08x\n",
1698
sym->trampoline_v3.trampType,
1699
sym->trampoline_v3.sectThunk,
1700
sym->trampoline_v3.offThunk,
1701
sym->trampoline_v3.cbThunk,
1702
sym->trampoline_v3.sectTarget,
1703
sym->trampoline_v3.offTarget);
1704
break;
1705
1706
case S_LABEL32_ST:
1707
printf("Label V1 '%s' (%04x:%08x)\n",
1708
p_string(&sym->label_v1.p_name),
1709
sym->label_v1.segment, sym->label_v1.offset);
1710
break;
1711
1712
case S_LABEL32:
1713
printf("Label V3 '%s' (%04x:%08x) flag:%x\n",
1714
sym->label_v3.name, sym->label_v3.segment,
1715
sym->label_v3.offset, sym->label_v3.flags);
1716
break;
1717
1718
case S_CONSTANT_ST:
1719
{
1720
int vlen;
1721
struct full_value fv;
1722
1723
vlen = full_numeric_leaf(&fv, sym->constant_v2.data);
1724
printf("Constant V2 '%s' = %s type:%x\n",
1725
p_string((const struct p_string *)&sym->constant_v2.data[vlen]),
1726
full_value_string(&fv), sym->constant_v2.type);
1727
}
1728
break;
1729
1730
case S_CONSTANT:
1731
{
1732
int vlen;
1733
struct full_value fv;
1734
1735
vlen = full_numeric_leaf(&fv, sym->constant_v3.data);
1736
printf("Constant V3 '%s' = %s type:%x\n",
1737
(const char*)&sym->constant_v3.data[vlen],
1738
full_value_string(&fv), sym->constant_v3.type);
1739
}
1740
break;
1741
1742
case S_UDT_16t:
1743
printf("Udt V1 '%s': type:0x%x\n",
1744
p_string(&sym->udt_v1.p_name), sym->udt_v1.type);
1745
break;
1746
1747
case S_UDT_ST:
1748
printf("Udt V2 '%s': type:0x%x\n",
1749
p_string(&sym->udt_v2.p_name), sym->udt_v2.type);
1750
break;
1751
1752
case S_UDT:
1753
printf("Udt V3 '%s': type:0x%x\n",
1754
sym->udt_v3.name, sym->udt_v3.type);
1755
break;
1756
/*
1757
* These are special, in that they are always followed by an
1758
* additional length-prefixed string which is *not* included
1759
* into the symbol length count. We need to skip it.
1760
*/
1761
case S_PROCREF_ST:
1762
printf("Procref V1 "); goto doaref;
1763
case S_DATAREF_ST:
1764
printf("Dataref V1 "); goto doaref;
1765
case S_LPROCREF_ST:
1766
printf("L-Procref V1 "); goto doaref;
1767
doaref:
1768
{
1769
const struct p_string* pname;
1770
1771
pname = PSTRING(sym, length);
1772
length += (pname->namelen + 1 + 3) & ~3;
1773
printf("%08x %08x %08x '%s'\n",
1774
((const UINT *)sym)[1], ((const UINT *)sym)[2], ((const UINT *)sym)[3],
1775
p_string(pname));
1776
}
1777
break;
1778
1779
case S_ALIGN:
1780
/* simply skip it */
1781
break;
1782
1783
case S_SSEARCH:
1784
printf("Search V1: (%04x:%08x)\n",
1785
sym->ssearch_v1.segment, sym->ssearch_v1.offset);
1786
break;
1787
1788
case S_SECTION:
1789
printf("Section Info: seg=%04x ?=%04x rva=%08x size=%08x attr=%08x %s\n",
1790
*(const unsigned short*)((const char*)sym + 4),
1791
*(const unsigned short*)((const char*)sym + 6),
1792
*(const unsigned*)((const char*)sym + 8),
1793
*(const unsigned*)((const char*)sym + 12),
1794
*(const unsigned*)((const char*)sym + 16),
1795
(const char*)sym + 20);
1796
break;
1797
1798
case S_COFFGROUP:
1799
printf("SubSection Info: addr=%04x:%08x size=%08x attr=%08x %s\n",
1800
*(const unsigned short*)((const char*)sym + 16),
1801
*(const unsigned*)((const char*)sym + 12),
1802
*(const unsigned*)((const char*)sym + 4),
1803
*(const unsigned*)((const char*)sym + 8),
1804
(const char*)sym + 18);
1805
break;
1806
1807
case S_EXPORT:
1808
printf("EntryPoint: id=%x '%s'\n",
1809
*(const unsigned*)((const char*)sym + 4), (const char*)sym + 8);
1810
break;
1811
1812
case S_LTHREAD32_16t:
1813
case S_GTHREAD32_16t:
1814
printf("Thread %s Var V1 '%s' seg=%04x offset=%08x type=%x\n",
1815
sym->generic.id == S_LTHREAD32_16t ? "global" : "local",
1816
p_string(&sym->thread_v1.p_name),
1817
sym->thread_v1.segment, sym->thread_v1.offset, sym->thread_v1.symtype);
1818
break;
1819
1820
case S_LTHREAD32_ST:
1821
case S_GTHREAD32_ST:
1822
printf("Thread %s Var V2 '%s' seg=%04x offset=%08x type=%x\n",
1823
sym->generic.id == S_LTHREAD32_ST ? "global" : "local",
1824
p_string(&sym->thread_v2.p_name),
1825
sym->thread_v2.segment, sym->thread_v2.offset, sym->thread_v2.symtype);
1826
break;
1827
1828
case S_LTHREAD32:
1829
case S_GTHREAD32:
1830
printf("Thread %s Var V3 '%s' seg=%04x offset=%08x type=%x\n",
1831
sym->generic.id == S_LTHREAD32 ? "global" : "local", sym->thread_v3.name,
1832
sym->thread_v3.segment, sym->thread_v3.offset, sym->thread_v3.symtype);
1833
break;
1834
1835
case S_LOCAL:
1836
printf("Local V3 '%s' type=%x flags=%s\n",
1837
sym->local_v3.name, sym->local_v3.symtype,
1838
get_varflags(sym->local_v3.varflags));
1839
break;
1840
1841
case S_DEFRANGE:
1842
printf("DefRange dia:%x\n", sym->defrange_v3.program);
1843
dump_defrange(&sym->defrange_v3.range, get_last(sym), indent);
1844
break;
1845
case S_DEFRANGE_SUBFIELD:
1846
printf("DefRange-subfield V3 dia:%x off-parent:%x\n",
1847
sym->defrange_subfield_v3.program, sym->defrange_subfield_v3.offParent);
1848
dump_defrange(&sym->defrange_subfield_v3.range, get_last(sym), indent);
1849
break;
1850
case S_DEFRANGE_REGISTER:
1851
printf("DefRange-register V3 reg:%x attr-unk:%x\n",
1852
sym->defrange_register_v3.reg, sym->defrange_register_v3.attr);
1853
dump_defrange(&sym->defrange_register_v3.range, get_last(sym), indent);
1854
break;
1855
case S_DEFRANGE_FRAMEPOINTER_REL:
1856
printf("DefRange-framepointer-rel V3 offFP:%x\n",
1857
sym->defrange_frameptrrel_v3.offFramePointer);
1858
dump_defrange(&sym->defrange_frameptrrel_v3.range, get_last(sym), indent);
1859
break;
1860
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
1861
printf("DefRange-framepointer-rel-fullscope V3 offFP:%x\n",
1862
sym->defrange_frameptr_relfullscope_v3.offFramePointer);
1863
break;
1864
case S_DEFRANGE_SUBFIELD_REGISTER:
1865
printf("DefRange-subfield-register V3 reg:%d attr-unk:%x off-parent:%x\n",
1866
sym->defrange_subfield_register_v3.reg,
1867
sym->defrange_subfield_register_v3.attr,
1868
sym->defrange_subfield_register_v3.offParent);
1869
dump_defrange(&sym->defrange_subfield_register_v3.range, get_last(sym), indent);
1870
break;
1871
case S_DEFRANGE_REGISTER_REL:
1872
printf("DefRange-register-rel V3 reg:%x off-parent:%x off-BP:%x\n",
1873
sym->defrange_registerrel_v3.baseReg, sym->defrange_registerrel_v3.offsetParent,
1874
sym->defrange_registerrel_v3.offBasePointer);
1875
dump_defrange(&sym->defrange_registerrel_v3.range, get_last(sym), indent);
1876
break;
1877
1878
case S_CALLSITEINFO:
1879
printf("Call-site-info V3 %04x:%08x typeindex:%x\n",
1880
sym->callsiteinfo_v3.sect, sym->callsiteinfo_v3.off, sym->callsiteinfo_v3.typind);
1881
break;
1882
1883
case S_BUILDINFO:
1884
printf("Build-info V3 item:%04x\n", sym->build_info_v3.itemid);
1885
break;
1886
1887
case S_INLINESITE:
1888
printf("Inline-site V3 parent:<%x> end:<%x> inlinee:%x\n",
1889
sym->inline_site_v3.pParent, sym->inline_site_v3.pEnd, sym->inline_site_v3.inlinee);
1890
dump_binannot(sym->inline_site_v3.binaryAnnotations, get_last(sym), indent);
1891
push_symbol_dumper(&sd, sym, sym->inline_site_v3.pEnd);
1892
break;
1893
1894
case S_INLINESITE2:
1895
printf("Inline-site2 V3 parent:<%x> end:<%x> inlinee:%x #inv:%u\n",
1896
sym->inline_site2_v3.pParent, sym->inline_site2_v3.pEnd, sym->inline_site2_v3.inlinee,
1897
sym->inline_site2_v3.invocations);
1898
dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), indent);
1899
push_symbol_dumper(&sd, sym, sym->inline_site2_v3.pEnd);
1900
break;
1901
1902
case S_INLINESITE_END:
1903
ref = sd.depth ? (const char*)sd.stack[sd.depth - 1].sym - (const char*)root : 0;
1904
pop_symbol_dumper(&sd, i);
1905
printf("Inline-site-end <%x>\n", ref);
1906
break;
1907
1908
case S_CALLEES:
1909
case S_CALLERS:
1910
case S_INLINEES:
1911
{
1912
unsigned i, ninvoc;
1913
const cv_typ_t *functions;
1914
const unsigned* invoc;
1915
const char* tag;
1916
1917
if (sym->generic.id == S_CALLERS) tag = "Callers";
1918
else if (sym->generic.id == S_CALLEES) tag = "Callees";
1919
else tag = "Inlinees";
1920
printf("%s V3 count:%u\n", tag, sym->function_list_v3.count);
1921
functions = (const cv_typ_t *)&sym->function_list_v3.data;
1922
invoc = (const unsigned*)&functions[sym->function_list_v3.count];
1923
ninvoc = (const unsigned*)get_last(sym) - invoc;
1924
if (ninvoc < sym->function_list_v3.count) ninvoc = sym->function_list_v3.count;
1925
1926
for (i = 0; i < ninvoc; ++i)
1927
printf("%*s| func:%x invoc:%u\n",
1928
indent, "", functions[i], invoc[i]);
1929
if (i < sym->function_list_v3.count) printf("Number of entries exceed symbol serialized size\n");
1930
}
1931
break;
1932
1933
case S_HEAPALLOCSITE:
1934
printf("Heap-alloc-site V3 %04x:%08x#%x type:%04x\n",
1935
sym->heap_alloc_site_v3.sect_idx,
1936
sym->heap_alloc_site_v3.offset,
1937
sym->heap_alloc_site_v3.inst_len,
1938
sym->heap_alloc_site_v3.index);
1939
break;
1940
1941
case S_FILESTATIC:
1942
printf("File-static V3 '%s' type:%04x modOff:%08x flags:%s\n",
1943
sym->file_static_v3.name,
1944
sym->file_static_v3.typind,
1945
sym->file_static_v3.modOffset,
1946
get_varflags(sym->file_static_v3.varflags));
1947
break;
1948
1949
case S_UNAMESPACE_ST:
1950
printf("UNameSpace V2 '%s'\n", p_string(&sym->unamespace_v2.pname));
1951
break;
1952
1953
case S_UNAMESPACE:
1954
printf("UNameSpace V3 '%s'\n", sym->unamespace_v3.name);
1955
break;
1956
1957
case S_SEPCODE:
1958
printf("SepCode V3 parent:<%x> end:<%x> separated:%04x:%08x (#%u) from %04x:%08x\n",
1959
sym->sepcode_v3.pParent, sym->sepcode_v3.pEnd,
1960
sym->sepcode_v3.sect, sym->sepcode_v3.off, sym->sepcode_v3.length,
1961
sym->sepcode_v3.sectParent, sym->sepcode_v3.offParent);
1962
push_symbol_dumper(&sd, sym, sym->sepcode_v3.pEnd);
1963
break;
1964
1965
case S_ANNOTATION:
1966
printf("Annotation V3 %04x:%08x\n",
1967
sym->annotation_v3.seg, sym->annotation_v3.off);
1968
{
1969
const char* ptr = sym->annotation_v3.rgsz;
1970
const char* last = ptr + sym->annotation_v3.csz;
1971
for (; ptr < last; ptr += strlen(ptr) + 1)
1972
printf("%*s| %s\n", indent, "", ptr);
1973
}
1974
break;
1975
1976
case S_POGODATA:
1977
printf("PogoData V3 inv:%d dynCnt:%lld inst:%d staInst:%d\n",
1978
sym->pogoinfo_v3.invocations, (long long)sym->pogoinfo_v3.dynCount,
1979
sym->pogoinfo_v3.numInstrs, sym->pogoinfo_v3.staInstLive);
1980
break;
1981
1982
case S_GMANPROC:
1983
case S_LMANPROC:
1984
printf("%s Managed Procedure V3: '%s' (%04x:%08x#%x) attr:%x\n",
1985
sym->generic.id == S_GMANPROC ? "Global" : "Local",
1986
sym->managed_proc_v3.name,
1987
sym->managed_proc_v3.sect, sym->managed_proc_v3.off, sym->managed_proc_v3.proc_len,
1988
sym->managed_proc_v3.flags);
1989
printf("%*s\\- Debug: start=%08x end=%08x\n",
1990
indent, "", sym->managed_proc_v3.debug_start, sym->managed_proc_v3.debug_end);
1991
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
1992
indent, "", sym->managed_proc_v3.pparent, sym->managed_proc_v3.pend, sym->managed_proc_v3.pnext);
1993
printf("%*s\\- token:%x retReg:%x\n",
1994
indent, "", sym->managed_proc_v3.token, sym->managed_proc_v3.ret_reg);
1995
push_symbol_dumper(&sd, sym, sym->managed_proc_v3.pend);
1996
break;
1997
1998
case S_MANSLOT:
1999
printf("Managed slot V3: '%s' type:%x attr:%s slot:%u\n",
2000
sym->managed_slot_v3.name, sym->managed_slot_v3.typeid,
2001
get_varflags(sym->managed_slot_v3.attr), sym->managed_slot_v3.islot);
2002
break;
2003
2004
case S_OEM:
2005
printf("OEM symbol V3 guid=%s type=%x\n",
2006
get_guid_str(&sym->oem_v3.idOEM), sym->oem_v3.typeid);
2007
{
2008
const unsigned int *from = (const void*)sym->oem_v3.rgl;
2009
const unsigned int *last = (unsigned int*)((unsigned char*)sym + 2 + sym->generic.len);
2010
printf("%*s\\- rgl: [", indent, "");
2011
for (; from < last; from++) printf("%08x%s", *from, (from + 1) < last ? " " : "");
2012
printf("]\n");
2013
}
2014
break;
2015
2016
case S_ARMSWITCHTABLE:
2017
printf("ARM switch table type=%u base=%04x:%08x branch=%04x:%08x table=%04x:%08x entries=#%u\n",
2018
sym->armswitchtable.switch_type,
2019
sym->armswitchtable.base_section, sym->armswitchtable.base_offset,
2020
sym->armswitchtable.branch_section, sym->armswitchtable.branch_offset,
2021
sym->armswitchtable.table_section, sym->armswitchtable.table_offset,
2022
sym->armswitchtable.number_entries);
2023
break;
2024
default:
2025
printf("\n\t\t>>> Unsupported symbol-id %x sz=%d\n", sym->generic.id, sym->generic.len + 2);
2026
dump_data((const void*)sym, sym->generic.len + 2, " ");
2027
}
2028
}
2029
dispose_symbol_dumper(&sd);
2030
return TRUE;
2031
}
2032
2033
void codeview_dump_linetab(const char* linetab, BOOL pascal_str, const char* pfx)
2034
{
2035
const char* ptr = linetab;
2036
int nfile, nseg, nline;
2037
int i, j, k;
2038
const unsigned int* filetab;
2039
const unsigned int* lt_ptr;
2040
const struct startend* start;
2041
2042
nfile = *(const short*)linetab;
2043
filetab = (const unsigned int*)(linetab + 2 * sizeof(short));
2044
printf("%s%d files with %d ???\n", pfx, nfile, *(const short*)(linetab + sizeof(short)));
2045
2046
for (i = 0; i < nfile; i++)
2047
{
2048
ptr = linetab + filetab[i];
2049
nseg = *(const short*)ptr;
2050
ptr += 2 * sizeof(short);
2051
lt_ptr = (const unsigned int*)ptr;
2052
start = (const struct startend*)(lt_ptr + nseg);
2053
2054
/*
2055
* Now snarf the filename for all of the segments for this file.
2056
*/
2057
if (pascal_str)
2058
{
2059
char filename[MAX_PATH];
2060
const struct p_string* p_fn;
2061
2062
p_fn = (const struct p_string*)(start + nseg);
2063
memset(filename, 0, sizeof(filename));
2064
memcpy(filename, p_fn->name, p_fn->namelen);
2065
printf("%slines for file #%d/%d %s %d\n", pfx, i, nfile, filename, nseg);
2066
}
2067
else
2068
printf("%slines for file #%d/%d %s %d\n", pfx, i, nfile, (const char*)(start + nseg), nseg);
2069
2070
for (j = 0; j < nseg; j++)
2071
{
2072
ptr = linetab + *lt_ptr++;
2073
nline = *(const short*)(ptr + 2);
2074
printf("%s %04x:%08x-%08x #%d\n",
2075
pfx, *(const short*)(ptr + 0), start[j].start, start[j].end, nline);
2076
ptr += 4;
2077
for (k = 0; k < nline; k++)
2078
{
2079
printf("%s %x %d\n",
2080
pfx, ((const unsigned int*)ptr)[k],
2081
((const unsigned short*)((const unsigned int*)ptr + nline))[k]);
2082
}
2083
}
2084
}
2085
}
2086
2087
void codeview_dump_linetab2(const char* linetab, DWORD size, const PDB_STRING_TABLE* strimage, const char* pfx)
2088
{
2089
unsigned i;
2090
const struct CV_DebugSSubsectionHeader_t* hdr;
2091
const struct CV_DebugSSubsectionHeader_t* next_hdr;
2092
const struct CV_DebugSLinesHeader_t* lines_hdr;
2093
const struct CV_DebugSLinesFileBlockHeader_t* files_hdr;
2094
const struct CV_Column_t* cols;
2095
const struct CV_Checksum_t* chksms;
2096
const struct CV_InlineeSourceLine_t* inlsrc;
2097
const struct CV_InlineeSourceLineEx_t* inlsrcex;
2098
2099
static const char* subsect_types[] = /* starting at 0xf1 */
2100
{
2101
"SYMBOLS", "LINES", "STRINGTABLE", "FILECHKSMS",
2102
"FRAMEDATA", "INLINEELINES", "CROSSSCOPEIMPORTS", "CROSSSCOPEEXPORTS",
2103
"IL_LINES", "FUNC_MDTOKEN_MAP", "TYPE_MDTOKEN_MAP", "MERGED_ASSEMBLYINPUT",
2104
"COFF_SYMBOL_RVA"
2105
};
2106
hdr = (const struct CV_DebugSSubsectionHeader_t*)linetab;
2107
while (CV_IS_INSIDE(hdr, linetab + size))
2108
{
2109
next_hdr = CV_RECORD_GAP(hdr, hdr->cbLen);
2110
if (hdr->type & DEBUG_S_IGNORE)
2111
{
2112
printf("%s------ debug subsection <ignored>\n", pfx);
2113
hdr = next_hdr;
2114
continue;
2115
}
2116
2117
printf("%s------ debug subsection %s\n", pfx,
2118
(hdr->type >= 0xf1 && hdr->type - 0xf1 < ARRAY_SIZE(subsect_types)) ?
2119
subsect_types[hdr->type - 0xf1] : "<<unknown>>");
2120
switch (hdr->type)
2121
{
2122
case DEBUG_S_LINES:
2123
lines_hdr = CV_RECORD_AFTER(hdr);
2124
printf("%s block from %04x:%08x flags:%x size=%u\n",
2125
pfx, lines_hdr->segCon, lines_hdr->offCon, lines_hdr->flags, lines_hdr->cbCon);
2126
files_hdr = CV_RECORD_AFTER(lines_hdr);
2127
/* FIXME: as of today partial coverage:
2128
* - only one files_hdr has been seen in PDB files
2129
* OTOH, MS github presents two different structures
2130
* llvm ? one or two
2131
* - next files_hdr (depending on previous question, can be a void question)
2132
* is code correct ; what do MS and llvm do?
2133
*/
2134
while (CV_IS_INSIDE(files_hdr, next_hdr))
2135
{
2136
const struct CV_Line_t* lines;
2137
printf("%s file=%u lines=%d size=%x\n", pfx, files_hdr->offFile,
2138
files_hdr->nLines, files_hdr->cbBlock);
2139
lines = CV_RECORD_AFTER(files_hdr);
2140
cols = (const struct CV_Column_t*)&lines[files_hdr->nLines];
2141
for (i = 0; i < files_hdr->nLines; i++)
2142
{
2143
printf("%s offset=%8x line=%d deltaLineEnd=%u %s",
2144
pfx, lines[i].offset, lines[i].linenumStart, lines[i].deltaLineEnd,
2145
lines[i].fStatement ? "statement" : "expression");
2146
if (lines_hdr->flags & CV_LINES_HAVE_COLUMNS)
2147
printf(" cols[start=%u end=%u]",
2148
cols[i].offColumnStart, cols[i].offColumnEnd);
2149
printf("\n");
2150
}
2151
if (lines_hdr->flags & CV_LINES_HAVE_COLUMNS)
2152
files_hdr = (const struct CV_DebugSLinesFileBlockHeader_t*)&cols[files_hdr->nLines];
2153
else
2154
files_hdr = (const struct CV_DebugSLinesFileBlockHeader_t*)&lines[files_hdr->nLines];
2155
}
2156
break;
2157
case DEBUG_S_FILECHKSMS:
2158
chksms = CV_RECORD_AFTER(hdr);
2159
while (CV_IS_INSIDE(chksms, next_hdr))
2160
{
2161
const char* meth[] = {"None", "MD5", "SHA1", "SHA256"};
2162
printf("%s %d] name=%s size=%u method=%s checksum=[",
2163
pfx, (unsigned)((const char*)chksms - (const char*)(hdr + 1)),
2164
pdb_get_string_table_entry(strimage, chksms->strOffset),
2165
chksms->size, chksms->method < ARRAY_SIZE(meth) ? meth[chksms->method] : "<<unknown>>");
2166
for (i = 0; i < chksms->size; ++i) printf("%02x", chksms->checksum[i]);
2167
printf("]\n");
2168
chksms = CV_ALIGN(CV_RECORD_GAP(chksms, chksms->size), 4);
2169
}
2170
break;
2171
case DEBUG_S_INLINEELINES:
2172
/* subsection starts with a DWORD signature */
2173
switch (*(DWORD*)CV_RECORD_AFTER(hdr))
2174
{
2175
case CV_INLINEE_SOURCE_LINE_SIGNATURE:
2176
inlsrc = CV_RECORD_GAP(hdr, sizeof(DWORD));
2177
while (CV_IS_INSIDE(inlsrc, next_hdr))
2178
{
2179
printf("%s inlinee=%x fileref=%d srcstart=%d\n",
2180
pfx, inlsrc->inlinee, inlsrc->fileId, inlsrc->sourceLineNum);
2181
++inlsrc;
2182
}
2183
break;
2184
case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX:
2185
inlsrcex = CV_RECORD_GAP(hdr, sizeof(DWORD));
2186
while (CV_IS_INSIDE(inlsrcex, next_hdr))
2187
{
2188
printf("%s inlinee=%x fileref=%d srcstart=%d numExtraFiles=%d\n",
2189
pfx, inlsrcex->inlinee, inlsrcex->fileId, inlsrcex->sourceLineNum,
2190
inlsrcex->countOfExtraFiles);
2191
inlsrcex = CV_RECORD_GAP(inlsrcex, inlsrcex->countOfExtraFiles * sizeof(inlsrcex->extraFileId[0]));
2192
}
2193
break;
2194
default:
2195
printf("%sUnknown signature %x in INLINEELINES subsection\n", pfx, *(UINT *)CV_RECORD_AFTER(hdr));
2196
break;
2197
}
2198
break;
2199
default:
2200
dump_data(CV_RECORD_AFTER(hdr), hdr->cbLen, pfx);
2201
break;
2202
}
2203
hdr = next_hdr;
2204
}
2205
}
2206
2207