- Remove WIP comment -- the fix is correct
[reactos.git] / rosapps / applications / devutils / symdump / symdump.c
1 /*
2 * PE symbol dumper
3 *
4 * symdump.c
5 *
6 * Copyright (c) 2008 Timo Kreuzer <timo <dot> kreuzer <at> reactos <dot> org>
7 *
8 * This program is released under the terms of the GNU GPL.
9 *
10 * TODO:
11 * - fix GDILoObjType
12 * - fix UDTKind1
13 * - include the correct headers for some stuff
14 * - fix unions like LARGE_INTEGER
15 */
16
17 #include <stdio.h>
18 #define _WINVER 0x501
19 #include <windows.h>
20 #include <shlwapi.h>
21 #include <dbghelp.h>
22
23 HANDLE hCurrentProcess;
24 BOOL g_bShowPos = 0;
25
26 #define MAX_SYMBOL_NAME 1024
27
28 #define CV_CALL_NEAR_C 0x00
29 #define CV_CALL_FAR_C 0x01
30 #define CV_CALL_NEAR_PASCAL 0x02
31 #define CV_CALL_FAR_PASCAL 0x03
32 #define CV_CALL_NEAR_FAST 0x04
33 #define CV_CALL_FAR_FAST 0x05
34 #define CV_CALL_SKIPPED 0x06
35 #define CV_CALL_NEAR_STD 0x07
36 #define CV_CALL_FAR_STD 0x08
37 #define CV_CALL_NEAR_SYS 0x09
38 #define CV_CALL_FAR_SYS 0x0a
39 #define CV_CALL_THISCALL 0x0b
40 #define CV_CALL_MIPSCALL 0x0c
41 #define CV_CALL_GENERIC 0x0d
42 #define CV_CALL_ALPHACALL 0x0e
43 #define CV_CALL_PPCCALL 0x0f
44 #define CV_CALL_SHCALL 0x10
45 #define CV_CALL_ARMCALL 0x11
46 #define CV_CALL_AM33CALL 0x12
47 #define CV_CALL_TRICALL 0x13
48 #define CV_CALL_SH5CALL 0x14
49 #define CV_CALL_M32RCALL 0x15
50
51 enum SymTagEnum
52 {
53 SymTagNull,
54 SymTagExe,
55 SymTagCompiland,
56 SymTagCompilandDetails,
57 SymTagCompilandEnv,
58 SymTagFunction,
59 SymTagBlock,
60 SymTagData,
61 SymTagAnnotation,
62 SymTagLabel,
63 SymTagPublicSymbol,
64 SymTagUDT,
65 SymTagEnum,
66 SymTagFunctionType,
67 SymTagPointerType,
68 SymTagArrayType,
69 SymTagBaseType,
70 SymTagTypedef,
71 SymTagBaseClass,
72 SymTagFriend,
73 SymTagFunctionArgType,
74 SymTagFuncDebugStart,
75 SymTagFuncDebugEnd,
76 SymTagUsingNamespace,
77 SymTagVTableShape,
78 SymTagVTable,
79 SymTagCustom,
80 SymTagThunk,
81 SymTagCustomType,
82 SymTagManagedType,
83 SymTagDimension,
84 SymTagMax
85 };
86
87 enum
88 {
89 UDTKind_Struct = 0,
90 UDTKind_Class = 1, /* ? */
91 UDTKind_Union = 2,
92 };
93
94 enum BasicType
95 {
96 btNoType = 0,
97 btVoid = 1,
98 btChar = 2,
99 btWChar = 3,
100 btInt = 6,
101 btUInt = 7,
102 btFloat = 8,
103 btBCD = 9,
104 btBool = 10,
105 btLong = 13,
106 btULong = 14,
107 btCurrency = 25,
108 btDate = 26,
109 btVariant = 27,
110 btComplex = 28,
111 btBit = 29,
112 btBSTR = 30,
113 btHresult = 31
114 };
115
116 typedef struct
117 {
118 HANDLE hProcess;
119 DWORD64 dwModuleBase;
120 LPSTR pszSymbolName;
121 BOOL bType;
122 } ENUMINFO, *PENUMINFO;
123
124 VOID DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers);
125
126 CHAR *SymTagString[] =
127 {
128 "SymTagNull",
129 "SymTagExe",
130 "SymTagCompiland",
131 "SymTagCompilandDetails",
132 "SymTagCompilandEnv",
133 "SymTagFunction",
134 "SymTagBlock",
135 "SymTagData",
136 "SymTagAnnotation",
137 "SymTagLabel",
138 "SymTagPublicSymbol",
139 "SymTagUDT",
140 "SymTagEnum",
141 "SymTagFunctionType",
142 "SymTagPointerType",
143 "SymTagArrayType",
144 "SymTagBaseType",
145 "SymTagTypedef",
146 "SymTagBaseClass",
147 "SymTagFriend",
148 "SymTagFunctionArgType",
149 "SymTagFuncDebugStart",
150 "SymTagFuncDebugEnd",
151 "SymTagUsingNamespace",
152 "SymTagVTableShape",
153 "SymTagVTable",
154 "SymTagCustom",
155 "SymTagThunk",
156 "SymTagCustomType",
157 "SymTagManagedType",
158 "SymTagDimension",
159 "SymTagMax"
160 };
161
162 void
163 IndentPrint(INT ind)
164 {
165 INT i;
166 for (i = 0; i < ind; i++)
167 {
168 printf(" ");
169 }
170 }
171
172 #define printfi \
173 IndentPrint(indent); printf
174
175 VOID
176 PrintUsage()
177 {
178 printf("Syntax:\n\n");
179 printf("dumpsym <file> [-sp=<symbolpath>] [-p] [<symname>]\n\n");
180 printf("<file> The PE file you want to dump the symbols of\n");
181 printf("-sp=<symbolpath> Path to your symbol files.\n");
182 printf(" Default is MS symbol server.\n");
183 printf("-p Enable struct positions.\n");
184 printf("<symname> A name of a Symbol, you want to dump\n");
185 printf(" Default is all symbols.\n");
186 printf("\n");
187 }
188
189 BOOL InitDbgHelp(HANDLE hProcess, LPSTR pszSymbolPath)
190 {
191 if (!SymInitialize(hProcess, 0, FALSE))
192 return FALSE;
193
194 SymSetOptions(SymGetOptions() | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
195 SymSetOptions(SymGetOptions() & (~SYMOPT_DEFERRED_LOADS));
196 SymSetSearchPath(hProcess, pszSymbolPath);
197 return TRUE;
198 }
199
200 VOID
201 DumpBaseType(DWORD dwTypeIndex, PENUMINFO pei, INT indent)
202 {
203 ULONG64 ulSize;
204 DWORD dwBaseType;
205
206 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_LENGTH, &ulSize);
207 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_BASETYPE, &dwBaseType);
208
209 switch (dwBaseType)
210 {
211 case btVoid:
212 printfi("VOID");
213 return;
214 case btChar:
215 printfi("CHAR");
216 return;
217 case btWChar:
218 printfi("WCHAR");
219 return;
220 case btInt:
221 switch (ulSize)
222 {
223 case 1:
224 printfi("CHAR");
225 return;
226 case 2:
227 printfi("SHORT");
228 return;
229 case 4:
230 printfi("INT");
231 return;
232 case 8:
233 printfi("INT64");
234 return;
235 default:
236 printfi("INT%ld", (ULONG)ulSize * 8);
237 return;
238 }
239 case btUInt:
240 switch (ulSize)
241 {
242 case 1:
243 printfi("UCHAR");
244 return;
245 case 2:
246 printfi("USHORT");
247 return;
248 case 4:
249 printfi("UINT");
250 return;
251 case 8:
252 printfi("UINT64");
253 return;
254 default:
255 printfi("UINT%ld", (ULONG)ulSize * 8);
256 return;
257 }
258 case btFloat:
259 switch (ulSize)
260 {
261 case 4:
262 printfi("FLOAT");
263 return;
264 case 8:
265 printfi("DOUBLE");
266 return;
267 default:
268 printfi("FLOAT%ld", (ULONG)ulSize * 8);
269 return;
270 }
271 case btBCD:
272 printfi("BCD%ld", (ULONG)ulSize * 8);
273 return;
274 case btBool:
275 switch (ulSize)
276 {
277 case 1:
278 printfi("BOOLEAN");
279 return;
280 case 4:
281 printfi("BOOL");
282 return;
283 default:
284 printfi("BOOL%ld", (ULONG)ulSize * 8);
285 return;
286 }
287 case btLong:
288 switch (ulSize)
289 {
290 case 1:
291 printfi("CHAR");
292 return;
293 case 2:
294 printfi("SHORT");
295 return;
296 case 4:
297 printfi("LONG");
298 return;
299 case 8:
300 printfi("LONGLONG");
301 return;
302 default:
303 printfi("LONG%ld", (ULONG)ulSize * 8);
304 return;
305 }
306 case btULong:
307 switch (ulSize)
308 {
309 case 1:
310 printfi("UCHAR");
311 return;
312 case 2:
313 printfi("USHORT");
314 return;
315 case 4:
316 printfi("ULONG");
317 return;
318 case 8:
319 printfi("ULONGLONG");
320 return;
321 default:
322 printfi("ULONG%ld", (ULONG)ulSize * 8);
323 return;
324 }
325 case btCurrency:
326 case btDate:
327 case btVariant:
328 case btComplex:
329 case btBit:
330 case btBSTR:
331 printfi("UNSUP_%ld_%ld", dwBaseType, (ULONG)ulSize);
332 return;
333 case btHresult:
334 if (ulSize == 4)
335 {
336 printfi("HRESULT");
337 return;
338 }
339 printfi("HRESULT%ld", (ULONG)ulSize);
340 return;
341 }
342
343 printfi("UNKNBASETYPE");
344 }
345
346 VOID
347 DumpArray(DWORD dwTypeIndex, PENUMINFO pei, INT indent)
348 {
349 DWORD dwTypeId;
350
351 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_TYPE, &dwTypeId);
352 DumpType(dwTypeId, pei, indent, FALSE);
353 }
354
355 VOID
356 DumpPointer(DWORD dwTypeIndex, PENUMINFO pei, INT indent)
357 {
358 DWORD dwRefTypeId;
359 DWORD dwTag = 0;
360 ULONG64 ulSize;
361 DWORD dwBaseType;
362
363 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_TYPE, &dwRefTypeId);
364 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_BASETYPE, &dwBaseType);
365 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_LENGTH, &ulSize);
366 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_SYMTAG, &dwTag);
367
368 if (dwTag == SymTagFunctionType)
369 {
370 printfi("PPROC");
371 return;
372 }
373
374 switch (dwBaseType)
375 {
376 case btVoid:
377 switch (ulSize)
378 {
379 case 0:
380 printfi("PVOID");
381 return;
382 }
383 break;
384
385 case btChar:
386 switch (ulSize)
387 {
388 case 1:
389 printfi("PCHAR");
390 return;
391 }
392 break;
393 case btWChar:
394 switch (ulSize)
395 {
396 case 2:
397 printfi("PWCHAR");
398 return;
399 }
400 break;
401 case btInt:
402 switch (ulSize)
403 {
404 case 4:
405 printfi("PINT");
406 return;
407 }
408 break;
409 case btUInt:
410 switch (ulSize)
411 {
412 case 4:
413 printfi("PUINT");
414 return;
415 }
416 break;
417 case btFloat:
418 switch (ulSize)
419 {
420 case 4:
421 printfi("PFLOAT");
422 return;
423 case 8:
424 printfi("PDOUBLE");
425 return;
426 }
427 break;
428 case btBCD:
429 break;
430 case btBool:
431 switch (ulSize)
432 {
433 case 1:
434 printfi("PBOOLEAN");
435 return;
436 case 4:
437 printfi("PBOOL");
438 return;
439 }
440 break;
441 case btLong:
442 switch (ulSize)
443 {
444 case 4:
445 printfi("PLONG");
446 return;
447 case 8:
448 printfi("PLONGLONG");
449 return;
450 }
451 break;
452 case btULong:
453 switch (ulSize)
454 {
455 case 4:
456 printfi("PULONG");
457 return;
458 case 8:
459 printfi("PULONGLONG");
460 return;
461 }
462 break;
463 case btCurrency:
464 case btDate:
465 case btVariant:
466 case btComplex:
467 case btBit:
468 case btBSTR:
469 case btHresult:
470 break;
471 }
472
473 DumpType(dwRefTypeId, pei, indent, FALSE);
474 printf("*");
475 }
476
477 VOID
478 PrintVariant(VARIANT *v)
479 {
480 // printf("<vt%d>", v->n1.n2.vt);
481 switch (v->n1.n2.vt)
482 {
483 case VT_I1:
484 printf("%d", (INT)v->n1.n2.n3.cVal);
485 break;
486 case VT_UI1:
487 printf("0x%x", (UINT)v->n1.n2.n3.cVal);
488 break;
489 case VT_I2:
490 printf("%d", (UINT)v->n1.n2.n3.iVal);
491 break;
492 case VT_UI2:
493 printf("0x%x", (UINT)v->n1.n2.n3.iVal);
494 break;
495 case VT_INT:
496 case VT_I4:
497 printf("%d", (UINT)v->n1.n2.n3.lVal);
498 break;
499 case VT_UINT:
500 case VT_UI4:
501 printf("0x%x", (UINT)v->n1.n2.n3.lVal);
502 break;
503 }
504 }
505
506 BOOL
507 IsUnnamed(WCHAR *pszName)
508 {
509 if ((StrStrW(pszName, L"__unnamed") != NULL) ||
510 (StrStrW(pszName, L"<unnamed-tag>") != NULL))
511 {
512 return TRUE;
513 }
514 return FALSE;
515 }
516
517 VOID
518 DumpEnum(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
519 {
520 DWORD64 dwModuleBase = pei->dwModuleBase;
521 HANDLE hProcess = pei->hProcess;
522 INT i;
523 DWORD dwUDTKind;
524 WCHAR *pszName, *pszNameX;
525 struct
526 {
527 TI_FINDCHILDREN_PARAMS tfp;
528 ULONG TypeIds[200];
529 } tfpex;
530 VARIANT v;
531
532 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMNAME, &pszNameX);
533 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_UDTKIND, &dwUDTKind);
534 pszName = pszNameX;
535 if (IsUnnamed(pszName))
536 {
537 if (bMembers)
538 {
539 LocalFree(pszNameX);
540 return;
541 }
542 bMembers = TRUE;
543 pszName = L"";
544 }
545 printfi("enum %ls", pszName);
546 LocalFree(pszNameX);
547
548 if (bMembers)
549 {
550 printf(" /* %03x */", 0);
551 printfi("\n{\n");
552
553 /* Get the children */
554 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &tfpex.tfp.Count);
555
556 tfpex.tfp.Start = 0;
557 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_FINDCHILDREN, &tfpex.tfp);
558
559 for (i = 0; i < tfpex.tfp.Count; i++)
560 {
561 pszName = L"";
562
563 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_SYMNAME, &pszName);
564 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_VALUE, &v);
565
566 indent++;
567 printfi("%ls = ", pszName);
568 PrintVariant(&v);
569 printf(",\n");
570 indent--;
571
572 LocalFree(pszName);
573 }
574 printfi("}");
575 }
576 }
577
578 VOID
579 DumpUDT(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
580 {
581 DWORD64 dwModuleBase = pei->dwModuleBase;
582 HANDLE hProcess = pei->hProcess;
583 INT i;
584 DWORD dwUDTKind;
585 WCHAR *pszName, *pszNameX;
586 struct
587 {
588 TI_FINDCHILDREN_PARAMS tfp;
589 ULONG TypeIds[200];
590 } tfpex;
591
592 DWORD dwDataKind;
593 DWORD dwTypeId;
594 DWORD dwCount;
595 WCHAR *pszTypeName;
596
597 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMNAME, &pszNameX);
598 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_UDTKIND, &dwUDTKind);
599
600 pszName = pszNameX;
601 if (IsUnnamed(pszName))
602 {
603 if (bMembers)
604 {
605 LocalFree(pszNameX);
606 return;
607 }
608 bMembers = TRUE;
609 pszName = L"";
610 }
611 if (dwUDTKind == UDTKind_Struct)
612 {
613 printfi("struct %ls", pszName);
614 }
615 else if (dwUDTKind == UDTKind_Union)
616 {
617 printfi("union %ls", pszName);
618 }
619 else
620 {
621 printfi("UTDKind%ld %ls", dwUDTKind, pszName);
622 }
623 LocalFree(pszNameX);
624
625 if (bMembers)
626 {
627 ULONG64 ulLength;
628
629 printf("\n");
630 printfi("{\n");
631
632 /* Get the children */
633 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &tfpex.tfp.Count);
634
635 tfpex.tfp.Start = 0;
636 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_FINDCHILDREN, &tfpex.tfp);
637
638 for (i = 0; i < tfpex.tfp.Count; i++)
639 {
640 DWORD dwChildTag;
641 DWORD dwOffset;
642
643 pszName = L"";
644 pszTypeName = L"";
645
646 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_SYMNAME, &pszName);
647 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_DATAKIND, &dwDataKind);
648 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_TYPE, &dwTypeId);
649 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_OFFSET, &dwOffset);
650 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_SYMTAG, &dwChildTag);
651 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_LENGTH, &ulLength);
652
653 printf(" /* %03lx */", dwOffset);
654 DumpType(dwTypeId, pei, indent + 1, FALSE);
655 printf(" %ls", pszName);
656 if (dwChildTag == SymTagArrayType)
657 {
658 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_COUNT, &dwCount);
659 printf("[%ld]", dwCount);
660 }
661 else
662 {
663 DWORD dwCurrentBitPos;
664 DWORD dwNextBitPos;
665
666 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_BITPOSITION, &dwCurrentBitPos);
667 if (i < tfpex.tfp.Count - 1)
668 {
669 SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i+1], TI_GET_BITPOSITION, &dwNextBitPos);
670 }
671 else
672 {
673 dwNextBitPos = 0;
674 }
675
676 if (dwNextBitPos == 0 && dwCurrentBitPos != 0)
677 {
678 dwNextBitPos = ulLength * 8;
679 }
680
681 if (dwNextBitPos != dwCurrentBitPos)
682 {
683 printf(":%ld", dwNextBitPos - dwCurrentBitPos);
684 }
685 }
686 printf(";\n");
687 LocalFree(pszName);
688 }
689 printfi("}");
690 }
691 }
692
693 VOID
694 DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
695 {
696 HANDLE hProcess = pei->hProcess;
697 DWORD64 dwModuleBase = pei->dwModuleBase;
698 DWORD dwTag = 0;
699
700 SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMTAG, &dwTag);
701
702 switch (dwTag)
703 {
704 case SymTagEnum:
705 DumpEnum(dwTypeIndex, pei, indent, bMembers);
706 break;
707
708 case SymTagUDT:
709 DumpUDT(dwTypeIndex, pei, indent, bMembers);
710 break;
711
712 case SymTagPointerType:
713 DumpPointer(dwTypeIndex, pei, indent);
714 break;
715
716 case SymTagBaseType:
717 DumpBaseType(dwTypeIndex, pei, indent);
718 break;
719
720 case SymTagArrayType:
721 DumpArray(dwTypeIndex, pei, indent);
722 break;
723
724 case SymTagFunctionType:
725 printfi("function");
726 break;
727
728 default:
729 printfi("typeTag%ld", dwTag);
730 break;
731 }
732
733 }
734
735
736 VOID
737 DumpCV(DWORD dwTypeIndex, PENUMINFO pei)
738 {
739 DWORD cv = 0x20;
740
741 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_CALLING_CONVENTION, &cv);
742 switch (cv)
743 {
744 case CV_CALL_NEAR_C:
745 printf("CDECL");
746 return;
747 case CV_CALL_FAR_C:
748 printf("FAR CDECL");
749 return;
750 case CV_CALL_NEAR_PASCAL:
751 printf("PASCAL");
752 return;
753 case CV_CALL_FAR_PASCAL:
754 printf("FAR PASCAL");
755 return;
756 case CV_CALL_NEAR_FAST:
757 printf("FASTCALL");
758 return;
759 case CV_CALL_FAR_FAST:
760 printf("FAR FASTCALL");
761 return;
762 case CV_CALL_SKIPPED:
763 printf("SKIPPED");
764 return;
765 case CV_CALL_NEAR_STD:
766 printf("STDCALL");
767 return;
768 case CV_CALL_FAR_STD:
769 printf("FAR STDCALL");
770 return;
771 case CV_CALL_NEAR_SYS:
772 case CV_CALL_FAR_SYS:
773 case CV_CALL_THISCALL:
774 printf("THISCALL");
775 return;
776 case CV_CALL_MIPSCALL:
777 printf("MIPSCALL");
778 return;
779 case CV_CALL_GENERIC:
780 case CV_CALL_ALPHACALL:
781 case CV_CALL_PPCCALL:
782 case CV_CALL_SHCALL:
783 case CV_CALL_ARMCALL:
784 case CV_CALL_AM33CALL:
785 case CV_CALL_TRICALL:
786 case CV_CALL_SH5CALL:
787 case CV_CALL_M32RCALL:
788 default:
789 printf("UNKNOWNCV");
790 }
791
792 }
793
794 BOOL CALLBACK
795 EnumParamsProc(
796 PSYMBOL_INFO pSymInfo,
797 ULONG SymbolSize,
798 PVOID UserContext)
799 {
800 printf("x, ");
801 (*(INT*)UserContext)++;
802 return TRUE;
803 }
804
805 VOID
806 DumpParams(PSYMBOL_INFO pSymInfo, PENUMINFO pei)
807 {
808 IMAGEHLP_STACK_FRAME sf;
809 BOOL bRet;
810
811 sf.InstructionOffset = pSymInfo->Address;
812
813 printf("(");
814 bRet = SymSetContext(pei->hProcess, &sf, 0);
815
816 if (!bRet)
817 {
818 printf("\nError: SymSetContext() failed. Error code: %lu \n", GetLastError());
819 return;
820 }
821 printf("Address == 0x%x, ReturnOffset = 0x%x", (UINT)pSymInfo->Address, (UINT)sf.ReturnOffset);
822
823 // Enumerate local variables
824
825 INT NumLocals = 0; // the number of local variables found
826
827 bRet = SymEnumSymbols(pei->hProcess, 0, 0, EnumParamsProc, &NumLocals);
828
829 if (!bRet)
830 {
831 // printf("Error: SymEnumSymbols() failed. Error code: %lu \n", GetLastError());
832 printf("?)");
833 return;
834 }
835
836 if (NumLocals == 0)
837 {
838 // printf("The function does not have parameters and local variables.\n");
839 printf("void)");
840 }
841
842 printf(")");
843 }
844
845 VOID
846 DumpFunction(PSYMBOL_INFO pSymInfo, PENUMINFO pei)
847 {
848 DWORD dwTypeId;
849
850 //printf("Name=%s, Size=%ld, TypeId=0x%ld\n", pSymInfo->Name, pSymInfo->Size, pSymInfo->TypeIndex);
851
852 SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, pSymInfo->TypeIndex, TI_GET_TYPEID, &dwTypeId);
853
854 // DumpCV(pSymInfo->TypeIndex, pei);
855 // printf("\n");
856 // DumpType(pSymInfo->TypeIndex, pei, 0, FALSE);
857 printf("%s", pSymInfo->Name);
858 DumpParams(pSymInfo, pei);
859 }
860
861 BOOL CALLBACK
862 EnumSymbolsProc(
863 PSYMBOL_INFO pSymInfo,
864 ULONG SymbolSize,
865 PVOID UserContext)
866 {
867 PENUMINFO pei = (PENUMINFO)UserContext;
868
869 if ((pei->pszSymbolName == NULL) ||
870 (strstr(pSymInfo->Name, pei->pszSymbolName) != 0))
871 {
872 if (pei->bType)
873 {
874 DumpType(pSymInfo->TypeIndex, pei, 0, TRUE);
875 printf("\n\n");
876 }
877 else
878 {
879 printf("Symbol: %s, TypeIndex=%ld, Flags=%lx, Value=0x%llx\n",
880 pSymInfo->Name, pSymInfo->TypeIndex, pSymInfo->Flags, pSymInfo->Value);
881 //if (pSymInfo->Flags & SYMFLAG_FUNCTION)
882 {
883 // DumpFunction(pSymInfo, pei);
884 // printf("\n\n");
885 }
886 }
887 }
888 return TRUE;
889 }
890
891 int main(int argc, char* argv[])
892 {
893 HANDLE hProcess;
894 CHAR szFullFileName[MAX_PATH+1];
895 DWORD64 dwModuleBase;
896 BOOL bRet;
897 LPSTR pszSymbolPath, pszSymbolName;
898 INT i;
899 ENUMINFO enuminfo;
900
901 printf("PE symbol dumper\n");
902 printf("Copyright (c) Timo Kreuzer 2008\n\n");
903
904 if (argc < 2)
905 {
906 PrintUsage();
907 return 0;
908 }
909
910 /* Get the full path name of the PE file from first argument */
911 GetFullPathName(argv[1], MAX_PATH, szFullFileName, NULL);
912
913 /* Default Symbol Name (all) */
914 pszSymbolName = NULL;
915
916 /* Default to ms symbol server */
917 pszSymbolPath = "srv**symbols*http://msdl.microsoft.com/download/symbols";
918
919 /* Check other command line arguments */
920 for (i = 2; i < argc; i++)
921 {
922 if (*argv[i] == '-')
923 {
924 if (strncmp(argv[i], "-sp=", 4) == 0)
925 {
926 pszSymbolPath = argv[i] + 4;
927 }
928 else if (strcmp(argv[i], "-p") == 0)
929 {
930 g_bShowPos = 1;
931 }
932 else
933 {
934 printf("Invalid argument: %s\n", argv[i]);
935 PrintUsage();
936 return 0;
937 }
938 }
939 else
940 {
941 pszSymbolName = argv[i];
942 }
943 }
944
945 hProcess = GetCurrentProcess();
946
947 printf("Trying to get symbols from: %s\n", pszSymbolPath);
948
949 if (!InitDbgHelp(hProcess, pszSymbolPath))
950 {
951 printf("SymInitialize() failed\n");
952 goto cleanup;
953 }
954
955 printf("Loading symbols for %s, please wait...\n", szFullFileName);
956 dwModuleBase = SymLoadModule64(hProcess, 0, szFullFileName, 0, 0, 0);
957 if (dwModuleBase == 0)
958 {
959 printf("SymLoadModule64() failed: %ld\n", GetLastError());
960 goto cleanup;
961 }
962
963 printf("\nSymbols:\n");
964 enuminfo.hProcess = hProcess;
965 enuminfo.pszSymbolName = pszSymbolName;
966 enuminfo.bType = FALSE;
967 SetLastError(ERROR_SUCCESS);
968 bRet = SymEnumSymbols(hProcess, dwModuleBase, NULL, EnumSymbolsProc, &enuminfo);
969 if (!bRet)
970 {
971 printf("SymEnumSymbols failed: %ld\n", GetLastError());
972 }
973
974 printf("\nTypes:\n");
975 enuminfo.bType = TRUE;
976 enuminfo.dwModuleBase = dwModuleBase;
977 SetLastError(ERROR_SUCCESS);
978 bRet = SymEnumTypes(hProcess, dwModuleBase, EnumSymbolsProc, &enuminfo);
979 if (!bRet)
980 {
981 printf("SymEnumTypes failed: %ld\n", GetLastError());
982 }
983
984 cleanup:
985
986 return 0;
987 }