1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include "ildasmpch.h"
6#include <crtdbg.h>
7#include <utilcode.h>
8#include "specstrings.h"
9#include "debugmacros.h"
10#include "corpriv.h"
11#include "ceeload.h"
12#include "dynamicarray.h"
13#include <metamodelpub.h>
14#include "formattype.h"
15
16#define DECLARE_DATA
17#include "dasmenum.hpp"
18#include "dis.h"
19
20#include "resource.h"
21#include "dasm_sz.h"
22
23//#define MAX_FILENAME_LENGTH 2048 //moved to dis.h
24
25#include <corsym.h>
26#include <ndpversion.h>
27
28// Disable the "initialization of static local vars is no thread safe" error
29#ifdef _MSC_VER
30#pragma warning(disable : 4640)
31#endif
32
33#if defined(_DEBUG) && defined(FEATURE_PREJIT)
34#include <corcompile.h>
35#endif
36
37#ifdef FEATURE_PAL
38#include "coreclrloader.h"
39#include "resourcestring.h"
40#define NATIVE_STRING_RESOURCE_NAME dasm_rc
41DECLARE_NATIVE_STRING_RESOURCE_TABLE(NATIVE_STRING_RESOURCE_NAME);
42#endif
43
44struct MIDescriptor
45{
46 mdToken tkClass; // defining class token
47 mdToken tkDecl; // implemented method token
48 mdToken tkBody; // implementing method token
49 mdToken tkBodyParent; // parent of the implementing method
50};
51
52ISymUnmanagedReader* g_pSymReader = NULL;
53
54IMDInternalImport* g_pImport = NULL;
55IMetaDataImport2* g_pPubImport;
56extern IMetaDataAssemblyImport* g_pAssemblyImport;
57PELoader * g_pPELoader;
58void * g_pMetaData;
59unsigned g_cbMetaData;
60IMAGE_COR20_HEADER * g_CORHeader;
61DynamicArray<__int32> *g_pPtrTags = NULL; //to keep track of all "ldptr"
62DynamicArray<DWORD> *g_pPtrSize= NULL; //to keep track of all "ldptr"
63int g_iPtrCount = 0;
64mdToken * g_cl_list = NULL;
65mdToken * g_cl_enclosing = NULL;
66BYTE* g_enum_td_type = NULL; // enum (TD) underlying types
67BYTE* g_enum_tr_type = NULL; // enum (TR) underlying types
68IMDInternalImport** g_asmref_import = NULL; // IMDInternalImports for external assemblies
69DynamicArray<MIDescriptor> *g_pmi_list = NULL;
70DWORD g_NumMI;
71DWORD g_NumClasses;
72DWORD g_NumTypeRefs;
73DWORD g_NumAsmRefs;
74DWORD g_NumModules;
75BOOL g_fDumpIL = TRUE;
76BOOL g_fDumpHeader = FALSE;
77BOOL g_fDumpAsmCode = TRUE;
78extern BOOL g_fDumpTokens; // declared in formatType.cpp
79BOOL g_fDumpStats = FALSE;
80BOOL g_fTDC = TRUE;
81BOOL g_fShowCA = TRUE;
82BOOL g_fCAVerbal = FALSE;
83BOOL g_fShowRefs = FALSE;
84
85BOOL g_fDumpToPerfWriter = FALSE;
86HANDLE g_PerfDataFilePtr = NULL;
87
88BOOL g_fDumpClassList = FALSE;
89BOOL g_fDumpTypeList = FALSE;
90BOOL g_fDumpSummary = FALSE;
91BOOL g_fDecompile = FALSE; // still in progress
92BOOL g_fShowBytes = FALSE;
93BOOL g_fShowSource = FALSE;
94BOOL g_fPrettyPrint = FALSE;
95BOOL g_fInsertSourceLines = FALSE;
96BOOL g_fThisIsInstanceMethod;
97BOOL g_fTryInCode = TRUE;
98
99BOOL g_fLimitedVisibility = FALSE;
100#if defined(_DEBUG) && defined(FEATURE_PREJIT)
101BOOL g_fNGenNativeMetadata = FALSE;
102#endif
103BOOL g_fHidePub = TRUE;
104BOOL g_fHidePriv = TRUE;
105BOOL g_fHideFam = TRUE;
106BOOL g_fHideAsm = TRUE;
107BOOL g_fHideFAA = TRUE;
108BOOL g_fHideFOA = TRUE;
109BOOL g_fHidePrivScope = TRUE;
110
111BOOL g_fProject = FALSE; // if .winmd file, transform to .NET view
112
113extern BOOL g_fQuoteAllNames; // declared in formatType.cpp, init to FALSE
114BOOL g_fForwardDecl=FALSE;
115
116char g_szAsmCodeIndent[MAX_MEMBER_LENGTH];
117char g_szNamespace[MAX_MEMBER_LENGTH];
118
119DWORD g_Mode = MODE_DUMP_ALL;
120
121char g_pszClassToDump[MAX_CLASSNAME_LENGTH];
122char g_pszMethodToDump[MAX_MEMBER_LENGTH];
123char g_pszSigToDump[MAX_SIGNATURE_LENGTH];
124
125BOOL g_fCustomInstructionEncodingSystem = FALSE;
126
127COR_FIELD_OFFSET *g_rFieldOffset = NULL;
128ULONG g_cFieldsMax, g_cFieldOffsets;
129
130char* g_pszExeFile;
131char g_szInputFile[MAX_FILENAME_LENGTH]; // in UTF-8
132WCHAR g_wszFullInputFile[MAX_PATH + 1]; // in UTF-16
133char g_szOutputFile[MAX_FILENAME_LENGTH]; // in UTF-8
134char* g_pszObjFileName;
135FILE* g_pFile = NULL;
136
137mdToken g_tkClassToDump = 0;
138mdToken g_tkMethodToDump = 0;
139
140unsigned g_uConsoleCP = CP_ACP;
141unsigned g_uCodePage = g_uConsoleCP;
142
143char* g_rchCA = NULL; // dyn.allocated array of CA dumped/not flags
144unsigned g_uNCA = 0; // num. of CAs
145
146struct ResourceNode;
147extern DynamicArray<LocalComTypeDescr*> *g_pLocalComType;
148extern ULONG g_LocalComTypeNum;
149
150// MetaInfo integration:
151#include "../tools/metainfo/mdinfo.h"
152
153BOOL g_fDumpMetaInfo = FALSE;
154ULONG g_ulMetaInfoFilter = MDInfo::dumpDefault;
155// Validator module type.
156DWORD g_ValModuleType = ValidatorModuleTypeInvalid;
157IMetaDataDispenserEx *g_pDisp = NULL;
158void DisplayFile(__in __nullterminated wchar_t* szFile,
159 BOOL isFile,
160 ULONG DumpFilter,
161 __in_opt __nullterminated wchar_t* szObjFile,
162 strPassBackFn pDisplayString);
163extern mdMethodDef g_tkEntryPoint; // integration with MetaInfo
164
165DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName); // see DRES.CPP
166
167struct VTableRef
168{
169 mdMethodDef tkTok;
170 WORD wEntry;
171 WORD wSlot;
172};
173
174DynamicArray<VTableRef> *g_prVTableRef = NULL;
175ULONG g_nVTableRef = 0;
176
177struct EATableRef
178{
179 mdMethodDef tkTok;
180 char* pszName;
181};
182DynamicArray<EATableRef> *g_prEATableRef=NULL;
183ULONG g_nEATableRef = 0;
184ULONG g_nEATableBase = 0;
185
186extern HINSTANCE g_hResources;
187void DumpCustomAttributeProps(mdToken tkCA, mdToken tkType, mdToken tkOwner, BYTE*pBlob, ULONG ulLen, void *GUICookie, bool bWithOwner);
188
189WCHAR* RstrW(unsigned id)
190{
191 static WCHAR buffer[1024];
192 DWORD cchBuff = (DWORD)COUNTOF(buffer);
193 WCHAR* buff = (WCHAR*)buffer;
194 memset(buffer,0,sizeof(buffer));
195 switch(id)
196 {
197 case IDS_E_DASMOK:
198 case IDS_E_PARTDASM:
199 case IDS_E_PARAMSEQNO:
200 case IDS_E_MEMBRENUM:
201 case IDS_E_ODDMEMBER:
202 case IDS_E_ENUMINIT:
203 case IDS_E_NODATA:
204 case IDS_E_VTFUTABLE:
205 case IDS_E_BOGUSRVA:
206 case IDS_E_EATJTABLE:
207 case IDS_E_EATJSIZE:
208 case IDS_E_RESFLAGS:
209 case IDS_E_MIHENTRY:
210 case IDS_E_CODEMGRTBL:
211 case IDS_E_COMIMAGE:
212 case IDS_E_MDDETAILS:
213 case IDS_E_MISTART:
214 case IDS_E_MIEND:
215 case IDS_E_ONLYITEMS:
216 case IDS_E_DECOMPRESS:
217 case IDS_E_COMPRESSED:
218 case IDS_E_INSTRDECOD:
219 case IDS_E_INSTRTYPE:
220 case IDS_E_SECTHEADER:
221 case IDS_E_MDAIMPORT:
222 case IDS_E_MDAFROMMDI:
223 case IDS_E_MDIIMPORT:
224 case IDS_E_NOMANIFEST:
225 case IDS_W_CREATEDW32RES:
226 case IDS_E_CORRUPTW32RES:
227 case IDS_E_CANTACCESSW32RES:
228 case IDS_E_CANTOPENW32RES:
229 case IDS_ERRORREOPENINGFILE:
230 wcscpy_s(buffer,COUNTOF(buffer),W("// "));
231 buff +=3;
232 cchBuff -= 3;
233 break;
234 case IDS_E_AUTOCA:
235 case IDS_E_METHBEG:
236 case IDS_E_DASMNATIVE:
237 case IDS_E_METHODRT:
238 case IDS_E_CODESIZE:
239 case IDS_W_CREATEDMRES:
240 case IDS_E_READINGMRES:
241 wcscpy_s(buffer,COUNTOF(buffer),W("%s// "));
242 buff +=5;
243 cchBuff -= 5;
244 break;
245 case IDS_E_NORVA:
246 wcscpy_s(buffer,COUNTOF(buffer),W("/* "));
247 buff += 3;
248 cchBuff -= 3;
249 break;
250 default:
251 break;
252 }
253#ifdef FEATURE_PAL
254 LoadNativeStringResource(NATIVE_STRING_RESOURCE_TABLE(NATIVE_STRING_RESOURCE_NAME),id, buff, cchBuff, NULL);
255#else
256 _ASSERTE(g_hResources != NULL);
257 WszLoadString(g_hResources,id,buff,cchBuff);
258#endif
259 if(id == IDS_E_NORVA)
260 wcscat_s(buff,cchBuff,W(" */"));
261 return buffer;
262}
263
264char* RstrA(unsigned n, unsigned codepage)
265{
266 static char buff[2048];
267 WCHAR* wz = RstrW(n);
268 // Unicode -> UTF-8
269 memset(buff,0,sizeof(buff));
270 if(!WszWideCharToMultiByte(codepage,0,(LPCWSTR)wz,-1,buff,sizeof(buff),NULL,NULL))
271 buff[0] = 0;
272 return buff;
273}
274char* RstrUTF(unsigned n)
275{
276 return RstrA(n,CP_UTF8);
277}
278
279char* RstrANSI(unsigned n)
280{
281 return RstrA(n,g_uConsoleCP);
282}
283
284#if 0
285void PrintEncodingSystem()
286{
287 long i;
288
289 printf("Custom opcode encoding system employed\n");
290 printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
291
292 for (i = 0; i < 256; i++)
293 {
294 long value = g_pInstructionDecodingTable->m_SingleByteOpcodes[i];
295
296 printf("0x%02x --> ", i);
297 printf("%s\n", OpcodeInfo[value].pszName);
298 }
299}
300#endif
301
302// buffers for formatType functions
303extern CQuickBytes * g_szBuf_KEYWORD;
304extern CQuickBytes * g_szBuf_COMMENT;
305extern CQuickBytes * g_szBuf_ERRORMSG;
306extern CQuickBytes * g_szBuf_ANCHORPT;
307extern CQuickBytes * g_szBuf_JUMPPT;
308extern CQuickBytes * g_szBuf_UnquotedProperName;
309extern CQuickBytes * g_szBuf_ProperName;
310
311#ifdef FEATURE_PAL
312CoreCLRLoader *g_loader;
313#endif
314MetaDataGetDispenserFunc metaDataGetDispenser;
315GetMetaDataInternalInterfaceFunc getMetaDataInternalInterface;
316GetMetaDataInternalInterfaceFromPublicFunc getMetaDataInternalInterfaceFromPublic;
317GetMetaDataPublicInterfaceFromInternalFunc getMetaDataPublicInterfaceFromInternal;
318
319BOOL Init()
320{
321#ifdef FEATURE_PAL
322 g_loader = CoreCLRLoader::Create(g_pszExeFile);
323 if (g_loader == NULL)
324 {
325 return FALSE;
326 }
327 metaDataGetDispenser = (MetaDataGetDispenserFunc)g_loader->LoadFunction("MetaDataGetDispenser");
328 getMetaDataInternalInterface = (GetMetaDataInternalInterfaceFunc)g_loader->LoadFunction("GetMetaDataInternalInterface");
329 getMetaDataInternalInterfaceFromPublic = (GetMetaDataInternalInterfaceFromPublicFunc)g_loader->LoadFunction("GetMetaDataInternalInterfaceFromPublic");
330 getMetaDataPublicInterfaceFromInternal = (GetMetaDataPublicInterfaceFromInternalFunc)g_loader->LoadFunction("GetMetaDataPublicInterfaceFromInternal");
331#else // FEATURE_PAL
332 metaDataGetDispenser = (MetaDataGetDispenserFunc)MetaDataGetDispenser;
333 getMetaDataInternalInterface = (GetMetaDataInternalInterfaceFunc)GetMetaDataInternalInterface;
334 getMetaDataInternalInterfaceFromPublic = (GetMetaDataInternalInterfaceFromPublicFunc)GetMetaDataInternalInterfaceFromPublic;
335 getMetaDataPublicInterfaceFromInternal = (GetMetaDataPublicInterfaceFromInternalFunc)GetMetaDataPublicInterfaceFromInternal;
336#endif // FEATURE_PAL
337
338 g_szBuf_KEYWORD = new CQuickBytes();
339 g_szBuf_COMMENT = new CQuickBytes();
340 g_szBuf_ERRORMSG = new CQuickBytes();
341 g_szBuf_ANCHORPT = new CQuickBytes();
342 g_szBuf_JUMPPT = new CQuickBytes();
343 g_szBuf_UnquotedProperName = new CQuickBytes();
344 g_szBuf_ProperName = new CQuickBytes();
345 return TRUE;
346} // Init
347
348extern LPCSTR *rAsmRefName; // decl. in formatType.cpp -- for AsmRef aliases
349extern ULONG ulNumAsmRefs; // decl. in formatType.cpp -- for AsmRef aliases
350
351void Cleanup()
352{
353 if (g_pAssemblyImport != NULL)
354 {
355 g_pAssemblyImport->Release();
356 g_pAssemblyImport = NULL;
357 }
358 if (g_pPubImport != NULL)
359 {
360 g_pPubImport->Release();
361 g_pPubImport = NULL;
362 }
363 if (g_pImport != NULL)
364 {
365 g_pImport->Release();
366 g_pImport = NULL;
367 TokenSigDelete();
368 }
369 if (g_pDisp != NULL)
370 {
371 g_pDisp->Release();
372 g_pDisp = NULL;
373 }
374
375 if (g_pSymReader != NULL)
376 {
377 g_pSymReader->Release();
378 g_pSymReader = NULL;
379 }
380 if (g_pPELoader != NULL)
381 {
382 g_pPELoader->close();
383 SDELETE(g_pPELoader);
384 }
385 g_iPtrCount = 0;
386 g_NumClasses = 0;
387 g_NumTypeRefs = 0;
388 g_NumModules = 0;
389 g_tkEntryPoint = 0;
390 g_szAsmCodeIndent[0] = 0;
391 g_szNamespace[0]=0;
392 g_pszClassToDump[0]=0;
393 g_pszMethodToDump[0]=0;
394 g_pszSigToDump[0] = 0;
395 g_NumDups = 0;
396 g_NumRefs = 0;
397 g_NumMI = 0;
398 g_LocalComTypeNum = 0;
399 g_nEATableRef = 0;
400
401 g_fCustomInstructionEncodingSystem = FALSE;
402
403 if (rAsmRefName != NULL)
404 {
405 for (int i = 0; (unsigned)i < ulNumAsmRefs; i++)
406 {
407 if (rAsmRefName[i] != NULL) VDELETE(rAsmRefName[i]);
408 }
409 VDELETE(rAsmRefName);
410 ulNumAsmRefs = 0;
411 }
412
413 if (g_rchCA != NULL)
414 VDELETE(g_rchCA);
415
416 if (g_cl_list != NULL) VDELETE(g_cl_list);
417 if (g_cl_enclosing != NULL) VDELETE(g_cl_enclosing);
418 if (g_pmi_list != NULL) SDELETE(g_pmi_list);
419 if (g_dups != NULL) SDELETE(g_dups);
420 if (g_enum_td_type != NULL) VDELETE(g_enum_td_type);
421 if (g_enum_tr_type != NULL) VDELETE(g_enum_tr_type);
422 if (g_asmref_import != NULL)
423 {
424 for (DWORD i = 0; i < g_NumAsmRefs; i++)
425 {
426 if (g_asmref_import[i] != NULL)
427 g_asmref_import[i]->Release();
428 }
429 VDELETE(g_asmref_import);
430 g_NumAsmRefs = 0;
431 }
432} // Cleanup
433
434void Uninit()
435{
436 if (g_pPtrTags != NULL)
437 {
438 SDELETE(g_pPtrTags);
439 }
440 if (g_pPtrSize != NULL)
441 {
442 SDELETE(g_pPtrSize);
443 }
444 if (g_pmi_list != NULL)
445 {
446 SDELETE(g_pmi_list);
447 }
448 if (g_dups != NULL) SDELETE(g_dups);
449 if (g_refs != NULL) SDELETE(g_refs);
450 if (g_pLocalComType != NULL)
451 {
452 SDELETE(g_pLocalComType);
453 }
454 if (g_prVTableRef != NULL)
455 {
456 SDELETE(g_prVTableRef);
457 }
458 if (g_prEATableRef != NULL)
459 {
460 SDELETE(g_prEATableRef);
461 }
462 if (g_szBuf_KEYWORD != NULL)
463 {
464 SDELETE(g_szBuf_KEYWORD);
465 }
466 if (g_szBuf_COMMENT != NULL)
467 {
468 SDELETE(g_szBuf_COMMENT);
469 }
470 if (g_szBuf_ERRORMSG != NULL)
471 {
472 SDELETE(g_szBuf_ERRORMSG);
473 }
474 if (g_szBuf_ANCHORPT != NULL)
475 {
476 SDELETE(g_szBuf_ANCHORPT);
477 }
478 if (g_szBuf_JUMPPT != NULL)
479 {
480 SDELETE(g_szBuf_JUMPPT);
481 }
482 if (g_szBuf_UnquotedProperName != NULL)
483 {
484 SDELETE(g_szBuf_UnquotedProperName);
485 }
486 if (g_szBuf_ProperName != NULL)
487 {
488 SDELETE(g_szBuf_ProperName);
489 }
490
491#ifdef FEATURE_PAL
492 if (g_loader != NULL)
493 {
494 g_loader->Finish();
495 }
496#endif
497} // Uninit
498
499HRESULT IsClassRefInScope(mdTypeRef classref)
500{
501 HRESULT hr = S_OK;
502 const char *pszNameSpace;
503 const char *pszClassName;
504 mdTypeDef classdef;
505 mdToken tkRes;
506
507 IfFailRet(g_pImport->GetNameOfTypeRef(classref, &pszNameSpace, &pszClassName));
508 MAKE_NAME_IF_NONE(pszClassName,classref);
509 IfFailRet(g_pImport->GetResolutionScopeOfTypeRef(classref, &tkRes));
510
511 hr = g_pImport->FindTypeDef(pszNameSpace, pszClassName,
512 (TypeFromToken(tkRes) == mdtTypeRef) ? tkRes : mdTokenNil, &classdef);
513
514 return hr;
515}
516
517#ifdef _PREFAST_
518#pragma warning(push)
519#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
520#endif
521BOOL EnumClasses()
522{
523 HRESULT hr;
524 HENUMInternal hEnum;
525 ULONG i = 0,j;
526 //char szString[1024];
527 HENUMInternal hBody;
528 HENUMInternal hDecl;
529
530 if(g_cl_list) VDELETE(g_cl_list);
531 if(g_cl_enclosing) VDELETE(g_cl_enclosing);
532 if (g_pmi_list) SDELETE(g_pmi_list);
533 if (g_dups) SDELETE(g_dups);
534 if (g_enum_td_type) VDELETE(g_enum_td_type);
535 if (g_enum_tr_type) VDELETE(g_enum_tr_type);
536 if (g_asmref_import)
537 {
538 for (DWORD nIndex = 0; nIndex < g_NumAsmRefs; nIndex++)
539 {
540 if (g_asmref_import[nIndex] != NULL)
541 g_asmref_import[nIndex]->Release();
542 }
543 VDELETE(g_asmref_import);
544 g_NumAsmRefs = 0;
545 }
546 //--------------------------------------------------------------
547 if (FAILED(g_pImport->EnumAllInit(mdtTypeRef,&hEnum)))
548 {
549 printError(g_pFile, "MetaData error: cannot enumerate all TypeRefs");
550 return FALSE;
551 }
552 g_NumTypeRefs = g_pImport->EnumGetCount(&hEnum);
553 g_pImport->EnumClose(&hEnum);
554
555 if(g_NumTypeRefs)
556 {
557 g_enum_tr_type = new BYTE[g_NumTypeRefs+1];
558 if(g_enum_tr_type == NULL) return FALSE;
559 memset(g_enum_tr_type,0xFF,g_NumTypeRefs+1);
560 }
561 //--------------------------------------------------------------
562 if (FAILED(g_pImport->EnumAllInit(mdtAssemblyRef, &hEnum)))
563 {
564 printError(g_pFile, "MetaData error: cannot enumerate all AssemblyRefs");
565 return FALSE;
566 }
567 g_NumAsmRefs = g_pImport->EnumGetCount(&hEnum);
568 g_pImport->EnumClose(&hEnum);
569 if(g_NumAsmRefs)
570 {
571 g_asmref_import = new IMDInternalImport*[g_NumAsmRefs+1];
572 if(g_asmref_import == NULL) return FALSE;
573 memset(g_asmref_import,0,(g_NumAsmRefs+1)*sizeof(IMDInternalImport*));
574 }
575 //--------------------------------------------------------------
576 hr = g_pImport->EnumTypeDefInit(
577 &hEnum);
578 if (FAILED(hr))
579 {
580 printError(g_pFile,RstrUTF(IDS_E_CLSENUM));
581 return FALSE;
582 }
583
584 g_NumClasses = g_pImport->EnumTypeDefGetCount(&hEnum);
585
586 g_tkClassToDump = 0;
587
588 g_NumMI = 0;
589 g_NumDups = 0;
590
591 if(g_NumClasses == 0) return TRUE;
592
593 g_enum_td_type = new BYTE[g_NumClasses+1];
594 if(g_enum_td_type == NULL) return FALSE;
595 memset(g_enum_td_type,0xFF,g_NumClasses+1);
596
597 g_cl_list = new mdToken[g_NumClasses];
598 if(g_cl_list == NULL) return FALSE;
599
600 g_cl_enclosing = new mdToken[g_NumClasses];
601 if(g_cl_enclosing == NULL)
602 {
603 VDELETE(g_cl_list);
604 return FALSE;
605 }
606
607 g_pmi_list = new DynamicArray<MIDescriptor>;
608 if(g_pmi_list == NULL)
609 {
610 VDELETE(g_cl_enclosing);
611 VDELETE(g_cl_list);
612 return FALSE;
613 }
614
615 g_dups = new DynamicArray<mdToken>;
616 if(g_dups == NULL)
617 {
618 SDELETE(g_pmi_list);
619 VDELETE(g_cl_enclosing);
620 VDELETE(g_cl_list);
621 return FALSE;
622 }
623
624 // fill the list of typedef tokens
625 while(g_pImport->EnumTypeDefNext(&hEnum, &g_cl_list[i]))
626 {
627 mdToken tkEnclosing;
628
629 if (g_Mode == MODE_DUMP_CLASS || g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
630 {
631 CQuickBytes out;
632
633 // we want plain class name without token values
634 BOOL fDumpTokens = g_fDumpTokens;
635 g_fDumpTokens = FALSE;
636
637 PAL_CPP_TRY
638 {
639 if (strcmp(PrettyPrintClass(&out, g_cl_list[i], g_pImport), g_pszClassToDump) == 0)
640 {
641 g_tkClassToDump = g_cl_list[i];
642 }
643 }
644 PAL_CPP_CATCH_ALL
645 { }
646 PAL_CPP_ENDTRY;
647
648 g_fDumpTokens = fDumpTokens;
649 }
650 g_cl_enclosing[i] = mdTypeDefNil;
651
652 hr = g_pImport->GetNestedClassProps(g_cl_list[i],&tkEnclosing);
653 if (SUCCEEDED(hr) && RidFromToken(tkEnclosing)) // No need to check token validity here, it's done later
654 g_cl_enclosing[i] = tkEnclosing;
655 if (SUCCEEDED(g_pImport->EnumMethodImplInit(g_cl_list[i],&hBody,&hDecl)))
656 {
657 if ((j = g_pImport->EnumMethodImplGetCount(&hBody,&hDecl)))
658 {
659 mdToken tkBody,tkDecl,tkBodyParent;
660 for (ULONG k = 0; k < j; k++)
661 {
662 if (g_pImport->EnumMethodImplNext(&hBody,&hDecl,&tkBody,&tkDecl) == S_OK)
663 {
664 if (SUCCEEDED(g_pImport->GetParentToken(tkBody,&tkBodyParent)))
665 {
666 (*g_pmi_list)[g_NumMI].tkClass = g_cl_list[i];
667 (*g_pmi_list)[g_NumMI].tkBody = tkBody;
668 (*g_pmi_list)[g_NumMI].tkDecl = tkDecl;
669 (*g_pmi_list)[g_NumMI].tkBodyParent = tkBodyParent;
670 g_NumMI++;
671 }
672 }
673 }
674 }
675 g_pImport->EnumMethodImplClose(&hBody,&hDecl);
676 }
677 i++;
678 }
679 g_pImport->EnumTypeDefClose(&hEnum);
680 // check nesting consistency (circular nesting, invalid enclosers)
681 for(i = 0; i < g_NumClasses; i++)
682 {
683 mdToken tkThis = g_cl_list[i];
684 mdToken tkEncloser = g_cl_enclosing[i];
685 mdToken tkPrevLevel = tkThis;
686 while(tkEncloser != mdTypeDefNil)
687 {
688 if(tkThis == tkEncloser)
689 {
690 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_SELFNSTD),tkThis);
691 printError(g_pFile,szString);
692 g_cl_enclosing[i] = mdTypeDefNil;
693 break;
694 }
695 else
696 {
697 for(j = 0; (j < g_NumClasses)&&(tkEncloser != g_cl_list[j]); j++);
698 if(j == g_NumClasses)
699 {
700 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_NOENCLOS),
701 tkPrevLevel,tkEncloser);
702 printError(g_pFile,szString);
703 g_cl_enclosing[i] = mdTypeDefNil;
704 break;
705 }
706 else
707 {
708 tkPrevLevel = tkEncloser;
709 tkEncloser = g_cl_enclosing[j];
710 }
711 }
712 } // end while(tkEncloser != mdTypeDefNil)
713 } // end for(i = 0; i < g_NumClasses; i++)
714
715 // register all class dups
716 const char *pszClassName;
717 const char *pszNamespace;
718 const char *pszClassName1;
719 const char *pszNamespace1;
720
721 if (FAILED(g_pImport->GetNameOfTypeDef(
722 g_cl_list[0],
723 &pszClassName,
724 &pszNamespace)))
725 {
726 char sz[2048];
727 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), g_cl_list[0]);
728 printLine(g_pFile, sz);
729 return FALSE;
730 }
731 if((g_cl_enclosing[0]==mdTypeDefNil)
732 &&(0==strcmp(pszClassName,"<Module>"))
733 &&(*pszNamespace == 0))
734 {
735 (*g_dups)[g_NumDups++] = g_cl_list[0];
736 }
737 for(i = 1; i < g_NumClasses; i++)
738 {
739 if (FAILED(g_pImport->GetNameOfTypeDef(
740 g_cl_list[i],
741 &pszClassName,
742 &pszNamespace)))
743 {
744 char sz[2048];
745 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), g_cl_list[i]);
746 printLine(g_pFile, sz);
747 return FALSE;
748 }
749
750 for(j = 0; j < i; j++)
751 {
752 if (FAILED(g_pImport->GetNameOfTypeDef(
753 g_cl_list[j],
754 &pszClassName1,
755 &pszNamespace1)))
756 {
757 char sz[2048];
758 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), g_cl_list[j]);
759 printLine(g_pFile, sz);
760 return FALSE;
761 }
762
763 if((g_cl_enclosing[i]==g_cl_enclosing[j])
764 &&(0==strcmp(pszClassName,pszClassName1))
765 &&(0==strcmp(pszNamespace,pszNamespace1)))
766 {
767 (*g_dups)[g_NumDups++] = g_cl_list[i];
768 break;
769 }
770 }
771 } // end for(i = 1; i < g_NumClasses; i++)
772
773 //register all field and method dups
774 for(i = 0; i <= g_NumClasses; i++)
775 {
776 HENUMInternal hEnumMember;
777 mdToken *pMemberList = NULL;
778 DWORD NumMembers,k;
779
780 // methods
781 if (i != 0)
782 {
783 hr = g_pImport->EnumInit(mdtMethodDef, g_cl_list[i-1], &hEnumMember);
784 }
785 else
786 {
787 hr = g_pImport->EnumGlobalFunctionsInit(&hEnumMember);
788 }
789 if (FAILED(hr))
790 {
791 printLine(g_pFile,RstrUTF(IDS_E_MEMBRENUM));
792 return FALSE;
793 }
794 NumMembers = g_pImport->EnumGetCount(&hEnumMember);
795 pMemberList = new mdToken[NumMembers];
796 for (j = 0; g_pImport->EnumNext(&hEnumMember, &pMemberList[j]); j++);
797 _ASSERTE(j == NumMembers);
798 g_pImport->EnumClose(&hEnumMember);
799 for (j = 1; j < NumMembers; j++)
800 {
801 const char *pszName;
802 ULONG cSig;
803 PCCOR_SIGNATURE pSig;
804 if (FAILED(g_pImport->GetNameOfMethodDef(pMemberList[j], &pszName)) ||
805 FAILED(g_pImport->GetSigOfMethodDef(pMemberList[j], &cSig, &pSig)))
806 {
807 char sz[2048];
808 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[j]);
809 printLine(g_pFile, sz);
810 return FALSE;
811 }
812 for (k = 0; k < j; k++)
813 {
814 const char *szName1;
815 if (FAILED(g_pImport->GetNameOfMethodDef(pMemberList[k], &szName1)))
816 {
817 char sz[2048];
818 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
819 printLine(g_pFile, sz);
820 return FALSE;
821 }
822 if (strcmp(pszName, szName1) == 0)
823 {
824 ULONG cSig1;
825 PCCOR_SIGNATURE pSig1;
826 if (FAILED(g_pImport->GetSigOfMethodDef(pMemberList[k], &cSig1, &pSig1)))
827 {
828 char sz[2048];
829 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
830 printLine(g_pFile, sz);
831 return FALSE;
832 }
833 if((cSig == cSig1)&&(0==memcmp(pSig,pSig1,cSig)))
834 {
835 (*g_dups)[g_NumDups++] = pMemberList[j];
836 break;
837 }
838 }
839 }
840 }
841 VDELETE(pMemberList);
842
843 // fields
844 if (i != 0)
845 {
846 hr = g_pImport->EnumInit(mdtFieldDef, g_cl_list[i-1], &hEnumMember);
847 }
848 else
849 {
850 hr = g_pImport->EnumGlobalFieldsInit(&hEnumMember);
851 }
852 if (FAILED(hr))
853 {
854 printLine(g_pFile,RstrUTF(IDS_E_MEMBRENUM));
855 return FALSE;
856 }
857 NumMembers = g_pImport->EnumGetCount(&hEnumMember);
858 pMemberList = new mdToken[NumMembers];
859 for (j = 0; g_pImport->EnumNext(&hEnumMember, &pMemberList[j]); j++);
860 _ASSERTE(j == NumMembers);
861 g_pImport->EnumClose(&hEnumMember);
862 for (j = 1; j < NumMembers; j++)
863 {
864 const char *pszName;
865 ULONG cSig;
866 PCCOR_SIGNATURE pSig;
867 if (FAILED(g_pImport->GetNameOfFieldDef(pMemberList[j], &pszName)) ||
868 FAILED(g_pImport->GetSigOfFieldDef(pMemberList[j], &cSig, &pSig)))
869 {
870 char sz[2048];
871 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[j]);
872 printLine(g_pFile, sz);
873 return FALSE;
874 }
875 for (k = 0; k < j; k++)
876 {
877 const char *szName1;
878 if (FAILED(g_pImport->GetNameOfFieldDef(pMemberList[k], &szName1)))
879 {
880 char sz[2048];
881 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
882 printLine(g_pFile, sz);
883 return FALSE;
884 }
885 if (strcmp(pszName, szName1) == 0)
886 {
887 ULONG cSig1;
888 PCCOR_SIGNATURE pSig1;
889 if (FAILED(g_pImport->GetSigOfFieldDef(pMemberList[k], &cSig1, &pSig1)))
890 {
891 char sz[2048];
892 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), pMemberList[k]);
893 printLine(g_pFile, sz);
894 return FALSE;
895 }
896 if((cSig == cSig1)&&(0==memcmp(pSig,pSig1,cSig)))
897 {
898 (*g_dups)[g_NumDups++] = pMemberList[j];
899 break;
900 }
901 }
902 }
903 }
904 VDELETE(pMemberList);
905
906 } // end for(i = 0; i <= g_NumClasses; i++)
907 return TRUE;
908}
909#ifdef _PREFAST_
910#pragma warning(pop)
911#endif
912
913#ifndef _DEBUG
914bool HasSuppressingAttribute()
915{
916 const void* pData;
917 ULONG cbData;
918
919 return ((S_OK == g_pImport->GetCustomAttributeByName(TokenFromRid(mdtModule,1),
920 (LPCUTF8)"System.Runtime.CompilerServices.SuppressIldasmAttribute",
921 &pData,
922 &cbData))
923 || (S_OK == g_pImport->GetCustomAttributeByName(TokenFromRid(mdtAssembly,1),
924 (LPCUTF8)"System.Runtime.CompilerServices.SuppressIldasmAttribute",
925 &pData,
926 &cbData)));
927}
928#endif
929void DumpMscorlib(void* GUICookie)
930{
931 if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(GUICookie);
932 if(g_pAssemblyImport!=NULL)
933 {
934 mdAssembly tkAsm;
935 if(SUCCEEDED(g_pAssemblyImport->GetAssemblyFromScope(&tkAsm))&&(tkAsm != mdAssemblyNil))
936 {
937 const void* pPublicKey;
938 ULONG cbPublicKey = 0;
939 ULONG ulHashAlgId;
940 WCHAR wzName[1024];
941 ULONG ulNameLen=0;
942 ASSEMBLYMETADATA md;
943 WCHAR wzLocale[1024];
944 DWORD dwFlags;
945 //char szString[4096];
946
947 md.szLocale = wzLocale;
948 md.cbLocale = 1024;
949 md.rProcessor = NULL;
950 md.ulProcessor = 0;
951 md.rOS = NULL;
952 md.ulOS = 0;
953
954 if(SUCCEEDED(g_pAssemblyImport->GetAssemblyProps( // S_OK or error.
955 tkAsm, // [IN] The Assembly for which to get the properties.
956 &pPublicKey, // [OUT] Pointer to the public key.
957 &cbPublicKey,// [OUT] Count of bytes in the public key.
958 &ulHashAlgId,// [OUT] Hash Algorithm.
959 wzName, // [OUT] Buffer to fill with name.
960 1024, // [IN] Size of buffer in wide chars.
961 &ulNameLen, // [OUT] Actual # of wide chars in name.
962 &md, // [OUT] Assembly MetaData.
963 &dwFlags))) // [OUT] Flags.
964 {
965 if(wcscmp(wzName,W("mscorlib")) == 0)
966 {
967 printLine(GUICookie,"");
968 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".mscorlib"));
969 printLine(GUICookie,szString);
970 printLine(GUICookie,"");
971 }
972 }
973 }
974 }
975}
976void DumpTypelist(void* GUICookie)
977{
978 if(g_NumClasses > 1)
979 {
980 DWORD i;
981 CQuickBytes out;
982 printLine(GUICookie,"");
983 sprintf_s(szString,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".typelist"));
984 printLine(GUICookie,szString);
985 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
986 printLine(GUICookie,szString);
987 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
988
989 for(i = 0; i < g_NumClasses; i++)
990 {
991 out.Shrink(0);
992 sprintf_s(szString,SZSTRING_SIZE, "%s%s",g_szAsmCodeIndent, PrettyPrintClass(&out, g_cl_list[i], g_pImport));
993 printLine(GUICookie,szString);
994 }
995 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
996 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
997 printLine(GUICookie,szString);
998 printLine(GUICookie,"");
999 }
1000
1001}
1002#define ELEMENT_TYPE_TYPEDEF ELEMENT_TYPE_MAX+1
1003BOOL EnumTypedefs()
1004{
1005 HENUMInternal hEnum;
1006 ULONG i,l;
1007 mdToken tk;
1008 if (g_typedefs) SDELETE(g_typedefs);
1009 g_typedefs = new DynamicArray<TypeDefDescr>;
1010 g_NumTypedefs = 0;
1011 if (FAILED(g_pImport->EnumAllInit(mdtTypeSpec, &hEnum)))
1012 {
1013 return FALSE;
1014 }
1015 for (i = 0; g_pImport->EnumNext(&hEnum, &tk); i++)
1016 {
1017 ULONG cSig;
1018 PCCOR_SIGNATURE sig;
1019 if (FAILED(g_pImport->GetSigFromToken(tk, &cSig, &sig)))
1020 {
1021 return FALSE;
1022 }
1023 if (*sig == ELEMENT_TYPE_TYPEDEF)
1024 {
1025 TypeDefDescr* pTDD = &((*g_typedefs)[g_NumTypedefs]);
1026 pTDD->szName = (char*)sig+1;
1027 l = 2+(ULONG)strlen((char*)sig+1);
1028 pTDD->tkTypeSpec = GET_UNALIGNED_VAL32(sig + l);
1029 pTDD->tkSelf = tk;
1030 if (TypeFromToken(pTDD->tkTypeSpec) == mdtTypeSpec)
1031 {
1032 if (FAILED(g_pImport->GetSigFromToken(pTDD->tkTypeSpec,&(pTDD->cb), &(pTDD->psig))))
1033 {
1034 return FALSE;
1035 }
1036 }
1037 else if (TypeFromToken(pTDD->tkTypeSpec) == mdtCustomAttribute)
1038 {
1039 l += sizeof(mdToken);
1040 pTDD->psig = sig + l;
1041 pTDD->cb = cSig - l;
1042 }
1043 else
1044 {
1045 pTDD->psig = NULL;
1046 pTDD->cb = 0;
1047 }
1048 g_NumTypedefs++;
1049 }
1050 }
1051 g_pImport->EnumClose(&hEnum);
1052 return TRUE;
1053}
1054
1055void DumpTypedefs(void* GUICookie)
1056{
1057 DWORD i;
1058 char* szptr;
1059 CQuickBytes out;
1060 printLine(GUICookie,"");
1061 for(i = 0; i < g_NumTypedefs; i++)
1062 {
1063 TypeDefDescr* pTDD = &((*g_typedefs)[i]);
1064 szptr = &szString[0];
1065 szString[0] = 0;
1066 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,ANCHORPT(KEYWORD(".typedef"),pTDD->tkSelf));
1067 if(g_fDumpTokens)
1068 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),pTDD->tkSelf);
1069
1070 {
1071 ULONG n = g_NumTypedefs;
1072 DWORD tk = pTDD->tkTypeSpec;
1073 switch (TypeFromToken(tk))
1074 {
1075 default:
1076 break;
1077
1078 case mdtCustomAttribute:
1079 printLine(GUICookie,szString);
1080 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
1081 {
1082 mdToken tkType;
1083 mdToken tkOwner;
1084 BYTE* pBlob=NULL;
1085 ULONG uLen=0;
1086 tkType = GET_UNALIGNED_VAL32(pTDD->psig);
1087 tkOwner = GET_UNALIGNED_VAL32(pTDD->psig + sizeof(mdToken));
1088 if(pTDD->cb > 2*sizeof(mdToken))
1089 {
1090 pBlob = (BYTE*)pTDD->psig + 2*sizeof(mdToken);
1091 uLen = pTDD->cb - 2*sizeof(mdToken);
1092 }
1093 DumpCustomAttributeProps(0,tkType,tkOwner,pBlob,uLen,GUICookie,
1094 (RidFromToken(tkOwner)!=0));
1095
1096 }
1097 sprintf_s(szString,SZSTRING_SIZE,"%s %s %s", g_szAsmCodeIndent,KEYWORD("as"),
1098 ProperName((*g_typedefs)[i].szName));
1099 printLine(GUICookie,szString);
1100 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-8]=0;
1101 continue;
1102
1103 case mdtMethodDef:
1104 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
1105 break;
1106
1107 case mdtFieldDef:
1108 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
1109 break;
1110
1111 case mdtMemberRef:
1112 {
1113 PCCOR_SIGNATURE typePtr;
1114 const char *pszMemberName;
1115 ULONG cComSig;
1116
1117 if (FAILED(g_pImport->GetNameAndSigOfMemberRef(
1118 tk,
1119 &typePtr,
1120 &cComSig,
1121 &pszMemberName)))
1122 {
1123 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"ERROR ");
1124 break;
1125 }
1126 unsigned callConv = CorSigUncompressData(typePtr);
1127
1128 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
1129 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
1130 else
1131 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
1132 break;
1133 }
1134 }
1135 g_NumTypedefs = 0;
1136 PrettyPrintToken(szString, tk, g_pImport,g_pFile,0);
1137 g_NumTypedefs = n;
1138 szptr = &szString[strlen(szString)];
1139 }
1140 szptr+= sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s %s", KEYWORD("as"), ProperName((*g_typedefs)[i].szName));
1141 printLine(GUICookie,szString);
1142 }
1143}
1144
1145BOOL PrintClassList()
1146{
1147 DWORD i;
1148 BOOL fSuccess = FALSE;
1149 //char szString[1024];
1150 char* szptr;
1151
1152 if(g_NumClasses)
1153 {
1154 printLine(g_pFile,COMMENT("// Classes defined in this module:"));
1155 printLine(g_pFile,COMMENT("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
1156
1157 for (i = 0; i < g_NumClasses; i++)
1158 {
1159 const char *pszClassName;
1160 const char *pszNamespace;
1161 DWORD dwClassAttrs;
1162 mdTypeRef crExtends;
1163
1164 if (FAILED(g_pImport->GetNameOfTypeDef(
1165 g_cl_list[i],
1166 &pszClassName,
1167 &pszNamespace)))
1168 {
1169 printLine(g_pFile, COMMENT("// Invalid TypeDef record"));
1170 return FALSE;
1171 }
1172 MAKE_NAME_IF_NONE(pszClassName,g_cl_list[i]);
1173 // if this is the "<Module>" class (there is a misnomer) then skip it!
1174 if (FAILED(g_pImport->GetTypeDefProps(
1175 g_cl_list[i],
1176 &dwClassAttrs,
1177 &crExtends)))
1178 {
1179 printLine(g_pFile, COMMENT("// Invalid TypeDef record"));
1180 return FALSE;
1181 }
1182 szptr = &szString[0];
1183 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"// ");
1184 if (IsTdInterface(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"Interface ");
1185 //else if (IsTdValueType(dwClassAttrs)) szptr+=sprintf(szptr,"Value Class");
1186 //else if (IsTdUnmanagedValueType(dwClassAttrs)) szptr+=sprintf(szptr,"NotInGCHeap Value Class");
1187 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"Class ");
1188
1189 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-30s ", pszClassName);
1190
1191 if (IsTdPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(public) ");
1192 if (IsTdAbstract(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(abstract) ");
1193 if (IsTdAutoLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(auto) ");
1194 if (IsTdSequentialLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(sequential) ");
1195 if (IsTdExplicitLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(explicit) ");
1196 if (IsTdAnsiClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(ansi) ");
1197 if (IsTdUnicodeClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(unicode) ");
1198 if (IsTdAutoClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(autochar) ");
1199 if (IsTdImport(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(import) ");
1200 if (IsTdWindowsRuntime(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(windowsruntime) ");
1201 //if (IsTdEnum(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(enum) ");
1202 if (IsTdSealed(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(sealed) ");
1203 if (IsTdNestedPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested public) ");
1204 if (IsTdNestedPrivate(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested private) ");
1205 if (IsTdNestedFamily(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested family) ");
1206 if (IsTdNestedAssembly(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested assembly) ");
1207 if (IsTdNestedFamANDAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested famANDassem) ");
1208 if (IsTdNestedFamORAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(nested famORassem) ");
1209
1210 printLine(g_pFile,COMMENT(szString));
1211 }
1212 printLine(g_pFile,COMMENT("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
1213 printLine(g_pFile,"");
1214 }
1215 else
1216 printLine(g_pFile,COMMENT("// No classes defined in this module"));
1217 fSuccess = TRUE;
1218
1219 return fSuccess;
1220}
1221
1222BOOL ValidateToken(mdToken tk, ULONG type = (ULONG) ~0)
1223{
1224 BOOL bRtn;
1225 //char szString[1024];
1226 bRtn = g_pImport->IsValidToken(tk);
1227 if (!bRtn)
1228 {
1229 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_INVALIDTK), tk);
1230 printError(g_pFile,szString);
1231 }
1232 else if (type != (ULONG) ~0 && TypeFromToken(tk) != type)
1233 {
1234 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_UNEXPTYPE),
1235 TypeFromToken(type), TypeFromToken(tk));
1236 printError(g_pFile,szString);
1237 bRtn = FALSE;
1238 }
1239 return bRtn;
1240}
1241
1242
1243BOOL DumpModule(mdModuleRef mdMod)
1244{
1245 const char *pszModName;
1246 //char szString[1024];
1247 if (FAILED(g_pImport->GetModuleRefProps(mdMod,&pszModName)))
1248 {
1249 pszModName = "Invalid ModuleRef record";
1250 }
1251 MAKE_NAME_IF_NONE(pszModName,mdMod);
1252 sprintf_s(szString,SZSTRING_SIZE,"%s%s \"%s\"",g_szAsmCodeIndent,KEYWORD(".import"),pszModName); // what about GUID and MVID?
1253 printLine(g_pFile,szString);
1254 return TRUE;
1255}
1256
1257char* DumpPinvokeMap(DWORD dwMappingFlags, const char *szImportName,
1258 mdModuleRef mrImportDLL, __inout __nullterminated char* szString, void* GUICookie)
1259{
1260 const char *szImportDLLName;
1261 char* szptr = &szString[strlen(szString)];
1262
1263 if (FAILED(g_pImport->GetModuleRefProps(mrImportDLL,&szImportDLLName)))
1264 {
1265 szImportDLLName = "Invalid ModuleRef record";
1266 }
1267 if(strlen(szImportDLLName) != 0)
1268 {
1269 szptr = DumpQString(GUICookie,
1270 (char*)szImportDLLName,
1271 g_szAsmCodeIndent,
1272 80);
1273 }
1274
1275 //if(strlen(szImportDLLName)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"\"%s\"",szImportDLLName);
1276 //if(szImportName && strlen(szImportName)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," as \"%s\"",szImportName);
1277 if(szImportName && strlen(szImportName))
1278 {
1279 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD(" as "));
1280 szptr = DumpQString(GUICookie,
1281 (char*)szImportName,
1282 g_szAsmCodeIndent,
1283 80);
1284 }
1285 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
1286 if(IsPmNoMangle(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," nomangle");
1287 if(IsPmCharSetAnsi(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," ansi");
1288 if(IsPmCharSetUnicode(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," unicode");
1289 if(IsPmCharSetAuto(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," autochar");
1290 if(IsPmSupportsLastError(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," lasterr");
1291 if(IsPmCallConvWinapi(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," winapi");
1292 if(IsPmCallConvCdecl(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," cdecl");
1293 if(IsPmCallConvThiscall(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," thiscall");
1294 if(IsPmCallConvFastcall(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," fastcall");
1295 if(IsPmCallConvStdcall(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," stdcall");
1296 if(IsPmBestFitEnabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," bestfit:on");
1297 if(IsPmBestFitDisabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," bestfit:off");
1298 if(IsPmThrowOnUnmappableCharEnabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," charmaperror:on");
1299 if(IsPmThrowOnUnmappableCharDisabled(dwMappingFlags)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," charmaperror:off");
1300 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
1301 return szptr;
1302}
1303
1304void DumpByteArray(__inout __nullterminated char* szString, const BYTE* pBlob, ULONG ulLen, void* GUICookie)
1305{
1306 ULONG32 ulStrOffset = 0;
1307 ULONG32 j = 0;
1308 ULONG32 k = 0;
1309 ULONG32 m = 0;
1310 char sz[256];
1311 bool printsz = FALSE;
1312 char* szptr = NULL;
1313 BYTE byt = 0;
1314
1315
1316 ulStrOffset = (ULONG32) strlen(szString);
1317 szptr = &szString[ulStrOffset];
1318 if(!pBlob) ulLen = 0;
1319 for(j = 0, k=0, m=0; j < ulLen; j++,k++,m++)
1320 {
1321 if(k == 16)
1322 {
1323 if(printsz)
1324 {
1325 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" // %s"),sz);
1326 }
1327 printLine(GUICookie,szString);
1328 strcpy_s(szString,SZSTRING_SIZE,g_szAsmCodeIndent);
1329 for(k=(ULONG32) strlen(szString); k < ulStrOffset; k++) szString[k] = ' ';
1330 szString[k] = 0;
1331 szptr = &szString[ulStrOffset];
1332 k = 0;
1333 m = 0;
1334 printsz = FALSE;
1335 }
1336 bool bBreak = FALSE;
1337 PAL_CPP_TRY {
1338 byt = pBlob[j];
1339 }
1340 PAL_CPP_CATCH_ALL
1341 {
1342 strcat_s(szString, SZSTRING_SIZE,ERRORMSG("INVALID DATA ADDRESS"));
1343 bBreak = TRUE;
1344 }
1345 PAL_CPP_ENDTRY;
1346
1347 if (bBreak)
1348 break;
1349
1350 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X ",byt);
1351 if(isprint(byt))
1352 {
1353 if(g_fDumpRTF)
1354 {
1355 if((byt == '\\')||(byt=='{')||(byt=='}')) sz[m++]='\\';
1356 sz[m] = byt;
1357 }
1358 else if(g_fDumpHTML)
1359 {
1360 if(byt == '<') { sz[m] = 0; strcat_s(sz,256-m,LTN()); m+=(ULONG32)(strlen(LTN())); }
1361 else if(byt == '>') { sz[m] = 0; strcat_s(sz,256-m,GTN()); m+=(ULONG32)(strlen(GTN())); }
1362 else sz[m] = byt;
1363 }
1364 else sz[m] = byt;
1365 printsz = TRUE;
1366 }
1367 else sz[m] = '.';
1368 sz[m+1] = 0;
1369 }
1370 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
1371 if(printsz)
1372 {
1373 for(j = k; j < 16; j++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," ");
1374 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// %s"),sz);
1375 }
1376}
1377
1378mdToken ResolveTypeDefReflectionNotation(IMDInternalImport *pIMDI,
1379 LPCUTF8 szNamespace,
1380 __inout LPUTF8 szName,
1381 mdToken tkEncloser)
1382{
1383 mdToken tk = 0;
1384 LPUTF8 pch = strrchr(szName, '+');
1385 if(pch != NULL)
1386 {
1387 *pch = 0;
1388 tkEncloser = ResolveTypeDefReflectionNotation(pIMDI,szNamespace,szName,tkEncloser);
1389 szNamespace = "";
1390 szName = pch+1;
1391 }
1392 if(SUCCEEDED(pIMDI->FindTypeDef(szNamespace,szName,tkEncloser,&tk)))
1393 return tk;
1394 else
1395 return 0;
1396}
1397
1398mdToken ResolveTypeRefReflectionNotation(IMDInternalImport *pIMDI,
1399 __in __nullterminated const char* szNamespace,
1400 __inout __nullterminated char* szName,
1401 mdToken tkResScope)
1402{
1403 mdToken tk = 0;
1404 char* pch = strrchr(szName, '+');
1405 if(pch != NULL)
1406 {
1407 *pch = 0;
1408 tkResScope = ResolveTypeRefReflectionNotation(pIMDI,szNamespace,szName,tkResScope);
1409 szNamespace = "";
1410 szName = pch+1;
1411 }
1412 if(SUCCEEDED(pIMDI->FindTypeRefByName((LPCSTR)szNamespace,(LPCSTR)szName,tkResScope,&tk)))
1413 return tk;
1414 else
1415 return 0;
1416}
1417mdToken ResolveReflectionNotation(BYTE* dataPtr,
1418 unsigned Lstr,
1419 IMDInternalImport *pIMDI,
1420 void* GUICookie)
1421{
1422 char* str = new char[Lstr+1];
1423 mdToken ret = 0;
1424 if(str)
1425 {
1426 char szNamespaceDefault[] = "";
1427 char* szNamespace = szNamespaceDefault;
1428 char* szName = str;
1429 char* szAssembly = NULL;
1430 char szAssemblyMscorlib[] = "mscorlib";
1431 char* pch;
1432 memcpy(str,dataPtr,Lstr);
1433 str[Lstr] = 0;
1434 //format: Namespace.Name, Assembly,...
1435 pch = strchr(str,',');
1436 if(pch)
1437 {
1438 *pch = 0;
1439 for(szAssembly = pch+1; *szAssembly == ' '; szAssembly++);
1440 pch = strchr(szAssembly,',');
1441 if(pch) *pch = 0;
1442 }
1443 pch = strrchr(str,'.');
1444 if(pch)
1445 {
1446 *pch = 0;
1447 szNamespace = str;
1448 szName = pch+1;
1449 }
1450 if(szAssembly == NULL)
1451 {
1452 // Look in TypeDefs
1453 mdToken tk = ResolveTypeDefReflectionNotation(pIMDI,szNamespace,szName,mdTypeDefNil);
1454 if(tk != 0)
1455 ret = tk;
1456 else
1457 // TypeDef not found, try TypeRef from mscorlib
1458 szAssembly = szAssemblyMscorlib;
1459 }
1460 if(szAssembly != NULL)
1461 {
1462 // Look in TypeRefs
1463 // First, identify resolution scope
1464 _ASSERTE(*szName);
1465 ULONG mAsmRefs = pIMDI->GetCountWithTokenKind(mdtAssemblyRef);
1466 if(mAsmRefs)
1467 {
1468 mdToken tkResScope = 0;
1469 mdToken tk=TokenFromRid(mdtAssemblyRef,1), tkmax=TokenFromRid(mdtAssemblyRef,mAsmRefs);
1470 LPCSTR szAsmRefName;
1471 // these are dummies
1472 const void* pPKT, *pHash;
1473 ULONG ulPKT,ulHash;
1474 AssemblyMetaDataInternal MD;
1475 DWORD dwFlags;
1476
1477 for (;tk <= tkmax; tk++)
1478 {
1479 if (FAILED(pIMDI->GetAssemblyRefProps(tk,&pPKT,&ulPKT,&szAsmRefName,&MD,&pHash,&ulHash,&dwFlags)))
1480 {
1481 continue;
1482 }
1483 if(0==strcmp(szAsmRefName,szAssembly))
1484 {
1485 tkResScope = tk;
1486 break;
1487 }
1488 }
1489 if(tkResScope)
1490 {
1491 ret = ResolveTypeRefReflectionNotation(pIMDI,szNamespace,szName,tkResScope);
1492 }
1493 }
1494 }
1495 }
1496 VDELETE(str);
1497 return ret;
1498}
1499
1500unsigned UnderlyingTypeOfEnumTypeDef(mdToken tk, IMDInternalImport *pIMDI)
1501{
1502 // make sure it's a TypeDef
1503 if(TypeFromToken(tk) != mdtTypeDef) return 0;
1504
1505 // make sure it's an enum
1506 mdToken tkParent;
1507 DWORD dwAttr;
1508 if (FAILED(pIMDI->GetTypeDefProps(tk,&dwAttr,&tkParent)))
1509 {
1510 return 0;
1511 }
1512 if(RidFromToken(tkParent)==0) return 0;
1513 LPCSTR szName, szNamespace;
1514 switch(TypeFromToken(tkParent))
1515 {
1516 case mdtTypeDef:
1517 if (FAILED(pIMDI->GetNameOfTypeDef(tkParent, &szName, &szNamespace)))
1518 {
1519 return 0;
1520 }
1521 break;
1522
1523 case mdtTypeRef:
1524 if (FAILED(pIMDI->GetNameOfTypeRef(tkParent, &szNamespace, &szName)))
1525 {
1526 return 0;
1527 }
1528 break;
1529
1530 default:
1531 return 0;
1532 }
1533
1534 if (strcmp(szName,"Enum") != 0 || strcmp(szNamespace,"System") != 0)
1535 {
1536 // the parent type is not System.Enum so this type has no underlying type
1537 return 0;
1538 }
1539
1540 // OK, it's an enum; find its instance field and get its type
1541 HENUMInternal hEnum;
1542 mdToken tkField;
1543 if (FAILED(pIMDI->EnumInit(mdtFieldDef,tk,&hEnum)))
1544 {
1545 return 0;
1546 }
1547 while(pIMDI->EnumNext(&hEnum,&tkField))
1548 {
1549 if (FAILED(pIMDI->GetFieldDefProps(tkField, &dwAttr)))
1550 {
1551 continue;
1552 }
1553 if (IsFdStatic(dwAttr))
1554 {
1555 continue;
1556 }
1557 PCCOR_SIGNATURE psig;
1558 if (FAILED(pIMDI->GetSigOfFieldDef(tkField,(ULONG*)&dwAttr, &psig)))
1559 {
1560 continue;
1561 }
1562 pIMDI->EnumClose(&hEnum);
1563 return (unsigned) *(psig+1);
1564 }
1565 // no instance field found -- error!
1566 pIMDI->EnumClose(&hEnum);
1567 return 0;
1568}
1569mdToken TypeRefToTypeDef(mdToken tk, IMDInternalImport *pIMDI, IMDInternalImport **ppIMDInew)
1570{
1571 mdToken tkEncloser = mdTypeDefNil;
1572 mdToken tkTypeDef = mdTypeDefNil;
1573 *ppIMDInew = NULL;
1574
1575 // get the resolution scope of TypeRef
1576 mdToken tkRS;
1577 if (FAILED(pIMDI->GetResolutionScopeOfTypeRef(tk, &tkRS)))
1578 {
1579 goto AssignAndReturn;
1580 }
1581 if (TypeFromToken(tkRS) == mdtTypeRef)
1582 tkEncloser = TypeRefToTypeDef(tkRS,pIMDI,ppIMDInew);
1583 else if (TypeFromToken(tkRS) == mdtAssemblyRef)
1584 {
1585 *ppIMDInew = g_asmref_import[RidFromToken(tkRS)];
1586 if (*ppIMDInew == NULL)
1587 {
1588 // get that assembly and open IMDInternalImport
1589 IMetaDataAssemblyImport* pAssemblyImport;
1590 if (FAILED(g_pPubImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**) &pAssemblyImport)))
1591 goto AssignAndReturn;
1592
1593 const void *pPKT, *pHash;
1594 ULONG cHash,cName;
1595 WCHAR wzName[2048];
1596 ASSEMBLYMETADATA md;
1597 WCHAR wzLocale[1024];
1598 DWORD dwFlags;
1599 IUnknown* pIAMDI[64];
1600 memset(&md,0,sizeof(ASSEMBLYMETADATA));
1601 md.szLocale = wzLocale;
1602 md.cbLocale = 1024;
1603
1604 struct Param
1605 {
1606 IMetaDataAssemblyImport* pAssemblyImport;
1607 WCHAR *wzName;
1608 IUnknown **pIAMDI;
1609 ULONG cPKT;
1610 } param;
1611 param.pAssemblyImport = pAssemblyImport;
1612 param.wzName = wzName;
1613 param.pIAMDI = pIAMDI;
1614
1615 pAssemblyImport->GetAssemblyRefProps(tkRS,&pPKT,&param.cPKT,wzName,2048,&cName,&md,&pHash,&cHash,&dwFlags);
1616
1617 PAL_TRY(Param *, pParam, &param) {
1618 if(FAILED(pParam->pAssemblyImport->FindAssembliesByName(NULL,NULL,(LPCWSTR)pParam->wzName,pParam->pIAMDI,64,&pParam->cPKT)))
1619 pParam->cPKT=0;
1620 } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1621 param.cPKT=0;
1622 } PAL_ENDTRY
1623
1624 pAssemblyImport->Release();
1625 if(param.cPKT == 0) goto AssignAndReturn;
1626 _ASSERTE(pIAMDI[0] != NULL);
1627
1628 IUnknown *pUnk;
1629 if(FAILED(pIAMDI[0]->QueryInterface(IID_IUnknown, (void**)&pUnk))) goto AssignAndReturn;
1630
1631 if (FAILED(getMetaDataInternalInterfaceFromPublic(
1632 pUnk,
1633 IID_IMDInternalImport,
1634 (LPVOID *)ppIMDInew)))
1635 {
1636 goto AssignAndReturn;
1637 }
1638 _ASSERTE(*ppIMDInew != NULL);
1639 g_asmref_import[RidFromToken(tkRS)] = *ppIMDInew;
1640 pUnk->Release();
1641 for(cHash=0; cHash<param.cPKT; cHash++)
1642 if(pIAMDI[cHash]) pIAMDI[cHash]->Release();
1643 }
1644 }
1645 if (*ppIMDInew != NULL)
1646 {
1647 LPCSTR szName, szNamespace;
1648 if (FAILED(pIMDI->GetNameOfTypeRef(tk, &szNamespace, &szName)))
1649 {
1650 tkTypeDef = mdTypeDefNil;
1651 goto AssignAndReturn;
1652 }
1653
1654 if (FAILED((*ppIMDInew)->FindTypeDef(szNamespace,szName,tkEncloser,&tkTypeDef)))
1655 {
1656 tkTypeDef = mdTypeDefNil;
1657 }
1658 }
1659AssignAndReturn:
1660 return tkTypeDef;
1661}
1662unsigned UnderlyingTypeOfEnum(mdToken tk, IMDInternalImport *pIMDI)
1663{
1664 unsigned uRet = 0;
1665 unsigned ix = RidFromToken(tk);
1666 if(TypeFromToken(tk)==mdtTypeDef)
1667 {
1668 if(g_enum_td_type[ix] == 0xFF)
1669 {
1670 g_enum_td_type[ix] = (BYTE)UnderlyingTypeOfEnumTypeDef(tk,pIMDI);
1671 }
1672 return (unsigned)g_enum_td_type[ix];
1673 }
1674 else if(TypeFromToken(tk)==mdtTypeRef)
1675 {
1676 if(g_enum_tr_type[ix] == 0xFF)
1677 {
1678 IMDInternalImport *pIMDInew = NULL;
1679 mdToken tkTypeDef = TypeRefToTypeDef(tk,pIMDI, &pIMDInew);
1680 if((RidFromToken(tkTypeDef)!=0)&&(pIMDInew != NULL))
1681 {
1682 uRet = UnderlyingTypeOfEnumTypeDef(tkTypeDef,pIMDInew);
1683 }
1684 g_enum_tr_type[ix] = (BYTE)uRet;
1685 }
1686 return (unsigned)g_enum_tr_type[ix];
1687 }
1688 else return 0;
1689}
1690
1691/**************************************************************************/
1692/* move 'ptr past the exactly one type description */
1693
1694BYTE* skipType(BYTE* ptr)
1695{
1696 mdToken tk;
1697AGAIN:
1698 switch(*ptr++) {
1699 case ELEMENT_TYPE_VOID :
1700 case ELEMENT_TYPE_BOOLEAN :
1701 case ELEMENT_TYPE_CHAR :
1702 case ELEMENT_TYPE_I1 :
1703 case ELEMENT_TYPE_U1 :
1704 case ELEMENT_TYPE_I2 :
1705 case ELEMENT_TYPE_U2 :
1706 case ELEMENT_TYPE_I4 :
1707 case ELEMENT_TYPE_U4 :
1708 case ELEMENT_TYPE_I8 :
1709 case ELEMENT_TYPE_U8 :
1710 case ELEMENT_TYPE_R4 :
1711 case ELEMENT_TYPE_R8 :
1712 case ELEMENT_TYPE_U :
1713 case ELEMENT_TYPE_I :
1714 case ELEMENT_TYPE_STRING :
1715 case ELEMENT_TYPE_OBJECT :
1716 case ELEMENT_TYPE_TYPEDBYREF :
1717 case ELEMENT_TYPE_SENTINEL :
1718 case SERIALIZATION_TYPE_TYPE :
1719 case SERIALIZATION_TYPE_TAGGED_OBJECT :
1720 /* do nothing */
1721 break;
1722
1723 case SERIALIZATION_TYPE_ENUM :
1724 {
1725 unsigned Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)ptr);
1726 ptr += Lstr;
1727 break;
1728 }
1729
1730 case ELEMENT_TYPE_VALUETYPE :
1731 case ELEMENT_TYPE_CLASS :
1732 ptr += CorSigUncompressToken(ptr, &tk);
1733 break;
1734
1735 case ELEMENT_TYPE_CMOD_REQD :
1736 case ELEMENT_TYPE_CMOD_OPT :
1737 ptr += CorSigUncompressToken(ptr, &tk);
1738 goto AGAIN;
1739
1740 case ELEMENT_TYPE_ARRAY :
1741 {
1742 ptr = skipType(ptr); // element Type
1743 unsigned rank = CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
1744 if (rank != 0)
1745 {
1746 unsigned numSizes = CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
1747 while(numSizes > 0)
1748 {
1749 CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
1750 --numSizes;
1751 }
1752 unsigned numLowBounds = CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
1753 while(numLowBounds > 0)
1754 {
1755 CorSigUncompressData((PCCOR_SIGNATURE&) ptr);
1756 --numLowBounds;
1757 }
1758 }
1759 }
1760 break;
1761
1762 // Modifiers or depedant types
1763 case ELEMENT_TYPE_PINNED :
1764 case ELEMENT_TYPE_PTR :
1765 case ELEMENT_TYPE_BYREF :
1766 case ELEMENT_TYPE_SZARRAY :
1767 // tail recursion optimization
1768 // ptr = skipType(ptr, fFixupType);
1769 // break
1770 goto AGAIN;
1771
1772 case ELEMENT_TYPE_VAR:
1773 case ELEMENT_TYPE_MVAR:
1774 CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // bound
1775 break;
1776
1777 case ELEMENT_TYPE_FNPTR:
1778 {
1779 CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // calling convention
1780 unsigned argCnt = CorSigUncompressData((PCCOR_SIGNATURE&) ptr); // arg count
1781 ptr = skipType(ptr); // return type
1782 while(argCnt > 0)
1783 {
1784 ptr = skipType(ptr);
1785 --argCnt;
1786 }
1787 }
1788 break;
1789
1790 case ELEMENT_TYPE_GENERICINST:
1791 {
1792 ptr = skipType(ptr); // type constructor
1793 unsigned argCnt = CorSigUncompressData((PCCOR_SIGNATURE&)ptr); // arg count
1794 while(argCnt > 0) {
1795 ptr = skipType(ptr);
1796 --argCnt;
1797 }
1798 }
1799 break;
1800
1801 default:
1802 case ELEMENT_TYPE_END :
1803 _ASSERTE(!"Unknown Type");
1804 break;
1805 }
1806 return(ptr);
1807}
1808
1809
1810#ifdef _PREFAST_
1811#pragma warning(push)
1812#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1813#endif
1814BYTE* PrettyPrintCABlobValue(PCCOR_SIGNATURE &typePtr,
1815 BYTE* dataPtr,
1816 BYTE* dataEnd,
1817 CQuickBytes* out,
1818 IMDInternalImport *pIMDI,
1819 void* GUICookie)
1820{
1821 char str[64];
1822 char appendix[64];
1823 int typ;
1824 BOOL Reiterate;
1825 BOOL CloseParenthesis;
1826 unsigned numElements = 1;
1827 unsigned n,Lstr;
1828 unsigned underType;
1829 mdToken tk;
1830
1831 appendix[0] = 0;
1832 do {
1833 if(dataPtr >= dataEnd)
1834 {
1835 _ASSERTE(!"CA blob too short");
1836 return FALSE;
1837 }
1838 Reiterate = FALSE;
1839 CloseParenthesis = TRUE;
1840 switch(typ = *typePtr++) {
1841 case ELEMENT_TYPE_VOID :
1842 return NULL;
1843 case ELEMENT_TYPE_BOOLEAN :
1844 appendStr(out,KEYWORD("bool"));
1845 appendStr(out,appendix);
1846 appendStr(out,"(");
1847 for(n=0; n < numElements; n++)
1848 {
1849 if(n) appendStr(out," ");
1850 appendStr(out,(*dataPtr)? KEYWORD("true"):KEYWORD("false"));
1851 dataPtr++;
1852 }
1853 break;
1854 case ELEMENT_TYPE_CHAR :
1855 appendStr(out,KEYWORD("char"));
1856 appendStr(out,appendix);
1857 appendStr(out,"(");
1858 for(n=0; n < numElements; n++)
1859 {
1860 if(n) appendStr(out," ");
1861 sprintf_s(str,64,"0x%4.4X",(WORD)GET_UNALIGNED_VAL16(dataPtr));
1862 appendStr(out,str);
1863 dataPtr += 2;
1864 }
1865 break;
1866 case ELEMENT_TYPE_I1 :
1867 appendStr(out,KEYWORD("int8"));
1868 appendStr(out,appendix);
1869 appendStr(out,"(");
1870 for(n=0; n < numElements; n++)
1871 {
1872 if(n) appendStr(out," ");
1873 sprintf_s(str,64,"%d",*((char*)dataPtr));
1874 appendStr(out,str);
1875 dataPtr ++;
1876 }
1877 break;
1878 case ELEMENT_TYPE_U1 :
1879 appendStr(out,KEYWORD("uint8"));
1880 appendStr(out,appendix);
1881 appendStr(out,"(");
1882 for(n=0; n < numElements; n++)
1883 {
1884 if(n) appendStr(out," ");
1885 sprintf_s(str,64,"%d",*dataPtr);
1886 appendStr(out,str);
1887 dataPtr ++;
1888 }
1889 break;
1890 case ELEMENT_TYPE_I2 :
1891 appendStr(out,KEYWORD("int16"));
1892 appendStr(out,appendix);
1893 appendStr(out,"(");
1894 for(n=0; n < numElements; n++)
1895 {
1896 if(n) appendStr(out," ");
1897 sprintf_s(str,64,"%d",GET_UNALIGNED_VAL16(dataPtr));
1898 appendStr(out,str);
1899 dataPtr +=2;
1900 }
1901 break;
1902 case ELEMENT_TYPE_U2 :
1903 appendStr(out,KEYWORD("uint16"));
1904 appendStr(out,appendix);
1905 appendStr(out,"(");
1906 for(n=0; n < numElements; n++)
1907 {
1908 if(n) appendStr(out," ");
1909 sprintf_s(str,64,"%d",(WORD)GET_UNALIGNED_VAL16(dataPtr));
1910 appendStr(out,str);
1911 dataPtr +=2;
1912 }
1913 break;
1914 case ELEMENT_TYPE_I4 :
1915 appendStr(out,KEYWORD("int32"));
1916 appendStr(out,appendix);
1917 appendStr(out,"(");
1918 for(n=0; n < numElements; n++)
1919 {
1920 if(n) appendStr(out," ");
1921 sprintf_s(str,64,"%d",GET_UNALIGNED_VAL32(dataPtr));
1922 appendStr(out,str);
1923 dataPtr +=4;
1924 }
1925 break;
1926 case ELEMENT_TYPE_U4 :
1927 appendStr(out,KEYWORD("uint32"));
1928 appendStr(out,appendix);
1929 appendStr(out,"(");
1930 for(n=0; n < numElements; n++)
1931 {
1932 if(n) appendStr(out," ");
1933 sprintf_s(str,64,"%d",(unsigned)GET_UNALIGNED_VAL32(dataPtr));
1934 appendStr(out,str);
1935 dataPtr +=4;
1936 }
1937 break;
1938 case ELEMENT_TYPE_I8 :
1939 appendStr(out,KEYWORD("int64"));
1940 appendStr(out,appendix);
1941 appendStr(out,"(");
1942 for(n=0; n < numElements; n++)
1943 {
1944 if(n) appendStr(out," ");
1945 sprintf_s(str,64,"%I64d",GET_UNALIGNED_VAL64(dataPtr));
1946 appendStr(out,str);
1947 dataPtr +=8;
1948 }
1949 break;
1950 case ELEMENT_TYPE_U8 :
1951 appendStr(out,KEYWORD("uint64"));
1952 appendStr(out,appendix);
1953 appendStr(out,"(");
1954 for(n=0; n < numElements; n++)
1955 {
1956 if(n) appendStr(out," ");
1957 sprintf_s(str,64,"%I64d",(ULONGLONG)GET_UNALIGNED_VAL64(dataPtr));
1958 appendStr(out,str);
1959 dataPtr +=8;
1960 }
1961 break;
1962 case ELEMENT_TYPE_R4 :
1963 appendStr(out,KEYWORD("float32"));
1964 appendStr(out,appendix);
1965 appendStr(out,"(");
1966 for(n=0; n < numElements; n++)
1967 {
1968 if(n) appendStr(out," ");
1969 _gcvt_s(str,64,*((float*)dataPtr), 8);
1970 float df = (float)atof(str);
1971 // Must compare as underlying bytes, not floating point otherwise optmizier will
1972 // try to enregister and comapre 80-bit precision number with 32-bit precision number!!!!
1973 if((*(ULONG*)&df != (ULONG)GET_UNALIGNED_VAL32(dataPtr))||IsSpecialNumber(str))
1974 sprintf_s(str, 64,"0x%08X",(ULONG)GET_UNALIGNED_VAL32(dataPtr));
1975 appendStr(out,str);
1976 dataPtr +=4;
1977 }
1978 break;
1979
1980 case ELEMENT_TYPE_R8 :
1981 appendStr(out,KEYWORD("float64"));
1982 appendStr(out,appendix);
1983 appendStr(out,"(");
1984 for(n=0; n < numElements; n++)
1985 {
1986 if(n) appendStr(out," ");
1987 char *pch;
1988 _gcvt_s(str,64,*((double*)dataPtr), 17);
1989 double df = strtod(str, &pch);
1990 // Must compare as underlying bytes, not floating point otherwise optmizier will
1991 // try to enregister and comapre 80-bit precision number with 64-bit precision number!!!!
1992 if((*(ULONGLONG*)&df != (ULONGLONG)GET_UNALIGNED_VAL64(dataPtr))||IsSpecialNumber(str))
1993 sprintf_s(str, 64, "0x%I64X",(ULONGLONG)GET_UNALIGNED_VAL64(dataPtr));
1994 appendStr(out,str);
1995 dataPtr +=8;
1996 }
1997 break;
1998 case ELEMENT_TYPE_U :
1999 case ELEMENT_TYPE_I :
2000 return NULL;
2001
2002 case ELEMENT_TYPE_OBJECT :
2003 case SERIALIZATION_TYPE_TAGGED_OBJECT:
2004 appendStr(out,KEYWORD("object"));
2005 appendStr(out,appendix);
2006 appendStr(out,"(");
2007 for(n=0; n < numElements; n++)
2008 {
2009 BYTE* dataPtr1 = skipType(dataPtr);
2010 if(n) appendStr(out," ");
2011
2012 dataPtr = PrettyPrintCABlobValue((PCCOR_SIGNATURE&)dataPtr, dataPtr1, dataEnd, out, pIMDI,GUICookie);
2013 if (dataPtr == NULL) return NULL;
2014 }
2015 break;
2016 case ELEMENT_TYPE_STRING :
2017 appendStr(out,KEYWORD("string"));
2018 appendStr(out,appendix);
2019 appendStr(out,"(");
2020 for(n=0; n < numElements; n++)
2021 {
2022 if(n) appendStr(out," ");
2023 if(*dataPtr == 0xFF)
2024 {
2025 appendStr(out,KEYWORD("nullref"));
2026 Lstr = 1;
2027 }
2028 else
2029 {
2030 appendStr(out,"'");
2031 Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
2032 if(dataPtr + Lstr > dataEnd) return NULL;
2033 appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
2034 appendStr(out,"'");
2035 }
2036 dataPtr += Lstr;
2037 }
2038 break;
2039 case ELEMENT_TYPE_CLASS :
2040 typePtr += CorSigUncompressToken(typePtr, &tk); //skip the following token
2041 case SERIALIZATION_TYPE_TYPE :
2042 appendStr(out,KEYWORD("type"));
2043 appendStr(out,appendix);
2044 appendStr(out,"(");
2045 for(n=0; n < numElements; n++)
2046 {
2047 if(n) appendStr(out," ");
2048 if(*dataPtr == 0xFF)
2049 {
2050 appendStr(out,KEYWORD("nullref"));
2051 Lstr = 1;
2052 }
2053 else
2054 {
2055 Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
2056 if(dataPtr + Lstr > dataEnd) return NULL;
2057 tk = ResolveReflectionNotation(dataPtr,Lstr,pIMDI,GUICookie);
2058 if(IsNilToken(tk))
2059 {
2060 appendStr(out,KEYWORD("class "));
2061 appendStr(out,"'");
2062 appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
2063 appendStr(out,"'");
2064 }
2065 else
2066 {
2067 PrettyPrintClass(out, tk, pIMDI);
2068 }
2069 }
2070 dataPtr += Lstr;
2071 }
2072 break;
2073
2074
2075 case ELEMENT_TYPE_VALUETYPE :
2076 typePtr += CorSigUncompressToken(typePtr, &tk);
2077 _ASSERTE(pIMDI->IsValidToken(tk));
2078 goto GetUTSize;
2079
2080 case SERIALIZATION_TYPE_ENUM :
2081 Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)typePtr);
2082 tk = ResolveReflectionNotation((BYTE*)typePtr,Lstr,pIMDI,GUICookie);
2083 /*
2084 if(IsNilToken(tk))
2085 {
2086 _ASSERTE(!"Failed to resolve Reflection notation for S_T_ENUM");
2087 return NULL;
2088 }
2089 */
2090 typePtr += Lstr;
2091
2092 GetUTSize:
2093 underType = UnderlyingTypeOfEnum(tk, pIMDI);
2094 if(underType == 0)
2095 {
2096 // try to figure out the underlying type by its size
2097 switch(dataEnd - dataPtr)
2098 {
2099 case 1: // bool
2100 underType = ELEMENT_TYPE_BOOLEAN;
2101 break;
2102 case 2: // int16
2103 underType = ELEMENT_TYPE_I2;
2104 break;
2105 case 4: // int32
2106 underType = ELEMENT_TYPE_I4;
2107 break;
2108 case 8: // int64
2109 underType = ELEMENT_TYPE_I8;
2110 break;
2111 default:
2112 return NULL;
2113 }
2114 //_ASSERTE(!"Failed to find underlying type for S_T_ENUM");
2115 }
2116 {
2117 PCCOR_SIGNATURE ps = (PCCOR_SIGNATURE)&underType;
2118 dataPtr = PrettyPrintCABlobValue(ps, dataPtr, dataEnd, out, pIMDI,GUICookie);
2119 }
2120 CloseParenthesis = FALSE;
2121 break;
2122
2123
2124 case ELEMENT_TYPE_SZARRAY :
2125 numElements *= (unsigned)GET_UNALIGNED_VAL32(dataPtr);
2126 Reiterate = TRUE;
2127 sprintf_s(appendix,64,"[%d]",numElements);
2128 if(numElements == 0xFFFFFFFF)
2129 numElements = 0;
2130 dataPtr += 4;
2131 break;
2132
2133 case ELEMENT_TYPE_ARRAY :
2134 case ELEMENT_TYPE_VAR :
2135 case ELEMENT_TYPE_MVAR :
2136 case ELEMENT_TYPE_FNPTR :
2137 case ELEMENT_TYPE_GENERICINST :
2138 case ELEMENT_TYPE_TYPEDBYREF :
2139
2140#ifdef LOGGING
2141 case ELEMENT_TYPE_INTERNAL :
2142#endif // LOGGING
2143 return NULL;
2144
2145
2146 // Modifiers or depedent types
2147 case ELEMENT_TYPE_CMOD_OPT :
2148 case ELEMENT_TYPE_CMOD_REQD :
2149 case ELEMENT_TYPE_PINNED :
2150 Reiterate = TRUE;
2151 break;
2152
2153 case ELEMENT_TYPE_PTR :
2154 case ELEMENT_TYPE_BYREF :
2155 return NULL;
2156
2157 default:
2158 case ELEMENT_TYPE_SENTINEL :
2159 case ELEMENT_TYPE_END :
2160 _ASSERTE(!"Unknown Type");
2161 return NULL;
2162 } // end switch
2163 } while(Reiterate);
2164 if(CloseParenthesis) appendStr(out,")");
2165 return dataPtr;
2166}
2167#ifdef _PREFAST_
2168#pragma warning(pop)
2169#endif
2170
2171BOOL PrettyPrintCustomAttributeNVPairs(unsigned nPairs, BYTE* dataPtr, BYTE* dataEnd, CQuickBytes* out, void* GUICookie)
2172{
2173 IMDInternalImport *pIMDI = g_pImport; // ptr to IMDInternalImport class with ComSig
2174 while(dataPtr < dataEnd)
2175 {
2176 // field or property?
2177 switch(*dataPtr)
2178 {
2179 case SERIALIZATION_TYPE_FIELD:
2180 appendStr(out,KEYWORD("field "));
2181 break;
2182 case SERIALIZATION_TYPE_PROPERTY:
2183 appendStr(out,KEYWORD("property "));
2184 break;
2185 default:
2186 _ASSERTE(!"Invalid code of name/val pair in CA blob");
2187 return FALSE;
2188 }
2189 dataPtr++;
2190 if(dataPtr >= dataEnd)
2191 {
2192 _ASSERTE(!"CA blob too short");
2193 return FALSE;
2194 }
2195 // type of the field/property
2196 PCCOR_SIGNATURE dataTypePtr = (PCCOR_SIGNATURE)dataPtr;
2197 const char* szAppend = "";
2198 if(*dataPtr == ELEMENT_TYPE_SZARRAY) // Only SZARRAY modifier can occur in ser.type
2199 {
2200 szAppend = "[]";
2201 dataPtr++;
2202 }
2203 if(*dataPtr == SERIALIZATION_TYPE_TYPE)
2204 {
2205 appendStr(out,KEYWORD("type"));
2206 dataPtr++;
2207 }
2208 else if(*dataPtr == SERIALIZATION_TYPE_TAGGED_OBJECT)
2209 {
2210 appendStr(out,KEYWORD("object"));
2211 dataPtr++;
2212 }
2213 else if(*dataPtr == SERIALIZATION_TYPE_ENUM)
2214 {
2215 appendStr(out,KEYWORD("enum "));
2216 dataPtr++;
2217 unsigned Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
2218 if(dataPtr + Lstr > dataEnd) return FALSE;
2219 mdToken tk = ResolveReflectionNotation(dataPtr,Lstr,pIMDI,GUICookie);
2220 if(IsNilToken(tk))
2221 {
2222 appendStr(out,KEYWORD("class "));
2223 appendStr(out,"'");
2224 appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
2225 appendStr(out,"'");
2226 }
2227 else
2228 {
2229 PrettyPrintClass(out, tk, pIMDI);
2230 }
2231 dataPtr += Lstr;
2232 }
2233 else
2234 {
2235 szAppend = "";
2236 dataPtr = (BYTE*)PrettyPrintType(dataTypePtr, out, pIMDI);
2237 }
2238 if(*szAppend != 0)
2239 appendStr(out,szAppend);
2240 if(dataPtr >= dataEnd)
2241 {
2242 _ASSERTE(!"CA blob too short");
2243 return FALSE;
2244 }
2245 // name of the field/property
2246 unsigned Lstr = CorSigUncompressData((PCCOR_SIGNATURE&)dataPtr);
2247 if(dataPtr + Lstr > dataEnd) return FALSE;
2248 appendStr(out," '");
2249 appendStr(out,UnquotedProperName((char*)dataPtr,Lstr));
2250 appendStr(out,"' = ");
2251 dataPtr += Lstr;
2252 if(dataPtr >= dataEnd)
2253 {
2254 _ASSERTE(!"CA blob too short");
2255 return FALSE;
2256 }
2257 // value of the field/property
2258 dataPtr = PrettyPrintCABlobValue(dataTypePtr, dataPtr, dataEnd, out, pIMDI,GUICookie);
2259 if(NULL == dataPtr) return FALSE;
2260 appendStr(out,"\n");
2261
2262 nPairs--;
2263 }
2264 _ASSERTE(nPairs == 0);
2265 return TRUE;
2266}
2267BOOL PrettyPrintCustomAttributeBlob(mdToken tkType, BYTE* pBlob, ULONG ulLen, void* GUICookie, __inout __nullterminated char* szString)
2268{
2269 char* initszptr = szString + strlen(szString);
2270 PCCOR_SIGNATURE typePtr; // type to convert,
2271 ULONG typeLen; // the lenght of 'typePtr'
2272 CHECK_LOCAL_STATIC_VAR(static CQuickBytes out); // where to put the pretty printed string
2273
2274 IMDInternalImport *pIMDI = g_pImport; // ptr to IMDInternalImport class with ComSig
2275 unsigned numArgs = 0;
2276 unsigned numTyArgs = 0;
2277 PCCOR_SIGNATURE typeEnd;
2278 unsigned callConv;
2279 BYTE* dataPtr = pBlob;
2280 BYTE* dataEnd = dataPtr + ulLen;
2281 WORD wNumNVPairs = 0;
2282 unsigned numElements = 0;
2283
2284 if(TypeFromToken(tkType) == mdtMemberRef)
2285 {
2286 const char *szName_Ignore;
2287 if (FAILED(pIMDI->GetNameAndSigOfMemberRef(tkType,&typePtr,&typeLen, &szName_Ignore)))
2288 {
2289 return FALSE;
2290 }
2291 }
2292 else if(TypeFromToken(tkType) == mdtMethodDef)
2293 {
2294 if (FAILED(pIMDI->GetSigOfMethodDef(tkType, &typeLen, &typePtr)))
2295 {
2296 return FALSE;
2297 }
2298 }
2299 else
2300 return FALSE;
2301 typeEnd = typePtr + typeLen;
2302
2303 callConv = CorSigUncompressData(typePtr);
2304
2305 if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
2306 {
2307 numTyArgs = CorSigUncompressData(typePtr);
2308 return FALSE; // leave generic instantiations for later
2309 }
2310 numElements = numArgs = CorSigUncompressData(typePtr);
2311 out.Shrink(0);
2312 if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST))
2313 {
2314 // skip return type
2315 typePtr = PrettyPrintType(typePtr, &out, pIMDI);
2316 out.Shrink(0);
2317 }
2318 appendStr(&out," = {");
2319 dataPtr += 2; // skip blob prolog 0x0001
2320 // dump the arguments
2321 while(typePtr < typeEnd)
2322 {
2323 if (*typePtr == ELEMENT_TYPE_SENTINEL)
2324 {
2325 typePtr++;
2326 }
2327 else
2328 {
2329 if (numArgs <= 0)
2330 break;
2331 dataPtr = PrettyPrintCABlobValue(typePtr, dataPtr, dataEnd-2, &out, pIMDI,GUICookie);
2332 if(NULL == dataPtr) return FALSE;
2333 appendStr(&out,"\n");
2334 --numArgs;
2335 }
2336 }
2337 _ASSERTE(numArgs == 0);
2338 wNumNVPairs = (WORD)GET_UNALIGNED_VAL16(dataPtr);
2339 dataPtr+=2;
2340 numElements += wNumNVPairs;
2341 // arguments done, now to field/property name-val pairs
2342
2343 if(!PrettyPrintCustomAttributeNVPairs((unsigned) wNumNVPairs, dataPtr, dataEnd, &out, GUICookie))
2344 return FALSE;
2345
2346 {
2347 char* sz = asString(&out);
2348 char* ch = sz;
2349 char* szbl;
2350 while((ch = strchr(ch,'\n')))
2351 {
2352 *ch = 0;
2353 ch++;
2354 }
2355 // if the string is too long already, begin on next line
2356 if((initszptr - szString) > 80)
2357 {
2358 printLine(GUICookie,szString);
2359 sprintf_s(szString,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
2360 initszptr = &szString[strlen(szString)];
2361 }
2362 sprintf_s(initszptr,SZSTRING_REMAINING_SIZE(initszptr), "%s", sz);
2363 initszptr += 4; // to compensate for " = {"
2364 szbl = szString + strlen(g_szAsmCodeIndent);
2365 for(unsigned n = 1; n < numElements; n++)
2366 {
2367 printLine(GUICookie, szString);
2368 sz = sz + strlen(sz) + 1;
2369 for(ch = szbl; ch < initszptr; ch++) *ch = ' ';
2370 sprintf_s(initszptr,SZSTRING_REMAINING_SIZE(initszptr), "%s", sz);
2371 }
2372 }
2373 strcat_s(initszptr, SZSTRING_REMAINING_SIZE(initszptr),"}");
2374 if(g_fShowBytes)
2375 {
2376 printLine(GUICookie,szString);
2377 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," // ");
2378 sprintf_s(szString,SZSTRING_SIZE,"%s = ( ",g_szAsmCodeIndent);
2379 DumpByteArray(szString,pBlob,ulLen,GUICookie);
2380 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-8] = 0;
2381 }
2382 return TRUE;
2383}
2384
2385void DumpCustomAttributeProps(mdToken tkCA, mdToken tkType, mdToken tkOwner, BYTE* pBlob, ULONG ulLen, void *GUICookie, bool bWithOwner)
2386{
2387 char* szptr = &szString[0];
2388 BOOL fCommentItOut = FALSE;
2389 if((TypeFromToken(tkType) == mdtMemberRef)||(TypeFromToken(tkType) == mdtMethodDef))
2390 {
2391 mdToken tkParent;
2392 const char * pszClassName = NULL;
2393 const char * pszNamespace = NULL;
2394 if (TypeFromToken(tkType) == mdtMemberRef)
2395 {
2396 if (FAILED(g_pImport->GetParentOfMemberRef(tkType, &tkParent)))
2397 {
2398 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid MemberRef %08X record ", tkType);
2399 return;
2400 }
2401 }
2402 else
2403 {
2404 if (FAILED(g_pImport->GetParentToken(tkType, &tkParent)))
2405 {
2406 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid token %08X ", tkType);
2407 return;
2408 }
2409 }
2410
2411 REGISTER_REF(tkOwner,tkType); // owner of the CA references the class amd method
2412 REGISTER_REF(tkOwner,tkParent);
2413
2414 if (TypeFromToken(tkParent) == mdtTypeDef)
2415 {
2416 if (FAILED(g_pImport->GetNameOfTypeDef(tkParent, &pszClassName, &pszNamespace)))
2417 {
2418 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid TypeDef %08X record ", tkParent);
2419 return;
2420 }
2421 }
2422 else if (TypeFromToken(tkParent) == mdtTypeRef)
2423 {
2424 if (FAILED(g_pImport->GetNameOfTypeRef(tkParent, &pszNamespace, &pszClassName)))
2425 {
2426 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "Invalid TypeRef %08X record ", tkParent);
2427 return;
2428 }
2429 }
2430 if(pszClassName && pszNamespace
2431 && (strcmp(pszNamespace,"System.Diagnostics") == 0)
2432 && (strcmp(pszClassName,"DebuggableAttribute") == 0)) fCommentItOut = TRUE;
2433
2434
2435 }
2436 if(fCommentItOut)
2437 {
2438 printLine(GUICookie,COMMENT((char*)0)); // start multiline comment
2439 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_AUTOCA),g_szAsmCodeIndent);
2440 printLine(GUICookie, szString);
2441 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH,"// ");
2442 }
2443 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".custom"));
2444 if(bWithOwner)
2445 {
2446 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkCA);
2447 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(");
2448 switch(TypeFromToken(tkOwner))
2449 {
2450 case mdtTypeDef :
2451 case mdtTypeRef :
2452 case mdtTypeSpec:
2453 PrettyPrintToken(szString, tkOwner, g_pImport,GUICookie,0);
2454 break;
2455
2456 case mdtMemberRef:
2457 {
2458 PCCOR_SIGNATURE typePtr;
2459 const char* pszMemberName;
2460 ULONG cComSig;
2461
2462 if (FAILED(g_pImport->GetNameAndSigOfMemberRef(
2463 tkOwner,
2464 &typePtr,
2465 &cComSig,
2466 &pszMemberName)))
2467 {
2468 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"ERROR ");
2469 break;
2470 }
2471 unsigned callConv = CorSigUncompressData(typePtr);
2472
2473 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
2474 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
2475 else
2476 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
2477 PrettyPrintToken(szString, tkOwner, g_pImport,GUICookie,0);
2478 }
2479 break;
2480
2481 case mdtMethodDef:
2482 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("method "));
2483 PrettyPrintToken(szString, tkOwner, g_pImport,GUICookie,0);
2484 break;
2485
2486 default :
2487 strcat_s(szptr, SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("UNKNOWN_OWNER"));
2488 break;
2489 }
2490 szptr = &szString[strlen(szString)];
2491 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkOwner);
2492 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
2493 }
2494 else
2495 {
2496 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X:%08X*/ "),tkCA,tkType);
2497 }
2498 switch(TypeFromToken(tkType))
2499 {
2500 case mdtTypeDef :
2501 case mdtTypeRef :
2502 case mdtMemberRef:
2503 case mdtMethodDef:
2504 PrettyPrintToken(szString, tkType, g_pImport,GUICookie,0);
2505 break;
2506
2507 default :
2508 strcat_s(szString, SZSTRING_SIZE,ERRORMSG("UNNAMED_CUSTOM_ATTR"));
2509 break;
2510 }
2511 szptr = &szString[strlen(szString)];
2512
2513 if(pBlob && ulLen)
2514 {
2515 if(!g_fCAVerbal || !PrettyPrintCustomAttributeBlob(tkType, pBlob, ulLen, GUICookie, szString))
2516 {
2517 sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = ( ");
2518 DumpByteArray(szString,pBlob,ulLen,GUICookie);
2519 }
2520 }
2521 printLine(GUICookie, szString);
2522 if(fCommentItOut)
2523 {
2524 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-4] = 0;
2525 printLine(GUICookie,COMMENT((char*)-1)); // end multiline comment
2526 }
2527}
2528
2529void DumpCustomAttribute(mdCustomAttribute tkCA, void *GUICookie, bool bWithOwner)
2530{
2531 mdToken tkType;
2532 BYTE* pBlob=NULL;
2533 ULONG ulLen=0;
2534 mdToken tkOwner;
2535 static mdToken tkMod = 0xFFFFFFFF;
2536
2537 _ASSERTE((TypeFromToken(tkCA)==mdtCustomAttribute)&&(RidFromToken(tkCA)>0));
2538 _ASSERTE(RidFromToken(tkCA) <= g_uNCA);
2539 if(tkMod == 0xFFFFFFFF) tkMod = g_pImport->GetModuleFromScope();
2540
2541 // can't use InternalImport here: need the tkOwner
2542 if (FAILED(g_pPubImport->GetCustomAttributeProps( // S_OK or error.
2543 tkCA, // [IN] CustomValue token.
2544 &tkOwner, // [OUT, OPTIONAL] Object token.
2545 &tkType, // [OUT, OPTIONAL] Put TypeDef/TypeRef token here.
2546 (const void **)&pBlob, // [OUT, OPTIONAL] Put pointer to data here.
2547 &ulLen))) // [OUT, OPTIONAL] Put size of date here.
2548 {
2549 return;
2550 }
2551
2552 if(!RidFromToken(tkOwner)) return;
2553
2554 DWORD i;
2555 for(i = 0; i < g_NumTypedefs; i++)
2556 {
2557 TypeDefDescr* pTDD = &((*g_typedefs)[i]);
2558 if(TypeFromToken(pTDD->tkTypeSpec) == mdtCustomAttribute)
2559 {
2560 mdToken tkTypeTD;
2561 mdToken tkOwnerTD;
2562 BYTE* pBlobTD=NULL;
2563 ULONG uLenTD=0;
2564 tkTypeTD = GET_UNALIGNED_VAL32(pTDD->psig);
2565 if(tkTypeTD != tkType) continue;
2566
2567 tkOwnerTD = GET_UNALIGNED_VAL32(pTDD->psig + sizeof(mdToken));
2568 if(pTDD->cb > 2*sizeof(mdToken))
2569 {
2570 pBlobTD = (BYTE*)pTDD->psig + 2*sizeof(mdToken);
2571 uLenTD = pTDD->cb - 2*sizeof(mdToken);
2572 }
2573 if(uLenTD != ulLen) continue;
2574 if(memcmp(pBlobTD,pBlob,ulLen) != 0) continue;
2575 char* szptr = &szString[0];
2576 szString[0] = 0;
2577 szptr += sprintf_s(szString,SZSTRING_SIZE,"%s%s", g_szAsmCodeIndent,JUMPPT(ProperName(pTDD->szName),pTDD->tkSelf));
2578 if(g_fDumpTokens)
2579 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkCA);
2580 printLine(GUICookie,szString);
2581 break;
2582 }
2583 }
2584 if(i >= g_NumTypedefs)
2585 DumpCustomAttributeProps(tkCA,tkType,tkOwner,pBlob,ulLen,GUICookie,bWithOwner);
2586 _ASSERTE(g_rchCA);
2587 _ASSERTE(RidFromToken(tkCA) <= g_uNCA);
2588 g_rchCA[RidFromToken(tkCA)] = 1;
2589}
2590
2591void DumpCustomAttributes(mdToken tkOwner, void *GUICookie)
2592{
2593 if (g_fShowCA)
2594 {
2595 HENUMInternal hEnum;
2596 mdCustomAttribute tkCA;
2597
2598 if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, tkOwner,&hEnum)))
2599 {
2600 return;
2601 }
2602 while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
2603 {
2604 DumpCustomAttribute(tkCA,GUICookie,false);
2605 }
2606 g_pImport->EnumClose( &hEnum);
2607 }
2608}
2609
2610void DumpDefaultValue(mdToken tok, __inout __nullterminated char* szString, void* GUICookie)
2611{
2612 MDDefaultValue MDDV;
2613 char* szptr = &szString[strlen(szString)];
2614
2615 if (FAILED(g_pImport->GetDefaultValue(tok, &MDDV)))
2616 {
2617 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), ERRORMSG(" /* Invalid default value for %08X: */"), tok);
2618 return;
2619 }
2620 switch(MDDV.m_bType)
2621 {
2622 case ELEMENT_TYPE_VOID:
2623 strcat_s(szString, SZSTRING_SIZE," /* NO CORRESPONDING RECORD IN CONSTANTS TABLE */");
2624 break;
2625 case ELEMENT_TYPE_I1:
2626 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%02X)",KEYWORD("int8"),MDDV.m_byteValue);
2627 break;
2628 case ELEMENT_TYPE_U1:
2629 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%02X)",KEYWORD("uint8"),MDDV.m_byteValue);
2630 break;
2631 case ELEMENT_TYPE_I2:
2632 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%04X)",KEYWORD("int16"),MDDV.m_usValue);
2633 break;
2634 case ELEMENT_TYPE_U2:
2635 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%04X)",KEYWORD("uint16"),MDDV.m_usValue);
2636 break;
2637 case ELEMENT_TYPE_I4:
2638 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%08X)",KEYWORD("int32"),MDDV.m_ulValue);
2639 break;
2640 case ELEMENT_TYPE_U4:
2641 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%08X)",KEYWORD("uint32"),MDDV.m_ulValue);
2642 break;
2643 case ELEMENT_TYPE_CHAR:
2644 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%04X)",KEYWORD("char"),MDDV.m_usValue);
2645 break;
2646 case ELEMENT_TYPE_BOOLEAN:
2647 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s",KEYWORD("bool"));
2648 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(%s)", KEYWORD((char *)(MDDV.m_byteValue ? "true" : "false")));
2649 break;
2650 case ELEMENT_TYPE_I8:
2651 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%I64X)",KEYWORD("int64"),MDDV.m_ullValue);
2652 break;
2653 case ELEMENT_TYPE_U8:
2654 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(0x%I64X)",KEYWORD("uint64"),MDDV.m_ullValue);
2655 break;
2656 case ELEMENT_TYPE_R4:
2657 {
2658 char szf[32];
2659 _gcvt_s(szf,32,MDDV.m_fltValue, 8);
2660 float df = (float)atof(szf);
2661 // Must compare as underlying bytes, not floating point otherwise optmizier will
2662 // try to enregister and comapre 80-bit precision number with 32-bit precision number!!!!
2663 if((*(ULONG*)&df == MDDV.m_ulValue)&&!IsSpecialNumber(szf))
2664 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(%s)",KEYWORD("float32"),szf);
2665 else
2666 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " = %s(0x%08X)",KEYWORD("float32"),MDDV.m_ulValue);
2667
2668 }
2669 break;
2670 case ELEMENT_TYPE_R8:
2671 {
2672 char szf[32], *pch;
2673 _gcvt_s(szf,32,MDDV.m_dblValue, 17);
2674 double df = strtod(szf, &pch); //atof(szf);
2675 szf[31]=0;
2676 // Must compare as underlying bytes, not floating point otherwise optmizier will
2677 // try to enregister and comapre 80-bit precision number with 64-bit precision number!!!!
2678 if((*(ULONGLONG*)&df == MDDV.m_ullValue)&&!IsSpecialNumber(szf))
2679 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s(%s)",KEYWORD("float64"),szf);
2680 else
2681 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " = %s(0x%I64X) // %s",KEYWORD("float64"),MDDV.m_ullValue,szf);
2682 }
2683 break;
2684
2685 case ELEMENT_TYPE_STRING:
2686 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = ");
2687 PAL_CPP_TRY {
2688 szptr = DumpUnicodeString(GUICookie,szString,(WCHAR*)MDDV.m_wzValue,MDDV.m_cbSize/sizeof(WCHAR));
2689 } PAL_CPP_CATCH_ALL {
2690 strcat_s(szString, SZSTRING_SIZE,ERRORMSG("INVALID DATA ADDRESS"));
2691 } PAL_CPP_ENDTRY;
2692 break;
2693
2694 case ELEMENT_TYPE_CLASS:
2695 if(MDDV.m_wzValue==NULL)
2696 {
2697 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = %s",KEYWORD("nullref"));
2698 break;
2699 }
2700 //else fall thru to default case, to report the error
2701
2702 default:
2703 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" /* ILLEGAL CONSTANT type:0x%02X, size:%d bytes, blob: "),MDDV.m_bType,MDDV.m_cbSize);
2704 if(MDDV.m_wzValue)
2705 {
2706 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(");
2707 PAL_CPP_TRY {
2708 DumpByteArray(szString,(BYTE*)MDDV.m_wzValue,MDDV.m_cbSize,GUICookie);
2709 } PAL_CPP_CATCH_ALL {
2710 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" Invalid blob at 0x%08X)"), MDDV.m_wzValue);
2711 } PAL_CPP_ENDTRY
2712 }
2713 else
2714 {
2715 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"NULL");
2716 }
2717 strcat_s(szString, SZSTRING_REMAINING_SIZE(szptr), " */");
2718 break;
2719 }
2720}
2721
2722void DumpParams(ParamDescriptor* pPD, ULONG ulParams, void* GUICookie)
2723{
2724 if(pPD)
2725 {
2726 for(ULONG i = ulParams; i<2*ulParams+1; i++) // pPD[ulParams] is return value
2727 {
2728 ULONG j = i % (ulParams+1);
2729 if(RidFromToken(pPD[j].tok))
2730 {
2731 HENUMInternal hEnum;
2732 mdCustomAttribute tkCA;
2733 ULONG ulCAs= 0;
2734
2735 if(g_fShowCA)
2736 {
2737 if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, pPD[j].tok, &hEnum)))
2738 {
2739 sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MetaData error enumerating CustomAttribute for %08X", g_szAsmCodeIndent, pPD[j].tok);
2740 printLine(GUICookie, szString);
2741 continue;
2742 }
2743 ulCAs = g_pImport->EnumGetCount(&hEnum);
2744 }
2745 if(ulCAs || IsPdHasDefault(pPD[j].attr))
2746 {
2747 char *szptr = &szString[0];
2748 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s [%d]",g_szAsmCodeIndent,KEYWORD(".param"),i-ulParams);
2749 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),pPD[j].tok);
2750 if(IsPdHasDefault(pPD[j].attr)) DumpDefaultValue(pPD[j].tok, szString, GUICookie);
2751 printLine(GUICookie, szString);
2752 if(ulCAs)
2753 {
2754 while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
2755 {
2756 DumpCustomAttribute(tkCA,GUICookie,false);
2757 }
2758 }
2759 }
2760 if(g_fShowCA) g_pImport->EnumClose( &hEnum);
2761 }
2762 }
2763 }
2764}
2765
2766BOOL DumpPermissionSetBlob(void* GUICookie,__inout __nullterminated char* szString, BYTE* pvPermission, ULONG cbPermission)
2767{
2768 if(*pvPermission == '.')
2769 {
2770 CQuickBytes out;
2771 pvPermission++;
2772 char* szptr_init = &szString[strlen(szString)];
2773 char* szptr = szptr_init;
2774 appendStr(&out," = {");
2775 unsigned nAttrs = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission);
2776 for(unsigned iAttr = 0; iAttr < nAttrs; iAttr++)
2777 {
2778 unsigned L = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission); // class name length
2779 mdToken tkAttr = ResolveReflectionNotation(pvPermission,L,g_pImport,GUICookie);
2780 if(IsNilToken(tkAttr))
2781 {
2782 appendStr(&out,KEYWORD("class "));
2783 appendStr(&out,"'");
2784 appendStr(&out,UnquotedProperName((char*)pvPermission,L));
2785 appendStr(&out,"'");
2786 }
2787 else
2788 {
2789 PrettyPrintClass(&out, tkAttr, g_pImport);
2790 }
2791 pvPermission += L;
2792 appendStr(&out," = {");
2793 // dump blob
2794 L = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission); // blob length
2795 if(L > 0)
2796 {
2797 BYTE* pvEnd = pvPermission+L;
2798 L = CorSigUncompressData((PCCOR_SIGNATURE&)pvPermission); // number of props
2799 if(L > 0)
2800 {
2801 if(!PrettyPrintCustomAttributeNVPairs(L, pvPermission, pvEnd, &out, GUICookie))
2802 return FALSE;
2803 out.Shrink(out.Size()-1);
2804 }
2805 pvPermission = pvEnd;
2806 }
2807 appendStr(&out, iAttr == nAttrs-1 ? "}" : "}, ");
2808 }
2809 appendStr(&out, "}");
2810 char* sz = asString(&out);
2811 while(char* pc = strstr(sz,"}, "))
2812 {
2813 *(pc+2) = 0;
2814 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), sz);
2815 printLine(GUICookie,szString);
2816 sz = pc+3;
2817 if(szptr == szptr_init) szptr += 4; // to compensate for = {
2818 for(pc = szString; pc < szptr; pc++) *pc = ' ';
2819 }
2820 strcpy_s(szptr, SZSTRING_REMAINING_SIZE(szptr),sz);
2821 return TRUE;
2822 }
2823 return FALSE;
2824}
2825
2826void DumpPermissions(mdToken tkOwner, void* GUICookie)
2827{
2828 HCORENUM hEnum = NULL;
2829 static mdPermission rPerm[16384];
2830 ULONG count;
2831 HRESULT hr;
2832 //static char szString[4096];
2833
2834 // can't use internal import here: EnumInit not impl. for mdtPrmission
2835 while (SUCCEEDED(hr = g_pPubImport->EnumPermissionSets( &hEnum,
2836 tkOwner, 0, rPerm, 16384, &count)) &&
2837 count > 0)
2838 {
2839 for (ULONG i = 0; i < count; i++)
2840 {
2841 DWORD dwAction;
2842 const BYTE *pvPermission=NULL;
2843 ULONG cbPermission=0;
2844 const char *szAction;
2845 char *szptr;
2846
2847 szptr = &szString[0];
2848 if(SUCCEEDED(hr = g_pPubImport->GetPermissionSetProps( rPerm[i], &dwAction,
2849 (const void**)&pvPermission, &cbPermission)))
2850 {
2851 szptr += sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".permissionset"));
2852 switch(dwAction)
2853 {
2854 case dclActionNil: szAction = ""; break;
2855 case dclRequest: szAction = KEYWORD("request"); break;
2856 case dclDemand: szAction = KEYWORD("demand"); break;
2857 case dclAssert: szAction = KEYWORD("assert"); break;
2858 case dclDeny: szAction = KEYWORD("deny"); break;
2859 case dclPermitOnly: szAction = KEYWORD("permitonly"); break;
2860 case dclLinktimeCheck: szAction = KEYWORD("linkcheck"); break;
2861 case dclInheritanceCheck: szAction = KEYWORD("inheritcheck"); break;
2862 case dclRequestMinimum: szAction = KEYWORD("reqmin"); break;
2863 case dclRequestOptional: szAction = KEYWORD("reqopt"); break;
2864 case dclRequestRefuse: szAction = KEYWORD("reqrefuse"); break;
2865 case dclPrejitGrant: szAction = KEYWORD("prejitgrant"); break;
2866 case dclPrejitDenied: szAction = KEYWORD("prejitdeny"); break;
2867 case dclNonCasDemand: szAction = KEYWORD("noncasdemand"); break;
2868 case dclNonCasLinkDemand: szAction = KEYWORD("noncaslinkdemand"); break;
2869 case dclNonCasInheritance: szAction = KEYWORD("noncasinheritance"); break;
2870 default: szAction = ERRORMSG("<UNKNOWN_ACTION>"); break;
2871 }
2872 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),szAction);
2873 if(pvPermission && cbPermission)
2874 {
2875 printLine(GUICookie, szString);
2876 sprintf_s(szString,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
2877 if(!DumpPermissionSetBlob(GUICookie,szString,(BYTE*)pvPermission,cbPermission))
2878 {
2879 strcat_s(szString,SZSTRING_SIZE,KEYWORD("bytearray"));
2880 strcat_s(szString,SZSTRING_SIZE," (");
2881 DumpByteArray(szString, pvPermission, cbPermission, GUICookie);
2882 }
2883 printLine(GUICookie,szString);
2884 }
2885 else // i.e. if pvPermission == NULL or cbPermission == NULL
2886 {
2887 sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," = ()");
2888 printLine(GUICookie,szString);
2889 }
2890 DumpCustomAttributes(rPerm[i],GUICookie);
2891 }// end if(GetPermissionProps)
2892 } // end for(all permissions)
2893 }//end while(EnumPermissionSets)
2894 g_pPubImport->CloseEnum( hEnum);
2895}
2896
2897void PrettyPrintMethodSig(__inout __nullterminated char* szString, unsigned* puStringLen, CQuickBytes* pqbMemberSig, PCCOR_SIGNATURE pComSig, ULONG cComSig,
2898 __inout __nullterminated char* buff, __in_opt __nullterminated char* szArgPrefix, void* GUICookie)
2899{
2900 unsigned uMaxWidth = 40;
2901 if(g_fDumpHTML || g_fDumpRTF) uMaxWidth = 240;
2902 if(*buff && (strlen(szString) > (size_t)uMaxWidth))
2903 {
2904 printLine(GUICookie,szString);
2905 strcpy_s(szString,SZSTRING_SIZE,g_szAsmCodeIndent);
2906 strcat_s(szString,SZSTRING_SIZE," "); // to align with ".method "
2907 }
2908 appendStr(pqbMemberSig, szString);
2909 {
2910 char* pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, buff, pqbMemberSig, g_pImport, szArgPrefix);
2911 if(*buff)
2912 {
2913 size_t L = strlen(pszTailSig);
2914 char* newbuff = new char[strlen(buff)+3];
2915 sprintf_s(newbuff,strlen(buff)+3," %s(", buff);
2916 char* pszOffset = strstr(pszTailSig,newbuff);
2917 if(pszOffset)
2918 {
2919 char* pszTailSigRemainder = new char[L+1];
2920 if(pszOffset - pszTailSig > (int)uMaxWidth)
2921 {
2922 char* pszOffset2 = strstr(pszTailSig," marshal(");
2923 if(pszOffset2 && (pszOffset2 < pszOffset))
2924 {
2925 *pszOffset2 = 0;
2926 strcpy_s(pszTailSigRemainder,L,pszOffset2+1);
2927 printLine(GUICookie,pszTailSig);
2928 strcpy_s(pszTailSig,L,g_szAsmCodeIndent);
2929 strcat_s(pszTailSig,L," "); // to align with ".method "
2930 strcat_s(pszTailSig,L,pszTailSigRemainder);
2931 pszOffset = strstr(pszTailSig,newbuff);
2932 }
2933 *pszOffset = 0 ;
2934 strcpy_s(pszTailSigRemainder,L,pszOffset+1);
2935 printLine(GUICookie,pszTailSig);
2936 strcpy_s(pszTailSig,L,g_szAsmCodeIndent);
2937 strcat_s(pszTailSig,L," "); // to align with ".method "
2938 strcat_s(pszTailSig,L,pszTailSigRemainder);
2939 pszOffset = strstr(pszTailSig,newbuff);
2940 }
2941 size_t i, j, k, l, indent = pszOffset - pszTailSig + strlen(buff) + 2;
2942 char chAfterComma;
2943 char *pComma = pszTailSig+strlen(buff), *pch;
2944 while((pComma = strchr(pComma,',')))
2945 {
2946 for(pch = pszTailSig, i=0, j = 0, k=0, l=0; pch < pComma; pch++)
2947 {
2948 if(*pch == '\\') pch++;
2949 else
2950 {
2951 if(*pch == '\'') j=1-j;
2952 else if(*pch == '\"') k=1-k;
2953 else if(j==0)
2954 {
2955 if(*pch == '[') i++;
2956 else if(*pch == ']') i--;
2957 else if(strncmp(pch,LTN(),strlen(LTN()))==0) l++;
2958 else if(strncmp(pch,GTN(),strlen(GTN()))==0) l--;
2959 }
2960 }
2961 }
2962 pComma++;
2963 if((i==0)&&(j==0)&&(k==0)&&(l==0))// no brackets/quotes or all opened/closed
2964 {
2965 chAfterComma = *pComma;
2966 strcpy_s(pszTailSigRemainder,L,pComma);
2967 *pComma = 0;
2968 printLine(GUICookie,pszTailSig);
2969 *pComma = chAfterComma;
2970 for(i=0; i<indent; i++) pszTailSig[i] = ' ';
2971 strcpy_s(&pszTailSig[indent],L-indent,pszTailSigRemainder);
2972 pComma = pszTailSig;
2973 }
2974 }
2975 if(*puStringLen < (unsigned)strlen(pszTailSig)+128)
2976 {
2977 //free(szString);
2978 *puStringLen = (unsigned)strlen(pszTailSig)+128; // need additional space for "il managed" etc.
2979 //szString = (char*)malloc(*puStringLen);
2980 }
2981 VDELETE(pszTailSigRemainder);
2982 }
2983 strcpy_s(szString,SZSTRING_SIZE,pszTailSig);
2984 VDELETE(newbuff);
2985 }
2986 else // it's for GUI, don't split it into several lines
2987 {
2988 size_t L = strlen(szString);
2989 if(L < 2048)
2990 {
2991 L = 2048-L;
2992 strncpy_s(szString,SZSTRING_SIZE,pszTailSig,L);
2993 }
2994 }
2995 }
2996}
2997// helper to avoid mixing of SEH and stack objects with destructors
2998BOOL DisassembleWrapper(IMDInternalImport *pImport, BYTE *ILHeader,
2999 void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs)
3000{
3001 BOOL fRet = FALSE;
3002 //char szString[4096];
3003
3004 PAL_CPP_TRY
3005 {
3006 fRet = Disassemble(pImport, ILHeader, GUICookie, FuncToken, pszArgname, ulArgs);
3007 }
3008 PAL_CPP_CATCH_ALL
3009 {
3010 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_DASMERR),g_szAsmCodeIndent);
3011 printLine(GUICookie, szString);
3012 }
3013 PAL_CPP_ENDTRY
3014
3015 return fRet;
3016}
3017
3018BOOL PrettyPrintGP( // prints name of generic param, or returns FALSE
3019 mdToken tkOwner, // Class, method or 0
3020 CQuickBytes *out, // where to put the pretty printed generic param
3021 int n) // Index of generic param
3022{
3023 BOOL ret = FALSE;
3024 if(tkOwner && ((TypeFromToken(tkOwner)==mdtTypeDef)||(TypeFromToken(tkOwner)==mdtMethodDef)))
3025 {
3026 DWORD NumTyPars;
3027 HENUMInternal hEnumTyPar;
3028
3029 if(SUCCEEDED(g_pImport->EnumInit(mdtGenericParam,tkOwner,&hEnumTyPar)))
3030 {
3031 NumTyPars = g_pImport->EnumGetCount(&hEnumTyPar);
3032 if(NumTyPars > (DWORD)n)
3033 {
3034 // need this for name dup check
3035 LPCSTR *pszName = new LPCSTR[NumTyPars];
3036 if(pszName != NULL)
3037 {
3038 ULONG ulSequence;
3039 DWORD ix,nx;
3040 mdToken tk;
3041 for(ix = 0, nx = 0xFFFFFFFF; ix < NumTyPars; ix++)
3042 {
3043 if(g_pImport->EnumNext(&hEnumTyPar,&tk))
3044 {
3045 if(SUCCEEDED(g_pImport->GetGenericParamProps(tk,&ulSequence,NULL,NULL,NULL,&pszName[ix])))
3046 {
3047 if(ulSequence == (ULONG)n)
3048 nx = ix;
3049 }
3050 }
3051 }
3052 // if there are dup names, use !0 or !!0
3053 if(nx != 0xFFFFFFFF)
3054 {
3055 for(ix = 0; ix < nx; ix++)
3056 {
3057 if(strcmp(pszName[ix],pszName[nx]) == 0)
3058 break;
3059 }
3060 if(ix >= nx)
3061 {
3062 for(ix = nx+1; ix < NumTyPars; ix++)
3063 {
3064 if(strcmp(pszName[ix],pszName[nx]) == 0)
3065 break;
3066 }
3067 if(ix >= NumTyPars)
3068 {
3069 appendStr(out, ProperName((char*)(pszName[nx])));
3070 ret = TRUE;
3071 }
3072 }
3073 } // end if(tkTyPar != 0)
3074 delete [] pszName;
3075 } // end if(pszName != NULL)
3076 } // end if(NumTyPars > (DWORD)n)
3077 } // end if(SUCCEEDED(g_pImport->EnumInit(mdtGenericParam,tkOwner,&hEnumTyPar)))
3078 g_pImport->EnumClose(&hEnumTyPar);
3079 } // end if(tkOwner)
3080 return ret;
3081}
3082
3083// Pretty-print formal type parameters for a class or method
3084char *DumpGenericPars(__inout_ecount(SZSTRING_SIZE) char* szString, mdToken tok, void* GUICookie/*=NULL*/, BOOL fSplit/*=FALSE*/)
3085{
3086 WCHAR *wzArgName = wzUniBuf;
3087 ULONG chName;
3088 mdToken tkConstr[2048];
3089
3090 DWORD NumTyPars;
3091 DWORD NumConstrs;
3092 mdGenericParam tkTyPar;
3093 DWORD attr;
3094 HCORENUM hEnumTyPar = NULL;
3095 HCORENUM hEnumTyParConstr = NULL;
3096 char* szptr = &szString[strlen(szString)];
3097 char* szbegin;
3098 unsigned i;
3099
3100 if (FAILED(g_pPubImport->EnumGenericParams(&hEnumTyPar, tok, &tkTyPar, 1, &NumTyPars)))
3101 return NULL;
3102 if (NumTyPars > 0)
3103 {
3104 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),LTN());
3105 szbegin = szptr;
3106
3107 for (i = 1; NumTyPars != 0; i++)
3108 {
3109 g_pPubImport->GetGenericParamProps(tkTyPar, NULL, &attr, NULL, NULL, wzArgName, UNIBUF_SIZE/2, &chName);
3110 //if(wcslen(wzArgName) >= MAX_CLASSNAME_LENGTH)
3111 // wzArgName[MAX_CLASSNAME_LENGTH-1] = 0;
3112 hEnumTyParConstr = NULL;
3113 if (FAILED(g_pPubImport->EnumGenericParamConstraints(&hEnumTyParConstr, tkTyPar, tkConstr, 2048, &NumConstrs)))
3114 {
3115 g_pPubImport->CloseEnum(hEnumTyPar);
3116 return NULL;
3117 }
3118 *szptr = 0;
3119 CHECK_REMAINING_SIZE;
3120 switch (attr & gpVarianceMask)
3121 {
3122 case gpCovariant : szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "+ "); break;
3123 case gpContravariant : szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "- "); break;
3124 }
3125 CHECK_REMAINING_SIZE;
3126 if ((attr & gpReferenceTypeConstraint) != 0)
3127 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "class ");
3128 CHECK_REMAINING_SIZE;
3129 if ((attr & gpNotNullableValueTypeConstraint) != 0)
3130 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "valuetype ");
3131 CHECK_REMAINING_SIZE;
3132 if ((attr & gpDefaultConstructorConstraint) != 0)
3133 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ".ctor ");
3134 CHECK_REMAINING_SIZE;
3135 if (NumConstrs)
3136 {
3137 CQuickBytes out;
3138 mdToken tkConstrType,tkOwner;
3139 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"(");
3140 DWORD ix;
3141 for (ix=0; ix<NumConstrs; ix++)
3142 {
3143 if (FAILED(g_pPubImport->GetGenericParamConstraintProps(tkConstr[ix], &tkOwner, &tkConstrType)))
3144 return NULL;
3145
3146 if(ix) szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),", ");
3147 CHECK_REMAINING_SIZE;
3148 out.Shrink(0);
3149 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",PrettyPrintClass(&out,tkConstrType,g_pImport));
3150 CHECK_REMAINING_SIZE;
3151 }
3152 if(ix < NumConstrs) break;
3153 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
3154 CHECK_REMAINING_SIZE;
3155 }
3156 // re-get name, wzUniBuf may not contain it any more
3157 g_pPubImport->GetGenericParamProps(tkTyPar, NULL, &attr, NULL, NULL, wzArgName, UNIBUF_SIZE/2, &chName);
3158 //if(wcslen(wzArgName) >= MAX_CLASSNAME_LENGTH)
3159 // wzArgName[MAX_CLASSNAME_LENGTH-1] = 0;
3160 if (chName)
3161 {
3162 char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
3163 WszWideCharToMultiByte(CP_UTF8,0,wzArgName,-1,sz,UNIBUF_SIZE,NULL,NULL);
3164 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",ProperName(sz));
3165 }
3166 CHECK_REMAINING_SIZE;
3167 if (FAILED(g_pPubImport->EnumGenericParams(&hEnumTyPar, tok, &tkTyPar, 1, &NumTyPars)))
3168 return NULL;
3169 if (NumTyPars != 0)
3170 {
3171 *szptr++ = ',';
3172
3173 if(fSplit && (i == 4))
3174 {
3175 *szptr = 0;
3176 printLine(GUICookie,szString);
3177 i = 0; // mind i++ at the end of the loop
3178 for(szptr = szString; szptr < szbegin; szptr++) *szptr = ' ';
3179 }
3180 }
3181 } // end for (i = 1; NumTyPars != 0; i++)
3182 if(NumTyPars != 0) // all type parameters can't fit in szString, error
3183 {
3184 strcpy_s(szptr,4,"...");
3185 szptr += 3;
3186 }
3187 else
3188 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),GTN());
3189 } // end if (NumTyPars > 0)
3190 *szptr = 0;
3191 if(hEnumTyPar) g_pPubImport->CloseEnum(hEnumTyPar);
3192 return szptr;
3193}
3194
3195void DumpGenericParsCA(mdToken tok, void* GUICookie/*=NULL*/)
3196{
3197 DWORD NumTyPars;
3198 mdGenericParam tkTyPar;
3199 HCORENUM hEnumTyPar = NULL;
3200 unsigned i;
3201 WCHAR *wzArgName = wzUniBuf;
3202 ULONG chName;
3203 DWORD attr;
3204
3205 if(g_fShowCA)
3206 {
3207 for(i=0; SUCCEEDED(g_pPubImport->EnumGenericParams(&hEnumTyPar, tok, &tkTyPar, 1, &NumTyPars))
3208 &&(NumTyPars > 0); i++)
3209 {
3210 HENUMInternal hEnum;
3211 mdCustomAttribute tkCA;
3212 ULONG ulCAs= 0;
3213
3214 if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, tkTyPar, &hEnum)))
3215 {
3216 sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MetaData error enumerating CustomAttribute for %08X", g_szAsmCodeIndent, tkTyPar);
3217 printLine(GUICookie, szString);
3218 return;
3219 }
3220 ulCAs = g_pImport->EnumGetCount(&hEnum);
3221 if(ulCAs)
3222 {
3223 char *szptr = &szString[0];
3224 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".param type"));
3225 if(SUCCEEDED(g_pPubImport->GetGenericParamProps(tkTyPar, NULL, &attr, NULL, NULL, wzArgName, UNIBUF_SIZE/2, &chName))
3226 &&(chName > 0))
3227 {
3228 //if(wcslen(wzArgName) >= MAX_CLASSNAME_LENGTH)
3229 // wzArgName[MAX_CLASSNAME_LENGTH-1] = 0;
3230 char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
3231 WszWideCharToMultiByte(CP_UTF8,0,wzArgName,-1,sz,UNIBUF_SIZE,NULL,NULL);
3232 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",ProperName(sz));
3233 }
3234 else
3235 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"[%d] ",i+1);
3236 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),tkTyPar);
3237 printLine(GUICookie, szString);
3238 while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
3239 {
3240 DumpCustomAttribute(tkCA,GUICookie,false);
3241 }
3242 }
3243 g_pImport->EnumClose( &hEnum);
3244 } //end for(i=0;...
3245 } //end if(g_fShowCA)
3246}
3247
3248// Sets *pbOverridingTypeSpec to TRUE if we are overriding a method declared by a type spec.
3249// In that case the syntax is slightly different (there are additional 'method' keywords).
3250// Refer to Expert .NET 2.0 IL Assembler page 242.
3251void PrettyPrintOverrideDecl(ULONG i, __inout __nullterminated char* szString, void* GUICookie, mdToken tkOverrider,
3252 BOOL *pbOverridingTypeSpec)
3253{
3254 const char * pszMemberName;
3255 mdToken tkDecl,tkDeclParent=0;
3256 char szBadToken[256];
3257 char pszTailSigDefault[] = "";
3258 char* pszTailSig = pszTailSigDefault;
3259 CQuickBytes qbInstSig;
3260 char* szptr = &szString[0];
3261 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".override"));
3262 tkDecl = (*g_pmi_list)[i].tkDecl;
3263
3264 *pbOverridingTypeSpec = FALSE;
3265
3266 if(g_pImport->IsValidToken(tkDecl))
3267 {
3268 if(SUCCEEDED(g_pImport->GetParentToken(tkDecl,&tkDeclParent)))
3269 {
3270 if(g_pImport->IsValidToken(tkDeclParent))
3271 {
3272 if(TypeFromToken(tkDeclParent) == mdtMethodDef) //get the parent's parent
3273 {
3274 mdTypeRef cr1;
3275 if(FAILED(g_pImport->GetParentToken(tkDeclParent,&cr1))) cr1 = mdTypeRefNil;
3276 tkDeclParent = cr1;
3277 }
3278 if(RidFromToken(tkDeclParent))
3279 {
3280 if(TypeFromToken(tkDeclParent)==mdtTypeSpec)
3281 {
3282 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " %s ",KEYWORD("method"));
3283 PrettyPrintToken(szString,tkDecl,g_pImport,GUICookie,tkOverrider);
3284
3285 *pbOverridingTypeSpec = TRUE;
3286 return;
3287 }
3288 PrettyPrintToken(szString, tkDeclParent, g_pImport,GUICookie,tkOverrider);
3289 strcat_s(szString, SZSTRING_SIZE,"::");
3290 szptr = &szString[strlen(szString)];
3291 }
3292 }
3293 else
3294 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",ERRORMSG("INVALID OVERRIDDEN METHOD'S PARENT TOKEN"));
3295 }
3296 if(TypeFromToken(tkDecl) == mdtMethodSpec)
3297 {
3298 mdToken meth=0;
3299 PCCOR_SIGNATURE pSig=NULL;
3300 ULONG cSig=0;
3301 if (FAILED(g_pImport->GetMethodSpecProps(tkDecl, &meth, &pSig, &cSig)))
3302 {
3303 meth = mdTokenNil;
3304 pSig = NULL;
3305 cSig = 0;
3306 }
3307
3308 if (pSig && cSig)
3309 {
3310 qbInstSig.Shrink(0);
3311 pszTailSig = (char*)PrettyPrintSig(pSig, cSig, "", &qbInstSig, g_pImport, NULL);
3312 }
3313 tkDecl = meth;
3314 }
3315 if(TypeFromToken(tkDecl) == mdtMethodDef)
3316 {
3317 if (FAILED(g_pImport->GetNameOfMethodDef(tkDecl, &pszMemberName)))
3318 {
3319 sprintf_s(szBadToken,256,ERRORMSG("INVALID RECORD: 0x%8.8X"),tkDecl);
3320 pszMemberName = (const char *)szBadToken;
3321 }
3322 }
3323 else if(TypeFromToken(tkDecl) == mdtMemberRef)
3324 {
3325 PCCOR_SIGNATURE pComSig;
3326 ULONG cComSig;
3327
3328 if (FAILED(g_pImport->GetNameAndSigOfMemberRef(
3329 tkDecl,
3330 &pComSig,
3331 &cComSig,
3332 &pszMemberName)))
3333 {
3334 sprintf_s(szBadToken,256,ERRORMSG("INVALID RECORD: 0x%8.8X"),tkDecl);
3335 pszMemberName = (const char *)szBadToken;
3336 }
3337 }
3338 else
3339 {
3340 sprintf_s(szBadToken,256,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tkDecl);
3341 pszMemberName = (const char*)szBadToken;
3342 }
3343 MAKE_NAME_IF_NONE(pszMemberName,tkDecl);
3344 }
3345 else
3346 {
3347 sprintf_s(szBadToken,256,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tkDecl);
3348 pszMemberName = (const char*)szBadToken;
3349 }
3350 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s",ProperName((char*)pszMemberName),pszTailSig);
3351
3352 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X::%08X*/ "),tkDeclParent,(*g_pmi_list)[i].tkDecl);
3353}
3354
3355#ifdef _PREFAST_
3356#pragma warning(push)
3357#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3358#endif
3359BOOL DumpMethod(mdToken FuncToken, const char *pszClassName, DWORD dwEntryPointToken,void *GUICookie,BOOL DumpBody)
3360{
3361 const char *pszMemberName = NULL;//[MAX_MEMBER_LENGTH];
3362 const char *pszMemberSig = NULL;
3363 DWORD dwAttrs = 0;
3364 DWORD dwImplAttrs;
3365 DWORD dwOffset;
3366 DWORD dwTargetRVA;
3367 CQuickBytes qbMemberSig;
3368 PCCOR_SIGNATURE pComSig = NULL;
3369 ULONG cComSig;
3370 char *buff = NULL;//[MAX_MEMBER_LENGTH];
3371 ParamDescriptor* pszArgname = NULL;
3372 ULONG ulArgs=0;
3373 unsigned retParamIx = 0;
3374 unsigned uStringLen = SZSTRING_SIZE;
3375 char szArgPrefix[MAX_PREFIX_SIZE];
3376 char* szptr = NULL;
3377 mdToken tkMVarOwner = g_tkMVarOwner;
3378
3379 if (FAILED(g_pImport->GetMethodDefProps(FuncToken, &dwAttrs)))
3380 {
3381 sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MethodDef %08X has wrong record", g_szAsmCodeIndent, FuncToken);
3382 printError(GUICookie, ERRORMSG(szString));
3383 return FALSE;
3384 }
3385 if (g_fLimitedVisibility)
3386 {
3387 if(g_fHidePub && IsMdPublic(dwAttrs)) return FALSE;
3388 if(g_fHidePriv && IsMdPrivate(dwAttrs)) return FALSE;
3389 if(g_fHideFam && IsMdFamily(dwAttrs)) return FALSE;
3390 if(g_fHideAsm && IsMdAssem(dwAttrs)) return FALSE;
3391 if(g_fHideFOA && IsMdFamORAssem(dwAttrs)) return FALSE;
3392 if(g_fHideFAA && IsMdFamANDAssem(dwAttrs)) return FALSE;
3393 if(g_fHidePrivScope && IsMdPrivateScope(dwAttrs)) return FALSE;
3394 }
3395 if (FAILED(g_pImport->GetMethodImplProps(FuncToken, &dwOffset, &dwImplAttrs)))
3396 {
3397 sprintf_s(szString, SZSTRING_SIZE, "%sERROR: Invalid MethodImpl %08X record", g_szAsmCodeIndent, FuncToken);
3398 printError(GUICookie, ERRORMSG(szString));
3399 return FALSE;
3400 }
3401 if (FAILED(g_pImport->GetNameOfMethodDef(FuncToken, &pszMemberName)))
3402 {
3403 sprintf_s(szString, SZSTRING_SIZE, "%sERROR: MethodDef %08X has wrong record", g_szAsmCodeIndent, FuncToken);
3404 printError(GUICookie, ERRORMSG(szString));
3405 return FALSE;
3406 }
3407 MAKE_NAME_IF_NONE(pszMemberName,FuncToken);
3408 if (FAILED(g_pImport->GetSigOfMethodDef(FuncToken, &cComSig, &pComSig)))
3409 {
3410 pComSig = NULL;
3411 }
3412
3413 if (cComSig == NULL)
3414 {
3415 sprintf_s(szString, SZSTRING_SIZE, "%sERROR: method '%s' has no signature", g_szAsmCodeIndent, pszMemberName);
3416 printError(GUICookie, ERRORMSG(szString));
3417 return FALSE;
3418 }
3419 bool bRet = FALSE;
3420
3421 PAL_CPP_TRY {
3422 if((*pComSig & IMAGE_CEE_CS_CALLCONV_MASK) > IMAGE_CEE_CS_CALLCONV_VARARG)
3423 {
3424 sprintf_s(szString,SZSTRING_SIZE,"%sERROR: signature of method '%s' has invalid calling convention 0x%2.2X",g_szAsmCodeIndent,pszMemberName,*pComSig);
3425 printError(GUICookie,ERRORMSG(szString));
3426 bRet = TRUE;
3427 goto lDone;
3428 }
3429
3430 g_tkMVarOwner = FuncToken;
3431 szString[0] = 0;
3432 DumpGenericPars(szString,FuncToken); //,NULL,FALSE);
3433 pszMemberSig = PrettyPrintSig(pComSig, cComSig, szString, &qbMemberSig, g_pImport,NULL);
3434lDone: ;
3435 } PAL_CPP_CATCH_ALL {
3436 printError(GUICookie,"INVALID DATA ADDRESS");
3437 bRet = TRUE;
3438 } PAL_CPP_ENDTRY;
3439
3440 if (bRet)
3441 {
3442 g_tkMVarOwner = tkMVarOwner;
3443 return FALSE;
3444 }
3445
3446 if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
3447 {
3448 if (strcmp(pszMemberName, g_pszMethodToDump) != 0) return FALSE;
3449
3450 if (g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
3451 {
3452 // we want plain signature without token values
3453 const char *pszPlainSig;
3454 if (g_fDumpTokens)
3455 {
3456 // temporarily disable token dumping
3457 g_fDumpTokens = FALSE;
3458
3459 PAL_CPP_TRY
3460 {
3461 CQuickBytes qbTempSig;
3462 pszPlainSig = PrettyPrintSig(pComSig, cComSig, "", &qbTempSig, g_pImport, NULL);
3463 }
3464 PAL_CPP_CATCH_ALL
3465 {
3466 pszPlainSig = "";
3467 }
3468 PAL_CPP_ENDTRY;
3469
3470 g_fDumpTokens = TRUE;
3471 }
3472 else
3473 {
3474 pszPlainSig = pszMemberSig;
3475 }
3476
3477 if (strcmp(pszPlainSig, g_pszSigToDump) != 0) return FALSE;
3478 }
3479 }
3480
3481 if(!DumpBody)
3482 {
3483 printLine(GUICookie,(char*)pszMemberSig);
3484 g_tkMVarOwner = tkMVarOwner;
3485 return TRUE;
3486 }
3487
3488 szptr = &szString[0];
3489 szString[0] = 0;
3490 if(DumpBody) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s ",g_szAsmCodeIndent,ANCHORPT(KEYWORD(".method"),FuncToken));
3491 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",ANCHORPT(KEYWORD(".method"),FuncToken));
3492
3493 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
3494 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
3495 if(IsMdPublic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"public ");
3496 if(IsMdPrivate(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"private ");
3497 if(IsMdFamily(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"family ");
3498 if(IsMdAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"assembly ");
3499 if(IsMdFamANDAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famandassem ");
3500 if(IsMdFamORAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famorassem ");
3501 if(IsMdPrivateScope(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"privatescope ");
3502 if(IsMdHideBySig(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"hidebysig ");
3503 if(IsMdNewSlot(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"newslot ");
3504 if(IsMdSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"specialname ");
3505 if(IsMdRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"rtspecialname ");
3506 if (IsMdStatic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"static ");
3507 if (IsMdAbstract(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"abstract ");
3508 if (dwAttrs & 0x00000200) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"strict ");
3509 if (IsMdVirtual(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"virtual ");
3510 if (IsMdFinal(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"final ");
3511 if (IsMdUnmanagedExport(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"unmanagedexp ");
3512 if(IsMdRequireSecObject(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"reqsecobj ");
3513 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
3514 if (IsMdPinvokeImpl(dwAttrs))
3515 {
3516 DWORD dwMappingFlags;
3517 const char *szImportName;
3518 mdModuleRef mrImportDLL;
3519
3520 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s(",KEYWORD("pinvokeimpl"));
3521 if(FAILED(g_pImport->GetPinvokeMap(FuncToken,&dwMappingFlags,
3522 &szImportName,&mrImportDLL))) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/* No map */"));
3523 else
3524 szptr=DumpPinvokeMap(dwMappingFlags, (strcmp(szImportName,pszMemberName)? szImportName : NULL),
3525 mrImportDLL,szString,GUICookie);
3526 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
3527 }
3528 // A little hack to get the formatting we need for Assem.
3529 buff = new char[SZSTRING_SIZE];
3530 if(buff==NULL)
3531 {
3532 printError(GUICookie,"Out of memory");
3533 g_tkMVarOwner = tkMVarOwner;
3534 return FALSE;
3535 }
3536 g_fThisIsInstanceMethod = !IsMdStatic(dwAttrs);
3537 {
3538 const char *psz = NULL;
3539 if(IsMdPrivateScope(dwAttrs))
3540 sprintf_s(buff,SZSTRING_SIZE,"%s$PST%08X", pszMemberName,FuncToken );
3541 else
3542 strcpy_s(buff,SZSTRING_SIZE, pszMemberName );
3543
3544 psz = ProperName(buff);
3545 if(psz != buff)
3546 {
3547 strcpy_s(buff,SZSTRING_SIZE,psz);
3548 }
3549 }
3550
3551 DumpGenericPars(buff, FuncToken); //, NULL, FALSE);
3552
3553 qbMemberSig.Shrink(0);
3554 // Get the argument names, if any
3555 strcpy_s(szArgPrefix,MAX_PREFIX_SIZE,(g_fThisIsInstanceMethod ? "A1": "A0"));
3556 {
3557 PCCOR_SIGNATURE typePtr = pComSig;
3558 unsigned ulCallConv = CorSigUncompressData(typePtr); // get the calling convention out of the way
3559 if (ulCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
3560 CorSigUncompressData(typePtr); // get the num of generic args out of the way
3561 unsigned numArgs = CorSigUncompressData(typePtr)+1;
3562 HENUMInternal hArgEnum;
3563 mdParamDef tkArg;
3564 if (FAILED(g_pImport->EnumInit(mdtParamDef,FuncToken,&hArgEnum)))
3565 {
3566 printError(GUICookie, "Invalid MetaDataFormat");
3567 g_tkMVarOwner = tkMVarOwner;
3568 return FALSE;
3569 }
3570 ulArgs = g_pImport->EnumGetCount(&hArgEnum);
3571 retParamIx = numArgs-1;
3572 if (ulArgs < numArgs) ulArgs = numArgs;
3573 if (ulArgs != 0)
3574 {
3575 pszArgname = new ParamDescriptor[ulArgs+2];
3576 memset(pszArgname,0,(ulArgs+2)*sizeof(ParamDescriptor));
3577 LPCSTR szName;
3578 ULONG ulSequence, ix;
3579 USHORT wSequence;
3580 DWORD dwAttr;
3581 ULONG j;
3582 for (j=0; g_pImport->EnumNext(&hArgEnum,&tkArg) && RidFromToken(tkArg); j++)
3583 {
3584 if (FAILED(g_pImport->GetParamDefProps(tkArg, &wSequence, &dwAttr, &szName)))
3585 {
3586 char sz[256];
3587 sprintf_s(sz, COUNTOF(sz), RstrUTF(IDS_E_INVALIDRECORD), tkArg);
3588 printError(GUICookie, sz);
3589 continue;
3590 }
3591 ulSequence = wSequence;
3592
3593 if (ulSequence > ulArgs+1)
3594 {
3595 char sz[256];
3596 sprintf_s(sz,256,RstrUTF(IDS_E_PARAMSEQNO),j,ulSequence,ulSequence);
3597 printError(GUICookie,sz);
3598 }
3599 else
3600 {
3601 ix = retParamIx;
3602 if (ulSequence != 0)
3603 {
3604 ix = ulSequence-1;
3605 if (*szName != 0)
3606 {
3607 pszArgname[ix].name = new char[strlen(szName)+1];
3608 strcpy_s(pszArgname[ix].name,strlen(szName)+1,szName);
3609 }
3610 }
3611 pszArgname[ix].attr = dwAttr;
3612 pszArgname[ix].tok = tkArg;
3613 }
3614 }// end for( along the params)
3615 for (j=0; j <numArgs; j++)
3616 {
3617 if(pszArgname[j].name == NULL) // we haven't got the name!
3618 {
3619 pszArgname[j].name = new char[16];
3620 *pszArgname[j].name = 0;
3621 }
3622 if(*pszArgname[j].name == 0) // we haven't got the name!
3623 {
3624 sprintf_s(pszArgname[j].name,16,"A_%d",g_fThisIsInstanceMethod ? j+1 : j);
3625 }
3626 }// end for( along the argnames)
3627 sprintf_s(szArgPrefix,MAX_PREFIX_SIZE,"@%Id0",(size_t)pszArgname);
3628 } //end if (ulArgs)
3629 g_pImport->EnumClose(&hArgEnum);
3630 }
3631 g_tkRefUser = FuncToken;
3632 PrettyPrintMethodSig(szString, &uStringLen, &qbMemberSig, pComSig, cComSig,
3633 buff, szArgPrefix, GUICookie);
3634 g_tkRefUser = 0;
3635 szptr = &szString[strlen(szString)];
3636 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
3637 if(IsMiNative(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," native");
3638 if(IsMiIL(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," cil");
3639 if(IsMiOPTIL(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," optil");
3640 if(IsMiRuntime(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," runtime");
3641 if(IsMiUnmanaged(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," unmanaged");
3642 if(IsMiManaged(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," managed");
3643 if(IsMiPreserveSig(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," preservesig");
3644 if(IsMiForwardRef(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," forwardref");
3645 if(IsMiInternalCall(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," internalcall");
3646 if(IsMiSynchronized(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," synchronized");
3647 if(IsMiNoInlining(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," noinlining");
3648 if(IsMiAggressiveInlining(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," aggressiveinlining");
3649 if(IsMiNoOptimization(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," nooptimization");
3650 if(IsMiAggressiveOptimization(dwImplAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," aggressiveoptimization");
3651 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
3652 printLine(GUICookie, szString);
3653 VDELETE(buff);
3654
3655 if(!DumpBody)
3656 {
3657 g_tkMVarOwner = tkMVarOwner;
3658 return TRUE;
3659 }
3660
3661 if(g_fShowBytes)
3662 {
3663 if (FAILED(g_pImport->GetSigOfMethodDef(FuncToken, &cComSig, &pComSig)))
3664 {
3665 sprintf_s(szString,SZSTRING_SIZE,"%sERROR: method %08X has wrong record",g_szAsmCodeIndent,FuncToken);
3666 printError(GUICookie,ERRORMSG(szString));
3667 return FALSE;
3668 }
3669 const char* szt = "SIG:";
3670 for(ULONG i=0; i<cComSig;)
3671 {
3672 szptr = &szString[0];
3673 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s// %s", g_szAsmCodeIndent, szt);
3674 while(i<cComSig)
3675 {
3676 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %02X",pComSig[i]);
3677 i++;
3678 if((i & 0x1F)==0) break; // print only 32 per line
3679 }
3680 printLine(GUICookie, COMMENT(szString));
3681 szt = " ";
3682 }
3683 }
3684
3685 szptr = &szString[0];
3686 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s", g_szAsmCodeIndent,SCOPE());
3687 printLine(GUICookie, szString);
3688 szptr = &szString[0];
3689 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
3690
3691 // We have recoreded the entry point token from the CLR Header. Check to see if this
3692 // method is the entry point.
3693 if(FuncToken == static_cast<mdToken>(dwEntryPointToken))
3694 {
3695 sprintf_s(szString,SZSTRING_SIZE,"%s%s", g_szAsmCodeIndent,KEYWORD(".entrypoint"));
3696 printLine(GUICookie, szString);
3697 }
3698 DumpCustomAttributes(FuncToken,GUICookie);
3699 DumpGenericParsCA(FuncToken,GUICookie);
3700 DumpParams(pszArgname, retParamIx, GUICookie);
3701 DumpPermissions(FuncToken,GUICookie);
3702 // Check if the method represents entry in VTable fixups and in EATable
3703 {
3704 ULONG j;
3705 for(j=0; j<g_nVTableRef; j++)
3706 {
3707 if((*g_prVTableRef)[j].tkTok == FuncToken)
3708 {
3709 sprintf_s(szString,SZSTRING_SIZE,"%s%s %d : %d",
3710 g_szAsmCodeIndent,KEYWORD(".vtentry"),(*g_prVTableRef)[j].wEntry+1,(*g_prVTableRef)[j].wSlot+1);
3711 printLine(GUICookie, szString);
3712 break;
3713 }
3714 }
3715 for(j=0; j<g_nEATableRef; j++)
3716 {
3717 if((*g_prEATableRef)[j].tkTok == FuncToken)
3718 {
3719 szptr = &szString[0];
3720 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s [%d] ",
3721 g_szAsmCodeIndent,KEYWORD(".export"),j+g_nEATableBase);
3722 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s %s",
3723 KEYWORD("as"), ProperName((*g_prEATableRef)[j].pszName));
3724 printLine(GUICookie, szString);
3725 break;
3726 }
3727 }
3728 }
3729 // Dump method impls of this method:
3730 for(ULONG i = 0; i < g_NumMI; i++)
3731 {
3732 if((*g_pmi_list)[i].tkBody == FuncToken)
3733 {
3734 BOOL bOverridingTypeSpec;
3735 PrettyPrintOverrideDecl(i,szString,GUICookie,FuncToken,&bOverridingTypeSpec);
3736 printLine(GUICookie,szString);
3737 }
3738 }
3739 dwTargetRVA = dwOffset;
3740 if (IsMdPinvokeImpl(dwAttrs))
3741 {
3742 if(dwOffset)
3743 {
3744 sprintf_s(szString,SZSTRING_SIZE,"%s// Embedded native code",g_szAsmCodeIndent);
3745 printLine(GUICookie, COMMENT(szString));
3746 goto ItsMiNative;
3747 }
3748 if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
3749 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
3750 printLine(GUICookie, szString);
3751 g_tkMVarOwner = tkMVarOwner;
3752 return TRUE;
3753 }
3754
3755 if(IsMiManaged(dwImplAttrs))
3756 {
3757 if(IsMiIL(dwImplAttrs) || IsMiOPTIL(dwImplAttrs))
3758 {
3759 if(g_fShowBytes)
3760 {
3761 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_METHBEG), g_szAsmCodeIndent,dwTargetRVA);
3762 printLine(GUICookie, COMMENT(szString));
3763 }
3764 szString[0] = 0;
3765 if (dwTargetRVA != 0)
3766 {
3767 void* newTarget;
3768 if(g_pPELoader->getVAforRVA(dwTargetRVA,&newTarget))
3769 {
3770 DisassembleWrapper(g_pImport, (unsigned char*)newTarget, GUICookie, FuncToken,pszArgname, ulArgs);
3771 }
3772 else
3773 {
3774 sprintf_s(szString,SZSTRING_SIZE, "INVALID METHOD ADDRESS: 0x%8.8X (RVA: 0x%8.8X)",(size_t)newTarget,dwTargetRVA);
3775 printError(GUICookie,szString);
3776 }
3777 }
3778 }
3779 else if(IsMiNative(dwImplAttrs))
3780 {
3781ItsMiNative:
3782 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_DASMNATIVE), g_szAsmCodeIndent);
3783 printLine(GUICookie, COMMENT(szString));
3784
3785 sprintf_s(szString,SZSTRING_SIZE,"%s// Managed TargetRVA = 0x%8.8X", g_szAsmCodeIndent, dwTargetRVA);
3786 printLine(GUICookie, COMMENT(szString));
3787 }
3788 }
3789 else if(IsMiUnmanaged(dwImplAttrs)&&IsMiNative(dwImplAttrs))
3790 {
3791 _ASSERTE(IsMiNative(dwImplAttrs));
3792 sprintf_s(szString,SZSTRING_SIZE,"%s// Unmanaged TargetRVA = 0x%8.8X", g_szAsmCodeIndent, dwTargetRVA);
3793 printLine(GUICookie, COMMENT(szString));
3794 }
3795 else if(IsMiRuntime(dwImplAttrs))
3796 {
3797 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_METHODRT), g_szAsmCodeIndent);
3798 printLine(GUICookie, COMMENT(szString));
3799 }
3800#ifdef _DEBUG
3801 else _ASSERTE(!"Bad dwImplAttrs");
3802#endif
3803
3804 if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
3805 {
3806 szptr = &szString[0];
3807 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
3808 if(pszClassName)
3809 {
3810 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of method %s::"), ProperName((char*)pszClassName));
3811 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(ProperName((char*)pszMemberName)));
3812 }
3813 else
3814 sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of global method %s"), ProperName((char*)pszMemberName));
3815 }
3816 printLine(GUICookie, szString);
3817 szString[0] = 0;
3818 printLine(GUICookie, szString);
3819
3820 if(pszArgname)
3821 {
3822 for(ULONG i=0; i < ulArgs; i++)
3823 {
3824 if(pszArgname[i].name) VDELETE(pszArgname[i].name);
3825 }
3826 VDELETE(pszArgname);
3827 }
3828 g_tkMVarOwner = tkMVarOwner;
3829 return TRUE;
3830}
3831#ifdef _PREFAST_
3832#pragma warning(pop)
3833#endif
3834
3835BOOL DumpField(mdToken FuncToken, const char *pszClassName,void *GUICookie, BOOL DumpBody)
3836{
3837 char *pszMemberName = NULL;//[MAX_MEMBER_LENGTH];
3838 DWORD dwAttrs = 0;
3839 CQuickBytes qbMemberSig;
3840 PCCOR_SIGNATURE pComSig = NULL;
3841 ULONG cComSig;
3842 const char *szStr = NULL;//[1024];
3843 char* szptr;
3844
3845 const char *psz;
3846 if (FAILED(g_pImport->GetNameOfFieldDef(FuncToken, &psz)))
3847 {
3848 char sz[2048];
3849 sprintf_s(sz, 2048, "%sERROR: FieldDef %08X has no signature", g_szAsmCodeIndent, FuncToken);
3850 printError(GUICookie, sz);
3851 return FALSE;
3852 }
3853 MAKE_NAME_IF_NONE(psz,FuncToken);
3854
3855 if (FAILED(g_pImport->GetFieldDefProps(FuncToken, &dwAttrs)))
3856 {
3857 char sz[2048];
3858 sprintf_s(sz, 2048, "%sERROR: FieldDef %08X record error", g_szAsmCodeIndent, FuncToken);
3859 printError(GUICookie, sz);
3860 return FALSE;
3861 }
3862 if (g_fLimitedVisibility)
3863 {
3864 if(g_fHidePub && IsFdPublic(dwAttrs)) return FALSE;
3865 if(g_fHidePriv && IsFdPrivate(dwAttrs)) return FALSE;
3866 if(g_fHideFam && IsFdFamily(dwAttrs)) return FALSE;
3867 if(g_fHideAsm && IsFdAssembly(dwAttrs)) return FALSE;
3868 if(g_fHideFOA && IsFdFamORAssem(dwAttrs)) return FALSE;
3869 if(g_fHideFAA && IsFdFamANDAssem(dwAttrs)) return FALSE;
3870 if(g_fHidePrivScope && IsFdPrivateScope(dwAttrs)) return FALSE;
3871 }
3872
3873 {
3874 const char* psz1 = NULL;
3875 if(IsFdPrivateScope(dwAttrs))
3876 {
3877 pszMemberName = new char[strlen(psz)+15];
3878 sprintf_s(pszMemberName,strlen(psz)+15,"%s$PST%08X", psz,FuncToken );
3879 }
3880 else
3881 {
3882 pszMemberName = new char[strlen(psz)+3];
3883 strcpy_s(pszMemberName, strlen(psz)+3, psz );
3884 }
3885 psz1 = ProperName(pszMemberName);
3886 VDELETE(pszMemberName);
3887 pszMemberName = new char[strlen(psz1)+1];
3888 strcpy_s(pszMemberName,strlen(psz1)+1,psz1);
3889 }
3890 if (FAILED(g_pImport->GetSigOfFieldDef(FuncToken, &cComSig, &pComSig)))
3891 {
3892 pComSig = NULL;
3893 }
3894 if (cComSig == NULL)
3895 {
3896 char sz[2048];
3897 sprintf_s(sz,2048,"%sERROR: field '%s' has no signature",g_szAsmCodeIndent,pszMemberName);
3898 VDELETE(pszMemberName);
3899 printError(GUICookie,sz);
3900 return FALSE;
3901 }
3902 g_tkRefUser = FuncToken;
3903
3904 bool bRet = FALSE;
3905 PAL_CPP_TRY {
3906 szStr = PrettyPrintSig(pComSig, cComSig, (DumpBody ? pszMemberName : ""), &qbMemberSig, g_pImport,NULL);
3907 }
3908 PAL_CPP_CATCH_ALL
3909 {
3910 printError(GUICookie,"INVALID ADDRESS IN FIELD SIGNATURE");
3911 bRet = TRUE;
3912 } PAL_CPP_ENDTRY;
3913
3914 if (bRet)
3915 return FALSE;
3916
3917 g_tkRefUser = 0;
3918
3919 if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
3920 {
3921 if (strcmp(pszMemberName, g_pszMethodToDump) != 0)
3922 {
3923 VDELETE(pszMemberName);
3924 return FALSE;
3925 }
3926
3927 if (g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
3928 {
3929 // we want plain signature without token values and without the field name
3930 BOOL fDumpTokens = g_fDumpTokens;
3931 g_fDumpTokens = FALSE;
3932
3933 const char *pszPlainSig;
3934 PAL_CPP_TRY
3935 {
3936 CQuickBytes qbTempSig;
3937 pszPlainSig = PrettyPrintSig(pComSig, cComSig, "", &qbTempSig, g_pImport, NULL);
3938 }
3939 PAL_CPP_CATCH_ALL
3940 {
3941 pszPlainSig = "";
3942 }
3943 PAL_CPP_ENDTRY;
3944
3945 g_fDumpTokens = fDumpTokens;
3946
3947 if (strcmp(pszPlainSig, g_pszSigToDump) != 0)
3948 {
3949 VDELETE(pszMemberName);
3950 return FALSE;
3951 }
3952 }
3953 }
3954 VDELETE(pszMemberName);
3955
3956 szptr = &szString[0];
3957 if(DumpBody)
3958 {
3959 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ", g_szAsmCodeIndent,ANCHORPT(KEYWORD(".field"),FuncToken));
3960 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
3961 }
3962
3963 // put offset (if any)
3964 for(ULONG i=0; i < g_cFieldOffsets; i++)
3965 {
3966 if(g_rFieldOffset[i].ridOfField == FuncToken)
3967 {
3968 if(g_rFieldOffset[i].ulOffset != 0xFFFFFFFF) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"[%d] ",g_rFieldOffset[i].ulOffset);
3969 break;
3970 }
3971 }
3972
3973 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
3974 if(IsFdPublic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"public ");
3975 if(IsFdPrivate(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"private ");
3976 if(IsFdStatic(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"static ");
3977 if(IsFdFamily(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"family ");
3978 if(IsFdAssembly(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"assembly ");
3979 if(IsFdFamANDAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famandassem ");
3980 if(IsFdFamORAssem(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"famorassem ");
3981 if(IsFdPrivateScope(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"privatescope ");
3982 if(IsFdInitOnly(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"initonly ");
3983 if(IsFdLiteral(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"literal ");
3984 if(IsFdNotSerialized(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"notserialized ");
3985 if(IsFdSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"specialname ");
3986 if(IsFdRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"rtspecialname ");
3987 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
3988 if (IsFdPinvokeImpl(dwAttrs))
3989 {
3990 DWORD dwMappingFlags;
3991 const char *szImportName;
3992 mdModuleRef mrImportDLL;
3993
3994 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s(",KEYWORD("pinvokeimpl"));
3995 if(FAILED(g_pImport->GetPinvokeMap(FuncToken,&dwMappingFlags,
3996 &szImportName,&mrImportDLL))) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/* No map */"));
3997 else
3998 szptr = DumpPinvokeMap(dwMappingFlags, (strcmp(szImportName,psz)? szImportName : NULL),
3999 mrImportDLL, szString,GUICookie);
4000 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
4001 }
4002 szptr = DumpMarshaling(g_pImport,szString,SZSTRING_SIZE,FuncToken);
4003
4004 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s",szStr);
4005
4006 if (IsFdHasFieldRVA(dwAttrs)) // Do we have an RVA associated with this?
4007 {
4008 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD(" at "));
4009
4010 ULONG fieldRVA;
4011 if (SUCCEEDED(g_pImport->GetFieldRVA(FuncToken, &fieldRVA)))
4012 {
4013 szptr = DumpDataPtr(&szString[strlen(szString)], fieldRVA, SizeOfField(FuncToken,g_pImport));
4014 }
4015 else
4016 {
4017 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),RstrUTF(IDS_E_NORVA));
4018 }
4019 }
4020
4021 // dump default value (if any):
4022 if(IsFdHasDefault(dwAttrs) && DumpBody) DumpDefaultValue(FuncToken,szString,GUICookie);
4023 printLine(GUICookie, szString);
4024
4025 if(DumpBody)
4026 {
4027 DumpCustomAttributes(FuncToken,GUICookie);
4028 DumpPermissions(FuncToken,GUICookie);
4029 }
4030
4031 return TRUE;
4032
4033}
4034
4035BOOL DumpEvent(mdToken FuncToken, const char *pszClassName, DWORD dwClassAttrs, void *GUICookie, BOOL DumpBody)
4036{
4037 DWORD dwAttrs;
4038 mdToken tkEventType;
4039 LPCSTR psz;
4040 HENUMInternal hAssoc;
4041 ASSOCIATE_RECORD rAssoc[128];
4042 CQuickBytes qbMemberSig;
4043 ULONG nAssoc;
4044 char* szptr;
4045
4046 if (FAILED(g_pImport->GetEventProps(FuncToken,&psz,&dwAttrs,&tkEventType)))
4047 {
4048 char sz[2048];
4049 sprintf_s(sz, 2048, "%sERROR: Invalid Event %08X record", g_szAsmCodeIndent, FuncToken);
4050 printError(GUICookie, sz);
4051 return FALSE;
4052 }
4053 MAKE_NAME_IF_NONE(psz,FuncToken);
4054 if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
4055 {
4056 if (strcmp(psz, g_pszMethodToDump) != 0) return FALSE;
4057 }
4058
4059 if (FAILED(g_pImport->EnumAssociateInit(FuncToken,&hAssoc)))
4060 {
4061 char sz[2048];
4062 sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating Associate for %08X", g_szAsmCodeIndent, FuncToken);
4063 printError(GUICookie, sz);
4064 return FALSE;
4065 }
4066
4067 if ((nAssoc = hAssoc.m_ulCount))
4068 {
4069 memset(rAssoc,0,sizeof(rAssoc));
4070 if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc)))
4071 {
4072 char sz[2048];
4073 sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating all Associates", g_szAsmCodeIndent);
4074 printError(GUICookie, sz);
4075 return FALSE;
4076 }
4077
4078 if (g_fLimitedVisibility)
4079 {
4080 unsigned i;
4081 for (i=0; i < nAssoc;i++)
4082 {
4083 if ((TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef) && g_pImport->IsValidToken(rAssoc[i].m_memberdef))
4084 {
4085 DWORD dwMethodAttrs;
4086 if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwMethodAttrs)))
4087 {
4088 continue;
4089 }
4090 if(g_fHidePub && IsMdPublic(dwMethodAttrs)) continue;
4091 if(g_fHidePriv && IsMdPrivate(dwMethodAttrs)) continue;
4092 if(g_fHideFam && IsMdFamily(dwMethodAttrs)) continue;
4093 if(g_fHideAsm && IsMdAssem(dwMethodAttrs)) continue;
4094 if(g_fHideFOA && IsMdFamORAssem(dwMethodAttrs)) continue;
4095 if(g_fHideFAA && IsMdFamANDAssem(dwMethodAttrs)) continue;
4096 if(g_fHidePrivScope && IsMdPrivateScope(dwMethodAttrs)) continue;
4097 break;
4098 }
4099 }
4100 if (i >= nAssoc) return FALSE;
4101 }
4102 }
4103
4104 szptr = &szString[0];
4105 if (DumpBody)
4106 {
4107 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ", g_szAsmCodeIndent,KEYWORD(".event"));
4108 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
4109 }
4110 else
4111 {
4112 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s : ",ProperName((char*)psz));
4113 }
4114
4115 if(IsEvSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("specialname "));
4116 if(IsEvRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("rtspecialname "));
4117
4118 if(RidFromToken(tkEventType)&&g_pImport->IsValidToken(tkEventType))
4119 {
4120 switch(TypeFromToken(tkEventType))
4121 {
4122 case mdtTypeRef:
4123 case mdtTypeDef:
4124 case mdtTypeSpec:
4125 {
4126 PrettyPrintToken(szString, tkEventType, g_pImport,GUICookie,0);
4127 szptr = &szString[strlen(szString)];
4128 }
4129 break;
4130 default:
4131 break;
4132 }
4133 }
4134
4135 if(!DumpBody)
4136 {
4137 printLine(GUICookie,szString);
4138 return TRUE;
4139 }
4140
4141
4142 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s", ProperName((char*)psz));
4143 printLine(GUICookie,szString);
4144 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
4145 printLine(GUICookie,szString);
4146 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
4147
4148 DumpCustomAttributes(FuncToken,GUICookie);
4149 DumpPermissions(FuncToken,GUICookie);
4150
4151 if(nAssoc)
4152 {
4153 for(unsigned i=0; i < nAssoc;i++)
4154 {
4155 mdToken tk = rAssoc[i].m_memberdef;
4156 DWORD sem = rAssoc[i].m_dwSemantics;
4157
4158 szptr = &szString[0];
4159 if(IsMsAddOn(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".addon"));
4160 else if(IsMsRemoveOn(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".removeon"));
4161 else if(IsMsFire(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".fire"));
4162 else if(IsMsOther(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".other"));
4163 else szptr+=sprintf_s(szptr,SZSTRING_SIZE,ERRORMSG("UNKNOWN SEMANTICS: 0x%X "),sem);
4164
4165 if(g_pImport->IsValidToken(tk))
4166 PrettyPrintToken(szString, tk, g_pImport,GUICookie,0);
4167 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN 0x%8.8X"),tk);
4168 printLine(GUICookie,szString);
4169 }
4170 }
4171 if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
4172 szptr = &szString[0];
4173 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
4174 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of event %s::"),ProperName((char*)pszClassName));
4175 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(ProperName((char*)psz)));
4176 printLine(GUICookie,szString);
4177 return TRUE;
4178
4179}
4180
4181BOOL DumpProp(mdToken FuncToken, const char *pszClassName, DWORD dwClassAttrs, void *GUICookie, BOOL DumpBody)
4182{
4183 DWORD dwAttrs;
4184 LPCSTR psz;
4185 HENUMInternal hAssoc;
4186 ASSOCIATE_RECORD rAssoc[128];
4187 CQuickBytes qbMemberSig;
4188 PCCOR_SIGNATURE pComSig;
4189 ULONG cComSig, nAssoc;
4190 unsigned uStringLen = SZSTRING_SIZE;
4191 char* szptr;
4192
4193 if (FAILED(g_pImport->GetPropertyProps(FuncToken,&psz,&dwAttrs,&pComSig,&cComSig)))
4194 {
4195 char sz[2048];
4196 sprintf_s(sz, 2048, "%sERROR: Invalid Property %08X record", g_szAsmCodeIndent, FuncToken);
4197 printError(GUICookie, sz);
4198 return FALSE;
4199 }
4200 MAKE_NAME_IF_NONE(psz,FuncToken);
4201 if(cComSig == 0)
4202 {
4203 char sz[2048];
4204 sprintf_s(sz,2048,"%sERROR: property '%s' has no signature",g_szAsmCodeIndent,psz);
4205 printError(GUICookie,sz);
4206 return FALSE;
4207 }
4208
4209 if (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
4210 {
4211 if (strcmp(psz, g_pszMethodToDump) != 0) return FALSE;
4212 }
4213
4214 if (FAILED(g_pImport->EnumAssociateInit(FuncToken,&hAssoc)))
4215 {
4216 char sz[2048];
4217 sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating Associate for %08X", g_szAsmCodeIndent, FuncToken);
4218 printError(GUICookie, sz);
4219 return FALSE;
4220 }
4221 if ((nAssoc = hAssoc.m_ulCount) != 0)
4222 {
4223 memset(rAssoc,0,sizeof(rAssoc));
4224 if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc)))
4225 {
4226 char sz[2048];
4227 sprintf_s(sz, 2048, "%sERROR: MetaData error enumerating all Associates", g_szAsmCodeIndent);
4228 printError(GUICookie, sz);
4229 return FALSE;
4230 }
4231
4232 if (g_fLimitedVisibility)
4233 {
4234 unsigned i;
4235 for (i=0; i < nAssoc;i++)
4236 {
4237 if ((TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef) && g_pImport->IsValidToken(rAssoc[i].m_memberdef))
4238 {
4239 DWORD dwMethodAttrs;
4240 if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwMethodAttrs)))
4241 {
4242 continue;
4243 }
4244 if(g_fHidePub && IsMdPublic(dwMethodAttrs)) continue;
4245 if(g_fHidePriv && IsMdPrivate(dwMethodAttrs)) continue;
4246 if(g_fHideFam && IsMdFamily(dwMethodAttrs)) continue;
4247 if(g_fHideAsm && IsMdAssem(dwMethodAttrs)) continue;
4248 if(g_fHideFOA && IsMdFamORAssem(dwMethodAttrs)) continue;
4249 if(g_fHideFAA && IsMdFamANDAssem(dwMethodAttrs)) continue;
4250 if(g_fHidePrivScope && IsMdPrivateScope(dwMethodAttrs)) continue;
4251 break;
4252 }
4253 }
4254 if( i >= nAssoc) return FALSE;
4255 }
4256 }
4257
4258 szptr = &szString[0];
4259 if (DumpBody)
4260 {
4261 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ", g_szAsmCodeIndent,KEYWORD(".property"));
4262 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%08X*/ "),FuncToken);
4263 }
4264 else
4265 {
4266 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s : ",ProperName((char*)psz));
4267 }
4268
4269 if(IsPrSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("specialname "));
4270 if(IsPrRTSpecialName(dwAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("rtspecialname "));
4271
4272 {
4273 char pchDefault[] = "";
4274 char *pch = pchDefault;
4275 if(DumpBody)
4276 {
4277 pch = szptr+1;
4278 strcpy_s(pch,SZSTRING_REMAINING_SIZE(pch),ProperName((char*)psz));
4279 }
4280 qbMemberSig.Shrink(0);
4281 PrettyPrintMethodSig(szString, &uStringLen, &qbMemberSig, pComSig, cComSig,
4282 pch, NULL, GUICookie);
4283 if(IsPrHasDefault(dwAttrs) && DumpBody) DumpDefaultValue(FuncToken,szString,GUICookie);
4284 }
4285 printLine(GUICookie,szString);
4286
4287 if(DumpBody)
4288 {
4289 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
4290 printLine(GUICookie,szString);
4291 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
4292
4293 DumpCustomAttributes(FuncToken,GUICookie);
4294 DumpPermissions(FuncToken,GUICookie);
4295
4296 if(nAssoc)
4297 {
4298 for(unsigned i=0; i < nAssoc;i++)
4299 {
4300 mdToken tk = rAssoc[i].m_memberdef;
4301 DWORD sem = rAssoc[i].m_dwSemantics;
4302
4303 szptr = &szString[0];
4304 if(IsMsSetter(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".set"));
4305 else if(IsMsGetter(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".get"));
4306 else if(IsMsOther(sem)) szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".other"));
4307 else szptr+=sprintf_s(szptr,SZSTRING_SIZE,ERRORMSG("UNKNOWN SEMANTICS: 0x%X "),sem);
4308
4309 if(g_pImport->IsValidToken(tk))
4310 PrettyPrintToken(szString, tk, g_pImport,GUICookie,0);
4311 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN 0x%8.8X"),tk);
4312 printLine(GUICookie,szString);
4313 }
4314 }
4315 if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
4316 szptr = &szString[0];
4317 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,UNSCOPE());
4318 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of property %s::"),ProperName((char*)pszClassName));
4319 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(ProperName((char*)psz)));
4320 printLine(GUICookie,szString);
4321 } // end if(DumpBody)
4322 return TRUE;
4323
4324}
4325
4326BOOL DumpMembers(mdTypeDef cl, const char *pszClassNamespace, const char *pszClassName,
4327 DWORD dwClassAttrs, DWORD dwEntryPointToken, void* GUICookie)
4328{
4329 HRESULT hr;
4330 mdToken *pMemberList = NULL;
4331 DWORD NumMembers, NumFields,NumMethods,NumEvents,NumProps;
4332 DWORD i;
4333 HENUMInternal hEnumMethod;
4334 HENUMInternal hEnumField;
4335 HENUMInternal hEnumEvent;
4336 HENUMInternal hEnumProp;
4337 CQuickBytes qbMemberSig;
4338 BOOL ret;
4339
4340 // Get the total count of methods + fields
4341 hr = g_pImport->EnumInit(mdtMethodDef, cl, &hEnumMethod);
4342 if (FAILED(hr))
4343 {
4344FailedToEnum:
4345 printLine(GUICookie,RstrUTF(IDS_E_MEMBRENUM));
4346 ret = FALSE;
4347 goto CloseHandlesAndReturn;
4348 }
4349 NumMembers = NumMethods = g_pImport->EnumGetCount(&hEnumMethod);
4350
4351
4352 if (FAILED(g_pImport->EnumInit(mdtFieldDef, cl, &hEnumField))) goto FailedToEnum;
4353 NumFields = g_pImport->EnumGetCount(&hEnumField);
4354 NumMembers += NumFields;
4355
4356 if (FAILED(g_pImport->EnumInit(mdtEvent, cl, &hEnumEvent))) goto FailedToEnum;
4357 NumEvents = g_pImport->EnumGetCount(&hEnumEvent);
4358 NumMembers += NumEvents;
4359
4360 if (FAILED(g_pImport->EnumInit(mdtProperty, cl, &hEnumProp))) goto FailedToEnum;
4361 NumProps = g_pImport->EnumGetCount(&hEnumProp);
4362 NumMembers += NumProps;
4363 ret = TRUE;
4364
4365 if(NumMembers)
4366 {
4367 pMemberList = new (nothrow) mdToken[NumMembers];
4368 if(pMemberList == NULL) ret = FALSE;
4369 }
4370 if ((NumMembers == 0)||(pMemberList == NULL)) goto CloseHandlesAndReturn;
4371
4372 for (i = 0; g_pImport->EnumNext(&hEnumField, &pMemberList[i]); i++);
4373 for (; g_pImport->EnumNext(&hEnumMethod, &pMemberList[i]); i++);
4374 for (; g_pImport->EnumNext(&hEnumEvent, &pMemberList[i]); i++);
4375 for (; g_pImport->EnumNext(&hEnumProp, &pMemberList[i]); i++);
4376 _ASSERTE(i == NumMembers);
4377
4378 for (i = 0; i < NumMembers; i++)
4379 {
4380 mdToken tk = pMemberList[i];
4381 if(g_pImport->IsValidToken(tk))
4382 {
4383 switch (TypeFromToken(tk))
4384 {
4385 case mdtFieldDef:
4386 ret = DumpField(pMemberList[i], pszClassName, GUICookie,TRUE);
4387 break;
4388
4389 case mdtMethodDef:
4390 ret = DumpMethod(pMemberList[i], pszClassName, dwEntryPointToken,GUICookie,TRUE);
4391 break;
4392
4393 case mdtEvent:
4394 ret = DumpEvent(pMemberList[i], pszClassName, dwClassAttrs,GUICookie,TRUE);
4395 break;
4396
4397 case mdtProperty:
4398 ret = DumpProp(pMemberList[i], pszClassName, dwClassAttrs,GUICookie,TRUE);
4399 break;
4400
4401 default:
4402 {
4403 char szStr[4096];
4404 sprintf_s(szStr,4096,RstrUTF(IDS_E_ODDMEMBER),pMemberList[i],pszClassName);
4405 printLine(GUICookie,szStr);
4406 }
4407 ret = FALSE;
4408 break;
4409 } // end switch
4410 }
4411 else
4412 {
4413 char szStr[256];
4414 sprintf_s(szStr,256,ERRORMSG("INVALID MEMBER TOKEN: 0x%8.8X"),tk);
4415 printLine(GUICookie,szStr);
4416 ret= FALSE;
4417 }
4418 if(ret && (g_Mode == MODE_DUMP_CLASS_METHOD_SIG)) break;
4419 } // end for
4420 ret = TRUE;
4421
4422CloseHandlesAndReturn:
4423 g_pImport->EnumClose(&hEnumMethod);
4424 g_pImport->EnumClose(&hEnumField);
4425 g_pImport->EnumClose(&hEnumEvent);
4426 g_pImport->EnumClose(&hEnumProp);
4427 if(pMemberList) delete[] pMemberList;
4428 return ret;
4429}
4430BOOL GetClassLayout(mdTypeDef cl, ULONG* pulPackSize, ULONG* pulClassSize)
4431{ // Dump class layout
4432 HENUMInternal hEnumField;
4433 BOOL ret = FALSE;
4434
4435 if(g_rFieldOffset)
4436 VDELETE(g_rFieldOffset);
4437 g_cFieldOffsets = 0;
4438 g_cFieldsMax = 0;
4439
4440 if(RidFromToken(cl)==0) return TRUE;
4441
4442 if (SUCCEEDED(g_pImport->EnumInit(mdtFieldDef, cl, &hEnumField)))
4443 {
4444 g_cFieldsMax = g_pImport->EnumGetCount(&hEnumField);
4445 g_pImport->EnumClose(&hEnumField);
4446 }
4447
4448 if(SUCCEEDED(g_pImport->GetClassPackSize(cl,pulPackSize))) ret = TRUE;
4449 else *pulPackSize = 0xFFFFFFFF;
4450 if(SUCCEEDED(g_pImport->GetClassTotalSize(cl,pulClassSize))) ret = TRUE;
4451 else *pulClassSize = 0xFFFFFFFF;
4452
4453 if(g_cFieldsMax)
4454 {
4455 MD_CLASS_LAYOUT Layout;
4456 if(SUCCEEDED(g_pImport->GetClassLayoutInit(cl,&Layout)))
4457 {
4458 g_rFieldOffset = new COR_FIELD_OFFSET[g_cFieldsMax+1];
4459 if(g_rFieldOffset)
4460 {
4461 COR_FIELD_OFFSET* pFO = g_rFieldOffset;
4462 for(g_cFieldOffsets=0;
4463 SUCCEEDED(g_pImport->GetClassLayoutNext(&Layout,&(pFO->ridOfField),&(pFO->ulOffset)))
4464 &&RidFromToken(pFO->ridOfField);
4465 g_cFieldOffsets++, pFO++) ret = TRUE;
4466 }
4467 }
4468 }
4469 return ret;
4470}
4471
4472BOOL IsANestedInB(mdTypeDef A, mdTypeDef B)
4473{
4474 DWORD i;
4475 for(i = 0; i < g_NumClasses; i++)
4476 {
4477 if(g_cl_list[i] == A)
4478 {
4479 A = g_cl_enclosing[i];
4480 if(A == B) return TRUE;
4481 if(A == mdTypeDefNil) return FALSE;
4482 return IsANestedInB(A,B);
4483 }
4484 }
4485 return FALSE;
4486}
4487mdTypeDef TopEncloser(mdTypeDef A)
4488{
4489 DWORD i;
4490 for(i = 0; i < g_NumClasses; i++)
4491 {
4492 if(g_cl_list[i] == A)
4493 {
4494 if(g_cl_enclosing[i] == mdTypeDefNil) return A;
4495 return TopEncloser(g_cl_enclosing[i]);
4496 }
4497 }
4498 return A;
4499}
4500
4501BOOL DumpClass(mdTypeDef cl, DWORD dwEntryPointToken, void* GUICookie, ULONG WhatToDump)
4502// WhatToDump: 0-title,flags,extends,implements;
4503// +1-pack,size and custom attrs;
4504// +2-nested classes
4505// +4-members
4506{
4507 char *pszClassName; // name associated with this CL
4508 char *pszNamespace;
4509 const char *pc1,*pc2;
4510 DWORD dwClassAttrs;
4511 mdTypeRef crExtends;
4512 HRESULT hr;
4513 mdInterfaceImpl ii;
4514 DWORD NumInterfaces;
4515 DWORD i;
4516 HENUMInternal hEnumII; // enumerator for interface impl
4517 //char *szString;
4518 char* szptr;
4519
4520 mdToken tkVarOwner = g_tkVarOwner;
4521 ULONG WhatToDumpOrig = WhatToDump;
4522
4523 if (FAILED(g_pImport->GetNameOfTypeDef(
4524 cl,
4525 &pc1, //&pszClassName,
4526 &pc2))) //&pszNamespace
4527 {
4528 char sz[2048];
4529 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), cl);
4530 printError(GUICookie, sz);
4531 g_tkVarOwner = tkVarOwner;
4532 return FALSE;
4533 }
4534 MAKE_NAME_IF_NONE(pc1,cl);
4535
4536 if (g_Mode == MODE_DUMP_CLASS || g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)
4537 {
4538 if(cl != g_tkClassToDump)
4539 {
4540 if(IsANestedInB(g_tkClassToDump,cl))
4541 WhatToDump = 2; // nested classes only
4542 else
4543 return TRUE;
4544 }
4545 }
4546
4547 if (FAILED(g_pImport->GetTypeDefProps(
4548 cl,
4549 &dwClassAttrs,
4550 &crExtends)))
4551 {
4552 char sz[2048];
4553 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), cl);
4554 printError(GUICookie, sz);
4555 g_tkVarOwner = tkVarOwner;
4556 return FALSE;
4557 }
4558
4559 if(g_fLimitedVisibility)
4560 {
4561 if(g_fHidePub && (IsTdPublic(dwClassAttrs)||IsTdNestedPublic(dwClassAttrs))) return FALSE;
4562 if(g_fHidePriv && (IsTdNotPublic(dwClassAttrs)||IsTdNestedPrivate(dwClassAttrs))) return FALSE;
4563 if(g_fHideFam && IsTdNestedFamily(dwClassAttrs)) return FALSE;
4564 if(g_fHideAsm && IsTdNestedAssembly(dwClassAttrs)) return FALSE;
4565 if(g_fHideFOA && IsTdNestedFamORAssem(dwClassAttrs)) return FALSE;
4566 if(g_fHideFAA && IsTdNestedFamANDAssem(dwClassAttrs)) return FALSE;
4567 }
4568
4569 g_tkVarOwner = cl;
4570
4571 pszClassName = (char*)(pc1 ? pc1 : "");
4572 pszNamespace = (char*)(pc2 ? pc2 : "");
4573
4574
4575 szptr = &szString[0];
4576 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".class"));
4577 if(g_fDumpTokens) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("/*%8.8X*/ "),cl);
4578 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)0));
4579 if (IsTdInterface(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"interface ");
4580 if (IsTdPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"public ");
4581 if (IsTdNotPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"private ");
4582 if (IsTdAbstract(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"abstract ");
4583 if (IsTdAutoLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"auto ");
4584 if (IsTdSequentialLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"sequential ");
4585 if (IsTdExplicitLayout(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"explicit ");
4586 if (IsTdAnsiClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"ansi ");
4587 if (IsTdUnicodeClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"unicode ");
4588 if (IsTdAutoClass(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"autochar ");
4589 if (IsTdImport(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"import ");
4590 if (IsTdWindowsRuntime(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"windowsruntime ");
4591 if (IsTdSerializable(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"serializable ");
4592 if (IsTdSealed(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"sealed ");
4593 if (IsTdNestedPublic(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested public ");
4594 if (IsTdNestedPrivate(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested private ");
4595 if (IsTdNestedFamily(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested family ");
4596 if (IsTdNestedAssembly(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested assembly ");
4597 if (IsTdNestedFamANDAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested famandassem ");
4598 if (IsTdNestedFamORAssem(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"nested famorassem ");
4599 if (IsTdBeforeFieldInit(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"beforefieldinit ");
4600 if (IsTdSpecialName(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"specialname ");
4601 if (IsTdRTSpecialName(dwClassAttrs)) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"rtspecialname ");
4602 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD((char*)-1));
4603 if(*pszNamespace != 0)
4604 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s.",ProperName(pszNamespace));
4605 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),WhatToDump > 2 ? ANCHORPT(ProperName(pszClassName),cl) : JUMPPT(ProperName(pszClassName),cl));
4606
4607 szptr = DumpGenericPars(szString, cl, GUICookie,TRUE);
4608 if (szptr == NULL)
4609 {
4610 g_tkVarOwner = tkVarOwner;
4611 return FALSE;
4612 }
4613
4614 printLine(GUICookie,szString);
4615 if (!IsNilToken(crExtends))
4616 {
4617 CQuickBytes out;
4618 szptr = szString;
4619 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s %s ",g_szAsmCodeIndent,KEYWORD("extends"));
4620 if(g_pImport->IsValidToken(crExtends))
4621 PrettyPrintToken(szString, crExtends, g_pImport,GUICookie,cl);
4622 else
4623 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN: 0x%8.8X"),crExtends);
4624 printLine(GUICookie,szString);
4625 }
4626
4627 hr = g_pImport->EnumInit(
4628 mdtInterfaceImpl,
4629 cl,
4630 &hEnumII);
4631 if (FAILED(hr))
4632 {
4633 printError(GUICookie,RstrUTF(IDS_E_ENUMINIT));
4634 g_tkVarOwner = tkVarOwner;
4635 return FALSE;
4636 }
4637
4638 NumInterfaces = g_pImport->EnumGetCount(&hEnumII);
4639
4640 if (NumInterfaces > 0)
4641 {
4642 CQuickBytes out;
4643 mdTypeRef crInterface;
4644 for (i=0; g_pImport->EnumNext(&hEnumII, &ii); i++)
4645 {
4646 szptr = szString;
4647 if(i) szptr+=sprintf_s(szptr,SZSTRING_SIZE, "%s ",g_szAsmCodeIndent);
4648 else szptr+=sprintf_s(szptr,SZSTRING_SIZE, "%s %s ",g_szAsmCodeIndent,KEYWORD("implements"));
4649 if (FAILED(g_pImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
4650 {
4651 char sz[2048];
4652 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), ii);
4653 printError(GUICookie, sz);
4654 g_tkVarOwner = tkVarOwner;
4655 return FALSE;
4656 }
4657 if(g_pImport->IsValidToken(crInterface))
4658 PrettyPrintToken(szString, crInterface, g_pImport,GUICookie,cl);
4659 else
4660 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN: 0x%8.8X"),crInterface);
4661 if(i < NumInterfaces-1) strcat_s(szString, SZSTRING_SIZE,",");
4662 printLine(GUICookie,szString);
4663 out.Shrink(0);
4664 }
4665 // The assertion will fire if the enumerator is bad
4666 _ASSERTE(NumInterfaces == i);
4667
4668 g_pImport->EnumClose(&hEnumII);
4669 }
4670 if(WhatToDump == 0) // 0 = title only
4671 {
4672 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,SCOPE(),UNSCOPE());
4673 printLine(GUICookie,szString);
4674 g_tkVarOwner = tkVarOwner;
4675 return TRUE;
4676 }
4677 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
4678 printLine(GUICookie,szString);
4679 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
4680
4681 ULONG ulPackSize=0xFFFFFFFF,ulClassSize=0xFFFFFFFF;
4682 if(WhatToDump & 1)
4683 {
4684 if(GetClassLayout(cl,&ulPackSize,&ulClassSize))
4685 { // Dump class layout
4686 if(ulPackSize != 0xFFFFFFFF)
4687 {
4688 sprintf_s(szString,SZSTRING_SIZE,"%s%s %d",g_szAsmCodeIndent,KEYWORD(".pack"),ulPackSize);
4689 printLine(GUICookie,szString);
4690 }
4691 if(ulClassSize != 0xFFFFFFFF)
4692 {
4693 sprintf_s(szString,SZSTRING_SIZE,"%s%s %d",g_szAsmCodeIndent,KEYWORD(".size"),ulClassSize);
4694 printLine(GUICookie,szString);
4695 }
4696 }
4697 DumpCustomAttributes(cl,GUICookie);
4698 // Dev11 #10745
4699 // Dump InterfaceImpl custom attributes here
4700 if (NumInterfaces > 0 && g_fShowCA)
4701 {
4702 hr = g_pImport->EnumInit(
4703 mdtInterfaceImpl,
4704 cl,
4705 &hEnumII);
4706 if (FAILED(hr))
4707 {
4708 printError(GUICookie,RstrUTF(IDS_E_ENUMINIT));
4709 g_tkVarOwner = tkVarOwner;
4710 return FALSE;
4711 }
4712
4713 ASSERT_AND_CHECK(NumInterfaces == g_pImport->EnumGetCount(&hEnumII));
4714 CQuickBytes out;
4715 mdTypeRef crInterface;
4716 for (i = 0; g_pImport->EnumNext(&hEnumII, &ii); i++)
4717 {
4718 HENUMInternal hEnum;
4719 mdCustomAttribute tkCA;
4720 bool fFirst = true;
4721
4722 if (FAILED(g_pImport->EnumInit(mdtCustomAttribute, ii,&hEnum)))
4723 {
4724 return FALSE;
4725 }
4726 while(g_pImport->EnumNext(&hEnum,&tkCA) && RidFromToken(tkCA))
4727 {
4728 if (fFirst)
4729 {
4730 // Print .interfaceImpl type {type} before the custom attribute list
4731 szptr = szString;
4732 szptr += sprintf_s(szptr, SZSTRING_SIZE, "%s.%s ", g_szAsmCodeIndent, KEYWORD("interfaceimpl type"));
4733 if (FAILED(g_pImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
4734 {
4735 char sz[2048];
4736 sprintf_s(sz, 2048, RstrUTF(IDS_E_INVALIDRECORD), ii);
4737 printError(GUICookie, sz);
4738 g_tkVarOwner = tkVarOwner;
4739 return FALSE;
4740 }
4741 if(g_pImport->IsValidToken(crInterface))
4742 PrettyPrintToken(szString, crInterface, g_pImport,GUICookie,cl);
4743 else
4744 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG("INVALID TOKEN: 0x%8.8X"),crInterface);
4745 printLine(GUICookie,szString);
4746 out.Shrink(0);
4747
4748 szptr = szString;
4749 fFirst = false;
4750 }
4751 DumpCustomAttribute(tkCA,GUICookie,false);
4752 }
4753 g_pImport->EnumClose( &hEnum);
4754 }
4755 // The assertion will fire if the enumerator is bad
4756 _ASSERTE(NumInterfaces == i);
4757
4758 g_pImport->EnumClose(&hEnumII);
4759 }
4760 DumpGenericParsCA(cl,GUICookie);
4761 DumpPermissions(cl,GUICookie);
4762 }
4763
4764 // Dump method impls declared in this class whose implementing methods belong somewhere else:
4765 if(WhatToDump & 1) // 1 - dump headers
4766 {
4767 for(i = 0; i < g_NumMI; i++)
4768 {
4769 if(((*g_pmi_list)[i].tkClass == cl)&&((*g_pmi_list)[i].tkBodyParent != cl))
4770 {
4771 BOOL bOverridingTypeSpec;
4772 PrettyPrintOverrideDecl(i,szString,GUICookie,cl,&bOverridingTypeSpec);
4773 strcat_s(szString, SZSTRING_SIZE,KEYWORD(" with "));
4774
4775 if (bOverridingTypeSpec)
4776 {
4777 // If PrettyPrintOverrideDecl printed the 'method' keyword, we need it here as well
4778 // to satisfy the following grammar rule (simplified):
4779 // _OVERRIDE METHOD_ ... DCOLON methodName ... WITH_ METHOD_ ... DCOLON methodName ...
4780 strcat_s(szString, SZSTRING_SIZE,KEYWORD("method "));
4781 }
4782
4783 PrettyPrintToken(szString, (*g_pmi_list)[i].tkBody, g_pImport,GUICookie,0);
4784 printLine(GUICookie,szString);
4785 }
4786 }
4787 }
4788 if(WhatToDump & 2) // nested classes
4789 {
4790 BOOL fRegetClassLayout=FALSE;
4791 DWORD dwMode = g_Mode;
4792
4793 if(g_Mode == MODE_DUMP_CLASS)
4794 g_Mode = MODE_DUMP_ALL;
4795
4796 for(i = 0; i < g_NumClasses; i++)
4797 {
4798 if(g_cl_enclosing[i] == cl)
4799 {
4800 DumpClass(g_cl_list[i],dwEntryPointToken,GUICookie,WhatToDumpOrig);
4801 fRegetClassLayout = TRUE;
4802 }
4803 }
4804 if(fRegetClassLayout) GetClassLayout(cl,&ulPackSize,&ulClassSize);
4805 g_Mode = dwMode;
4806 }
4807
4808 if(WhatToDump & 4)
4809 {
4810 DumpMembers(cl, pszNamespace, pszClassName, dwClassAttrs, dwEntryPointToken,GUICookie);
4811 }
4812
4813 if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
4814 szptr = szString;
4815 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s %s// end of class ",g_szAsmCodeIndent,UNSCOPE(),COMMENT((char*)0));
4816 if(*pszNamespace != 0) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s.",ProperName(pszNamespace));
4817 sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s", ProperName(pszClassName),COMMENT((char*)-1));
4818 printLine(GUICookie,szString);
4819 printLine(GUICookie,"");
4820 g_tkVarOwner = tkVarOwner;
4821 return TRUE;
4822}
4823
4824
4825
4826void DumpGlobalMethods(DWORD dwEntryPointToken)
4827{
4828 HENUMInternal hEnumMethod;
4829 mdToken FuncToken;
4830 DWORD i;
4831 CQuickBytes qbMemberSig;
4832
4833 if (FAILED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod)))
4834 return;
4835
4836 for (i = 0; g_pImport->EnumNext(&hEnumMethod, &FuncToken); i++)
4837 {
4838 if (i == 0)
4839 {
4840 printLine(g_pFile,"");
4841 printLine(g_pFile,COMMENT("// ================== GLOBAL METHODS ========================="));
4842 printLine(g_pFile,"");
4843 }
4844 if(DumpMethod(FuncToken, NULL, dwEntryPointToken, g_pFile, TRUE)&&
4845 (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)) break;
4846 }
4847 g_pImport->EnumClose(&hEnumMethod);
4848 if(i)
4849 {
4850 printLine(g_pFile,"");
4851 printLine(g_pFile,COMMENT("// ============================================================="));
4852 printLine(g_pFile,"");
4853 }
4854}
4855
4856void DumpGlobalFields()
4857{
4858 HENUMInternal hEnum;
4859 mdToken FieldToken;
4860 DWORD i;
4861 CQuickBytes qbMemberSig;
4862
4863 if (FAILED(g_pImport->EnumGlobalFieldsInit(&hEnum)))
4864 return;
4865
4866 for (i = 0; g_pImport->EnumNext(&hEnum, &FieldToken); i++)
4867 {
4868 if (i == 0)
4869 {
4870 printLine(g_pFile,"");
4871 printLine(g_pFile,COMMENT("// ================== GLOBAL FIELDS =========================="));
4872 printLine(g_pFile,"");
4873 }
4874 if(DumpField(FieldToken, NULL, g_pFile, TRUE)&&
4875 (g_Mode == MODE_DUMP_CLASS_METHOD || g_Mode == MODE_DUMP_CLASS_METHOD_SIG)) break;
4876 }
4877 g_pImport->EnumClose(&hEnum);
4878 if(i)
4879 {
4880 printLine(g_pFile,"");
4881 printLine(g_pFile,COMMENT("// ============================================================="));
4882 printLine(g_pFile,"");
4883 }
4884}
4885
4886void DumpVTables(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
4887{
4888 IMAGE_COR_VTABLEFIXUP *pFixup,*pDummy;
4889 DWORD iCount;
4890 DWORD i;
4891 USHORT iSlot;
4892 char* szStr = &szString[0];
4893
4894 if (VAL32(CORHeader->VTableFixups.VirtualAddress) == 0) return;
4895
4896 sprintf_s(szString,SZSTRING_SIZE,"// VTableFixup Directory:");
4897 printLine(GUICookie,szStr);
4898
4899 // Pull back a pointer to the guy.
4900 iCount = VAL32(CORHeader->VTableFixups.Size) / sizeof(IMAGE_COR_VTABLEFIXUP);
4901 if ((g_pPELoader->getVAforRVA(VAL32(CORHeader->VTableFixups.VirtualAddress), (void **) &pFixup) == FALSE)
4902 ||(g_pPELoader->getVAforRVA(VAL32(CORHeader->VTableFixups.VirtualAddress)+VAL32(CORHeader->VTableFixups.Size)-1, (void **) &pDummy) == FALSE))
4903 {
4904 printLine(GUICookie,RstrUTF(IDS_E_VTFUTABLE));
4905 goto exit;
4906 }
4907
4908 // Walk every v-table fixup entry and dump the slots.
4909 for (i=0; i<iCount; i++)
4910 {
4911 sprintf_s(szString,SZSTRING_SIZE,"// IMAGE_COR_VTABLEFIXUP[%d]:", i);
4912 printLine(GUICookie,szStr);
4913 sprintf_s(szString,SZSTRING_SIZE,"// RVA: 0x%08x", VAL32(pFixup->RVA));
4914 printLine(GUICookie,szStr);
4915 sprintf_s(szString,SZSTRING_SIZE,"// Count: 0x%04x", VAL16(pFixup->Count));
4916 printLine(GUICookie,szStr);
4917 sprintf_s(szString,SZSTRING_SIZE,"// Type: 0x%04x", VAL16(pFixup->Type));
4918 printLine(GUICookie,szStr);
4919
4920 BYTE *pSlot;
4921 if (g_pPELoader->getVAforRVA(VAL32(pFixup->RVA), (void **) &pSlot) == FALSE)
4922 {
4923 printLine(GUICookie,RstrUTF(IDS_E_BOGUSRVA));
4924 goto NextEntry;
4925 }
4926
4927 for (iSlot=0; iSlot<pFixup->Count; iSlot++)
4928 {
4929 mdMethodDef tkMethod = VAL32(*(DWORD *) pSlot);
4930 if (pFixup->Type & VAL16(COR_VTABLE_32BIT))
4931 {
4932 sprintf_s(szString,SZSTRING_SIZE,"// [0x%04x] (0x%08x)", iSlot, tkMethod);
4933 pSlot += sizeof(DWORD);
4934 }
4935 else
4936 {
4937 sprintf_s(szString,SZSTRING_SIZE,"// [0x%04x] (0x%16x)", iSlot, VAL64(*(unsigned __int64 *) pSlot));
4938 pSlot += sizeof(unsigned __int64);
4939 }
4940 printLine(GUICookie,szStr);
4941
4942 ValidateToken(tkMethod, mdtMethodDef);
4943 }
4944
4945 // Pointer to next fixup entry.
4946NextEntry:
4947 ++pFixup;
4948 }
4949
4950exit:
4951 printLine(GUICookie,"");
4952}
4953
4954
4955void DumpEATTable(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
4956{
4957 BYTE *pFixup,*pDummy;
4958 DWORD iCount;
4959 DWORD BufferRVA;
4960 DWORD i;
4961 char* szStr = &szString[0];
4962
4963 sprintf_s(szString,SZSTRING_SIZE,"// Export Address Table Jumps:");
4964 printLine(GUICookie,szStr);
4965
4966 if (VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress) == 0)
4967 {
4968 printLine(GUICookie,RstrUTF(IDS_E_NODATA));
4969 return;
4970 }
4971
4972 // Pull back a pointer to the guy.
4973 iCount = VAL32(CORHeader->ExportAddressTableJumps.Size) / IMAGE_COR_EATJ_THUNK_SIZE;
4974 if ((g_pPELoader->getVAforRVA(VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress), (void **) &pFixup) == FALSE)
4975 ||(g_pPELoader->getVAforRVA(VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress)+VAL32(CORHeader->ExportAddressTableJumps.Size)-1, (void **) &pDummy) == FALSE))
4976 {
4977 printLine(GUICookie,RstrUTF(IDS_E_EATJTABLE));
4978 goto exit;
4979 }
4980
4981 // Quick sanity check on the linker.
4982 if (VAL32(CORHeader->ExportAddressTableJumps.Size) % IMAGE_COR_EATJ_THUNK_SIZE)
4983 {
4984 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_EATJSIZE),
4985 VAL32(CORHeader->ExportAddressTableJumps.Size), IMAGE_COR_EATJ_THUNK_SIZE);
4986 printLine(GUICookie,szStr);
4987 }
4988
4989 // Walk every v-table fixup entry and dump the slots.
4990 BufferRVA = VAL32(CORHeader->ExportAddressTableJumps.VirtualAddress);
4991 for (i=0; i<iCount; i++)
4992 {
4993 ULONG ReservedFlag = VAL32(*(ULONG *) (pFixup + sizeof(ULONG)));
4994 sprintf_s(szString,SZSTRING_SIZE,"// Fixup Jump Entry [%d], at RVA 0x%08x:", i, BufferRVA);
4995 printLine(GUICookie,szStr);
4996 sprintf_s(szString,SZSTRING_SIZE,"// RVA of slot: 0x%08x", VAL32(*(ULONG *) pFixup));
4997 printLine(GUICookie,szStr);
4998 sprintf_s(szString,SZSTRING_SIZE,"// Reserved flag: 0x%08x", ReservedFlag);
4999 printLine(GUICookie,szStr);
5000 if (ReservedFlag != 0)
5001 {
5002 printLine(GUICookie,RstrUTF(IDS_E_RESFLAGS));
5003 }
5004
5005 pFixup += IMAGE_COR_EATJ_THUNK_SIZE;
5006 BufferRVA += IMAGE_COR_EATJ_THUNK_SIZE;
5007 }
5008
5009exit:
5010 printLine(GUICookie,"");
5011}
5012
5013
5014void DumpCodeManager(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
5015{
5016 char* szStr = &szString[0];
5017 sprintf_s(szString,SZSTRING_SIZE,"// Code Manager Table:");
5018 printLine(GUICookie,szStr);
5019 if (!VAL32(CORHeader->CodeManagerTable.Size))
5020 {
5021 sprintf_s(szString,SZSTRING_SIZE,"// default");
5022 printLine(GUICookie,szStr);
5023 return;
5024 }
5025
5026 const GUID *pcm;
5027 if (g_pPELoader->getVAforRVA(VAL32(CORHeader->CodeManagerTable.VirtualAddress), (void **) &pcm) == FALSE)
5028 {
5029 printLine(GUICookie,RstrUTF(IDS_E_CODEMGRTBL));
5030 return;
5031 }
5032
5033 sprintf_s(szString,SZSTRING_SIZE,"// [index] ID");
5034 printLine(GUICookie,szStr);
5035 ULONG iCount = VAL32(CORHeader->CodeManagerTable.Size) / sizeof(GUID);
5036 for (ULONG i=0; i<iCount; i++)
5037 {
5038 WCHAR rcguid[128];
5039 GUID Guid = *pcm;
5040 SwapGuid(&Guid);
5041 StringFromGUID2(Guid, rcguid, NumItems(rcguid));
5042 sprintf_s(szString,SZSTRING_SIZE,"// [0x%08x] %S", i, rcguid);
5043 printLine(GUICookie,szStr);
5044 pcm++;
5045 }
5046 printLine(GUICookie,"");
5047}
5048
5049void DumpSectionHeaders(IMAGE_SECTION_HEADER* pSH, USHORT nSH, void* GUICookie)
5050{
5051 char* szStr = &szString[0];
5052 char name[16];
5053 printLine(GUICookie,"");
5054 strcpy_s(szString,SZSTRING_SIZE,"// Image sections:");
5055 printLine(GUICookie,szStr);
5056 for(USHORT iSH=0; iSH < nSH; iSH++,pSH++)
5057 {
5058 strncpy_s(name,16,(const char*)(pSH->Name),8);
5059 name[8]=0;
5060 sprintf_s(szString,SZSTRING_SIZE,"// %s",name);
5061 printLine(GUICookie,szStr);
5062 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Virtual Size", pSH->Misc.VirtualSize);
5063 printLine(GUICookie,szStr);
5064 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Virtual Address", pSH->VirtualAddress);
5065 printLine(GUICookie,szStr);
5066 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Size of Raw Data", pSH->SizeOfRawData);
5067 printLine(GUICookie,szStr);
5068 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Pointer to Raw Data", pSH->PointerToRawData);
5069 printLine(GUICookie,szStr);
5070 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Pointer to Relocations", pSH->PointerToRelocations);
5071 printLine(GUICookie,szStr);
5072 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Pointer to Linenumbers", pSH->PointerToLinenumbers);
5073 printLine(GUICookie,szStr);
5074 sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Number of Relocations", pSH->NumberOfRelocations);
5075 printLine(GUICookie,szStr);
5076 sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Number of Linenumbers", pSH->NumberOfLinenumbers);
5077 printLine(GUICookie,szStr);
5078 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Characteristics", pSH->Characteristics);
5079 printLine(GUICookie,szStr);
5080 if((pSH->Characteristics & IMAGE_SCN_SCALE_INDEX))
5081 {
5082 strcpy_s(szString,SZSTRING_SIZE,"// SCALE_INDEX");
5083 printLine(GUICookie,szStr);
5084 }
5085 if((pSH->Characteristics & IMAGE_SCN_CNT_CODE))
5086 {
5087 strcpy_s(szString,SZSTRING_SIZE,"// CNT_CODE");
5088 printLine(GUICookie,szStr);
5089 }
5090 if((pSH->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA))
5091 {
5092 strcpy_s(szString,SZSTRING_SIZE,"// CNT_INITIALIZED_DATA");
5093 printLine(GUICookie,szStr);
5094 }
5095 if((pSH->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
5096 {
5097 strcpy_s(szString,SZSTRING_SIZE,"// CNT_UNINITIALIZED_DATA");
5098 printLine(GUICookie,szStr);
5099 }
5100 if((pSH->Characteristics & IMAGE_SCN_NO_DEFER_SPEC_EXC))
5101 {
5102 strcpy_s(szString,SZSTRING_SIZE,"// NO_DEFER_SPEC_EXC");
5103 printLine(GUICookie,szStr);
5104 }
5105 if((pSH->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL))
5106 {
5107 strcpy_s(szString,SZSTRING_SIZE,"// LNK_NRELOC_OVFL");
5108 printLine(GUICookie,szStr);
5109 }
5110 if((pSH->Characteristics & IMAGE_SCN_MEM_DISCARDABLE))
5111 {
5112 strcpy_s(szString,SZSTRING_SIZE,"// MEM_DISCARDABLE");
5113 printLine(GUICookie,szStr);
5114 }
5115 if((pSH->Characteristics & IMAGE_SCN_MEM_NOT_CACHED))
5116 {
5117 strcpy_s(szString,SZSTRING_SIZE,"// MEM_NOT_CACHED");
5118 printLine(GUICookie,szStr);
5119 }
5120 if((pSH->Characteristics & IMAGE_SCN_MEM_NOT_PAGED))
5121 {
5122 strcpy_s(szString,SZSTRING_SIZE,"// MEM_NOT_PAGED");
5123 printLine(GUICookie,szStr);
5124 }
5125 if((pSH->Characteristics & IMAGE_SCN_MEM_SHARED))
5126 {
5127 strcpy_s(szString,SZSTRING_SIZE,"// MEM_SHARED");
5128 printLine(GUICookie,szStr);
5129 }
5130 if((pSH->Characteristics & IMAGE_SCN_MEM_EXECUTE))
5131 {
5132 strcpy_s(szString,SZSTRING_SIZE,"// MEM_EXECUTE");
5133 printLine(GUICookie,szStr);
5134 }
5135 if((pSH->Characteristics & IMAGE_SCN_MEM_READ))
5136 {
5137 strcpy_s(szString,SZSTRING_SIZE,"// MEM_READ");
5138 printLine(GUICookie,szStr);
5139 }
5140 if((pSH->Characteristics & IMAGE_SCN_MEM_WRITE))
5141 {
5142 strcpy_s(szString,SZSTRING_SIZE,"// MEM_WRITE");
5143 printLine(GUICookie,szStr);
5144 }
5145 printLine(GUICookie,"");
5146 }
5147}
5148
5149void DumpBaseReloc(const char *szName, IMAGE_DATA_DIRECTORY *pDir, void* GUICookie)
5150{
5151 char* szStr = &szString[0];
5152 sprintf_s(szString,SZSTRING_SIZE,"// %s", szName);
5153 printLine(GUICookie,szStr);
5154 if (!VAL32(pDir->Size))
5155 {
5156 printLine(GUICookie,RstrUTF(IDS_E_NODATA));
5157 return;
5158 }
5159 char *pBegin, *pEnd;
5160 DWORD *pdw, i, Nentries;
5161 WORD *pw;
5162 if (g_pPELoader->getVAforRVA(VAL32(pDir->VirtualAddress), (void **) &pBegin) == FALSE)
5163 {
5164 printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
5165 return;
5166 }
5167 pEnd = pBegin + VAL32(pDir->Size);
5168 for(pdw = (DWORD*)pBegin; pdw < (DWORD*)pEnd; )
5169 {
5170 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Page RVA", *pdw);
5171 printLine(GUICookie,szStr);
5172 pdw++;
5173 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Block Size", *pdw);
5174 printLine(GUICookie,szStr);
5175 Nentries = (*pdw - 2*sizeof(DWORD)) / sizeof(WORD);
5176 pdw++;
5177 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Number of Entries", Nentries);
5178 printLine(GUICookie,szStr);
5179
5180 for(i = 1, pw = (WORD*)pdw; i <= Nentries; i++, pw++)
5181 {
5182 sprintf_s(szString,SZSTRING_SIZE,"// Entry %d: Type 0x%x Offset 0x%08x", i, ((*pw)>>12), ((*pw)&0x0FFF));
5183 printLine(GUICookie,szStr);
5184 }
5185 if((Nentries & 1)) pw++; // to make pdw DWORD-aligned
5186 pdw = (DWORD*)pw;
5187 printLine(GUICookie,"");
5188 }
5189}
5190void DumpIAT(const char *szName, IMAGE_DATA_DIRECTORY *pDir, void* GUICookie)
5191{
5192 char* szStr = &szString[0];
5193
5194 sprintf_s(szString,SZSTRING_SIZE,"// %s", szName);
5195 printLine(GUICookie,szStr);
5196 if (!VAL32(pDir->Size))
5197 {
5198 printLine(GUICookie,RstrUTF(IDS_E_NODATA));
5199 return;
5200 }
5201
5202 const char *szDLLName;
5203 const IMAGE_IMPORT_DESCRIPTOR *pImportDesc;
5204
5205 if (g_pPELoader->getVAforRVA(VAL32(pDir->VirtualAddress), (void **) &pImportDesc) == FALSE)
5206 {
5207 printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
5208 return;
5209 }
5210
5211 const DWORD *pImportTableID;
5212 while (VAL32(pImportDesc->FirstThunk))
5213 {
5214 if (g_pPELoader->getVAforRVA(VAL32(pImportDesc->Name), (void **) &szDLLName) == FALSE ||
5215 g_pPELoader->getVAforRVA(VAL32(pImportDesc->FirstThunk), (void **) &pImportTableID) == FALSE)
5216 {
5217 printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
5218 return;
5219 }
5220
5221 sprintf_s(szString,SZSTRING_SIZE,"// DLL : %s", szDLLName);
5222 printLine(GUICookie,szStr);
5223 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Import Address Table", VAL32(pImportDesc->FirstThunk));
5224 printLine(GUICookie,szStr);
5225 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Import Name Table", VAL32(pImportDesc->Name));
5226 printLine(GUICookie,szStr);
5227 sprintf_s(szString,SZSTRING_SIZE,"// %-8d Time Date Stamp", VAL32(pImportDesc->TimeDateStamp));
5228 printLine(GUICookie,szStr);
5229 sprintf_s(szString,SZSTRING_SIZE,"// %-8d Index of First Forwarder Reference", VAL32(pImportDesc->ForwarderChain));
5230 printLine(GUICookie,szStr);
5231 sprintf_s(szString,SZSTRING_SIZE,"//");
5232 printLine(GUICookie,szStr);
5233
5234 for ( ; VAL32(*pImportTableID); pImportTableID++)
5235 {
5236 if (VAL32(*pImportTableID) & 0x80000000)
5237 sprintf_s(szString,SZSTRING_SIZE,"// by Ordinal %d", VAL32(*pImportTableID) & 0x7fffffff);
5238 else
5239 {
5240 const IMAGE_IMPORT_BY_NAME *pName;
5241 if(g_pPELoader->getVAforRVA(VAL32(*pImportTableID) & 0x7fffffff, (void **) &pName))
5242 sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x %s", VAL16(pName->Hint), pName->Name);
5243 else
5244 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x bad RVA of IMAGE_IMPORT_BY_NAME", VAL32(*pImportTableID));
5245 }
5246 printLine(GUICookie,szStr);
5247 }
5248 printLine(GUICookie,"");
5249
5250 // Next import descriptor.
5251 pImportDesc++;
5252 }
5253}
5254
5255struct MDStreamHeader
5256{
5257 DWORD Reserved;
5258 BYTE Major;
5259 BYTE Minor;
5260 BYTE Heaps;
5261 BYTE Rid;
5262 ULONGLONG MaskValid;
5263 ULONGLONG Sorted;
5264};
5265
5266void DumpMetadataHeader(const char *szName, IMAGE_DATA_DIRECTORY *pDir, void* GUICookie)
5267{
5268 char* szStr = &szString[0];
5269
5270 printLine(GUICookie,"");
5271 sprintf_s(szString,SZSTRING_SIZE,"// %s", szName);
5272 printLine(GUICookie,szStr);
5273 if (!VAL32(pDir->Size))
5274 {
5275 printLine(GUICookie,RstrUTF(IDS_E_NODATA));
5276 return;
5277 }
5278
5279 const STORAGESIGNATURE *pSSig;
5280 char verstr[1024];
5281
5282 if (g_pPELoader->getVAforRVA(VAL32(pDir->VirtualAddress), (void **) &pSSig) == FALSE)
5283 {
5284 printLine(GUICookie,RstrUTF(IDS_E_IMPORTDATA));
5285 return;
5286 }
5287 strcpy_s(szString,SZSTRING_SIZE,"// Storage Signature:");
5288 printLine(GUICookie,szStr);
5289 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Signature", VAL32(pSSig->lSignature));
5290 printLine(GUICookie,szStr);
5291 sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Major Version", VAL16(pSSig->iMajorVer));
5292 printLine(GUICookie,szStr);
5293 sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Minor Version", VAL16(pSSig->iMinorVer));
5294 printLine(GUICookie,szStr);
5295 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Extra Data Offset", VAL32(pSSig->iExtraData));
5296 printLine(GUICookie,szStr);
5297 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Version String Length", VAL32(pSSig->iVersionString));
5298 printLine(GUICookie,szStr);
5299 memset(verstr,0,1024);
5300 strncpy_s(verstr,1024,(const char*)(pSSig->pVersion),VAL32(pSSig->iVersionString));
5301 sprintf_s(szString,SZSTRING_SIZE,"// '%s' Version String", verstr);
5302 printLine(GUICookie,szStr);
5303
5304 size_t pb = (size_t)pSSig;
5305 pb += (3*sizeof(DWORD)+2*sizeof(WORD)+VAL32(pSSig->iVersionString)+3)&~3;
5306 PSTORAGEHEADER pSHdr = (PSTORAGEHEADER)pb;
5307 strcpy_s(szString,SZSTRING_SIZE,"// Storage Header:");
5308 printLine(GUICookie,szStr);
5309 sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Flags", pSHdr->fFlags);
5310 printLine(GUICookie,szStr);
5311 short nStr = VAL16(pSHdr->iStreams);
5312 sprintf_s(szString,SZSTRING_SIZE,"// 0x%04x Number of Streams", nStr);
5313 if(nStr > 5)
5314 {
5315 strcat_s(szString, SZSTRING_SIZE, " -- BOGUS!");
5316 nStr = 5;
5317 }
5318 printLine(GUICookie,szStr);
5319
5320 PSTORAGESTREAM pStr = (PSTORAGESTREAM)(pSHdr+1);
5321 BYTE* pbMDstream = NULL;
5322 size_t cbMDstream = 0;
5323 for(short iStr = 1; iStr <= nStr; iStr++)
5324 {
5325 sprintf_s(szString,SZSTRING_SIZE,"// Stream %d:",iStr);
5326 printLine(GUICookie,szStr);
5327 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Offset", VAL32(pStr->iOffset));
5328 printLine(GUICookie,szStr);
5329 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Size", VAL32(pStr->iSize));
5330 printLine(GUICookie,szStr);
5331 sprintf_s(szString,SZSTRING_SIZE,"// '%s' Name", pStr->rcName);
5332 printLine(GUICookie,szStr);
5333 if((strcmp(pStr->rcName,"#-")==0)||(strcmp(pStr->rcName,"#~")==0))
5334 {
5335 pbMDstream = (BYTE*)pSSig + VAL32(pStr->iOffset);
5336 cbMDstream = VAL32(pStr->iSize);
5337 }
5338
5339 pb = (size_t)pStr;
5340 pb += (2*sizeof(DWORD)+strlen(pStr->rcName)+1+3)&~3;
5341 pStr = (PSTORAGESTREAM)pb;
5342 }
5343 if((pbMDstream)&&(cbMDstream >= sizeof(MDStreamHeader)))
5344 {
5345 printLine(GUICookie,"");
5346 strcpy_s(szString,SZSTRING_SIZE,"// Metadata Stream Header:");
5347 printLine(GUICookie,szStr);
5348
5349 MDStreamHeader* pMDSH = (MDStreamHeader*)pbMDstream;
5350 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x Reserved", VAL32(pMDSH->Reserved));
5351 printLine(GUICookie,szStr);
5352 sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Major", pMDSH->Major);
5353 printLine(GUICookie,szStr);
5354 sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Minor", pMDSH->Minor);
5355 printLine(GUICookie,szStr);
5356 sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Heaps", pMDSH->Heaps);
5357 printLine(GUICookie,szStr);
5358 sprintf_s(szString,SZSTRING_SIZE,"// 0x%02x Rid", pMDSH->Rid);
5359 printLine(GUICookie,szStr);
5360 sprintf_s(szString,SZSTRING_SIZE,"// 0x%016I64x MaskValid", (ULONGLONG)GET_UNALIGNED_VAL64(&(pMDSH->MaskValid)));
5361 printLine(GUICookie,szStr);
5362 sprintf_s(szString,SZSTRING_SIZE,"// 0x%016I64x Sorted", (ULONGLONG)GET_UNALIGNED_VAL64(&(pMDSH->Sorted)));
5363 printLine(GUICookie,szStr);
5364 }
5365}
5366void DumpEntryPoint(DWORD dwAddrOfEntryPoint,DWORD dwEntryPointSize,void* GUICookie)
5367{
5368 BYTE* pB;
5369 char* szStr = &szString[0];
5370 char* szptr = szStr+2;
5371 DWORD i;
5372
5373 printLine(GUICookie,"");
5374 strcpy_s(szString,SZSTRING_SIZE,"// Entry point code:");
5375 printLine(GUICookie,szStr);
5376 if (g_pPELoader->getVAforRVA(dwAddrOfEntryPoint, (void **) &pB) == FALSE)
5377 {
5378 printLine(GUICookie,"Bad RVA of entry point");
5379 return;
5380 }
5381 if(dwEntryPointSize == 48) pB -= 32;
5382 // on IA64, AddressOfEntryPoint points at PLabelDescriptor, not at the stub itself
5383 for(i=0; i<dwEntryPointSize; i++)
5384 {
5385 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X ",pB[i]);
5386 }
5387 printLine(GUICookie,szStr);
5388}
5389
5390#define DUMP_DIRECTORY(szName, Directory) \
5391 sprintf_s(szString,SZSTRING_SIZE,"// 0x%08x [0x%08x] address [size] of " szName, \
5392 VAL32(Directory.VirtualAddress), VAL32(Directory.Size)); \
5393 printLine(GUICookie,szStr)
5394
5395#ifdef _PREFAST_
5396#pragma warning(push)
5397#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
5398#endif
5399void DumpHeader(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
5400{
5401 char* szStr = &szString[0];
5402
5403 DWORD dwAddrOfEntryPoint=0, dwEntryPointSize=0;
5404
5405 PIMAGE_DOS_HEADER pDOSHeader = g_pPELoader->dosHeader();
5406
5407 strcpy_s(szString,SZSTRING_SIZE,"// ----- DOS Header:");
5408 printLine(GUICookie,szStr);
5409 sprintf_s(szString,SZSTRING_SIZE,"// Magic: 0x%04x", VAL16(pDOSHeader->e_magic));
5410 printLine(GUICookie,szStr);
5411 sprintf_s(szString,SZSTRING_SIZE,"// Bytes on last page: 0x%04x", VAL16(pDOSHeader->e_cblp));
5412 printLine(GUICookie,szStr);
5413 sprintf_s(szString,SZSTRING_SIZE,"// Pages in file: 0x%04x", VAL16(pDOSHeader->e_cp));
5414 printLine(GUICookie,szStr);
5415 sprintf_s(szString,SZSTRING_SIZE,"// Relocations: 0x%04x", VAL16(pDOSHeader->e_crlc));
5416 printLine(GUICookie,szStr);
5417 sprintf_s(szString,SZSTRING_SIZE,"// Size of header (paragraphs):0x%04x", VAL16(pDOSHeader->e_cparhdr));
5418 printLine(GUICookie,szStr);
5419 sprintf_s(szString,SZSTRING_SIZE,"// Min extra paragraphs: 0x%04x", VAL16(pDOSHeader->e_minalloc));
5420 printLine(GUICookie,szStr);
5421 sprintf_s(szString,SZSTRING_SIZE,"// Max extra paragraphs: 0x%04x", VAL16(pDOSHeader->e_maxalloc));
5422 printLine(GUICookie,szStr);
5423 sprintf_s(szString,SZSTRING_SIZE,"// Initial (relative) SS: 0x%04x", VAL16(pDOSHeader->e_ss));
5424 printLine(GUICookie,szStr);
5425 sprintf_s(szString,SZSTRING_SIZE,"// Initial SP: 0x%04x", VAL16(pDOSHeader->e_sp));
5426 printLine(GUICookie,szStr);
5427 sprintf_s(szString,SZSTRING_SIZE,"// Checksum: 0x%04x", VAL16(pDOSHeader->e_csum));
5428 printLine(GUICookie,szStr);
5429 sprintf_s(szString,SZSTRING_SIZE,"// Initial IP: 0x%04x", VAL16(pDOSHeader->e_ip));
5430 printLine(GUICookie,szStr);
5431 sprintf_s(szString,SZSTRING_SIZE,"// Initial (relative) CS: 0x%04x", VAL16(pDOSHeader->e_ip));
5432 printLine(GUICookie,szStr);
5433 sprintf_s(szString,SZSTRING_SIZE,"// File addr. of reloc table: 0x%04x", VAL16(pDOSHeader->e_lfarlc));
5434 printLine(GUICookie,szStr);
5435 sprintf_s(szString,SZSTRING_SIZE,"// Overlay number: 0x%04x", VAL16(pDOSHeader->e_ovno));
5436 printLine(GUICookie,szStr);
5437 sprintf_s(szString,SZSTRING_SIZE,"// OEM identifier: 0x%04x", VAL16(pDOSHeader->e_oemid));
5438 printLine(GUICookie,szStr);
5439 sprintf_s(szString,SZSTRING_SIZE,"// OEM info: 0x%04x", VAL16(pDOSHeader->e_oeminfo));
5440 printLine(GUICookie,szStr);
5441 sprintf_s(szString,SZSTRING_SIZE,"// File addr. of COFF header: 0x%04x", VAL16(pDOSHeader->e_lfanew));
5442 printLine(GUICookie,szStr);
5443
5444 strcpy_s(szString,SZSTRING_SIZE,"// ----- COFF/PE Headers:");
5445 printLine(GUICookie,szStr);
5446 sprintf_s(szString,SZSTRING_SIZE,"// Signature: 0x%08x", VAL32(g_pPELoader->Signature()));
5447 printLine(GUICookie,szStr);
5448
5449 strcpy_s(szString,SZSTRING_SIZE,"// ----- COFF Header:");
5450 printLine(GUICookie,szStr);
5451
5452 PIMAGE_FILE_HEADER pCOFF = g_pPELoader->coffHeader();
5453 sprintf_s(szString,SZSTRING_SIZE,"// Machine: 0x%04x", VAL16(pCOFF->Machine));
5454 printLine(GUICookie,szStr);
5455 sprintf_s(szString,SZSTRING_SIZE,"// Number of sections: 0x%04x", VAL16(pCOFF->NumberOfSections));
5456 printLine(GUICookie,szStr);
5457 sprintf_s(szString,SZSTRING_SIZE,"// Time-date stamp: 0x%08x", VAL32(pCOFF->TimeDateStamp));
5458 printLine(GUICookie,szStr);
5459 sprintf_s(szString,SZSTRING_SIZE,"// Ptr to symbol table: 0x%08x", VAL32(pCOFF->PointerToSymbolTable));
5460 printLine(GUICookie,szStr);
5461 sprintf_s(szString,SZSTRING_SIZE,"// Number of symbols: 0x%08x", VAL32(pCOFF->NumberOfSymbols));
5462 printLine(GUICookie,szStr);
5463 sprintf_s(szString,SZSTRING_SIZE,"// Size of optional header: 0x%04x", VAL16(pCOFF->SizeOfOptionalHeader));
5464 printLine(GUICookie,szStr);
5465 sprintf_s(szString,SZSTRING_SIZE,"// Characteristics: 0x%04x", VAL16(pCOFF->Characteristics));
5466 printLine(GUICookie,szStr);
5467
5468
5469 if (g_pPELoader->IsPE32())
5470 {
5471 IMAGE_NT_HEADERS32 *pNTHeader = g_pPELoader->ntHeaders32();
5472 IMAGE_OPTIONAL_HEADER32 *pOptHeader = &pNTHeader->OptionalHeader;
5473
5474 strcpy_s(szString,SZSTRING_SIZE,"// ----- PE Optional Header (32 bit):");
5475 printLine(GUICookie,szStr);
5476
5477 sprintf_s(szString,SZSTRING_SIZE,"// Magic: 0x%04x", VAL16(pOptHeader->Magic));
5478 printLine(GUICookie,szStr);
5479 sprintf_s(szString,SZSTRING_SIZE,"// Major linker version: 0x%02x", VAL16(pOptHeader->MajorLinkerVersion));
5480 printLine(GUICookie,szStr);
5481 sprintf_s(szString,SZSTRING_SIZE,"// Minor linker version: 0x%02x", VAL16(pOptHeader->MinorLinkerVersion));
5482 printLine(GUICookie,szStr);
5483 sprintf_s(szString,SZSTRING_SIZE,"// Size of code: 0x%08x", VAL32(pOptHeader->SizeOfCode));
5484 printLine(GUICookie,szStr);
5485 sprintf_s(szString,SZSTRING_SIZE,"// Size of init.data: 0x%08x", VAL32(pOptHeader->SizeOfInitializedData));
5486 printLine(GUICookie,szStr);
5487 sprintf_s(szString,SZSTRING_SIZE,"// Size of uninit.data: 0x%08x", VAL32(pOptHeader->SizeOfUninitializedData));
5488 printLine(GUICookie,szStr);
5489 sprintf_s(szString,SZSTRING_SIZE,"// Addr. of entry point: 0x%08x", VAL32(pOptHeader->AddressOfEntryPoint));
5490 printLine(GUICookie,szStr);
5491 dwAddrOfEntryPoint = VAL32(pOptHeader->AddressOfEntryPoint);
5492 dwEntryPointSize = 6;
5493 sprintf_s(szString,SZSTRING_SIZE,"// Base of code: 0x%08x", VAL32(pOptHeader->BaseOfCode));
5494 printLine(GUICookie,szStr);
5495 sprintf_s(szString,SZSTRING_SIZE,"// Base of data: 0x%08x", VAL32(pOptHeader->BaseOfData));
5496 printLine(GUICookie,szStr);
5497 sprintf_s(szString,SZSTRING_SIZE,"// Image base: 0x%08x", VAL32(pOptHeader->ImageBase));
5498 printLine(GUICookie,szStr);
5499 sprintf_s(szString,SZSTRING_SIZE,"// Section alignment: 0x%08x", VAL32(pOptHeader->SectionAlignment));
5500 printLine(GUICookie,szStr);
5501 sprintf_s(szString,SZSTRING_SIZE,"// File alignment: 0x%08x", VAL32(pOptHeader->FileAlignment));
5502 printLine(GUICookie,szStr);
5503 sprintf_s(szString,SZSTRING_SIZE,"// Major OS version: 0x%04x", VAL16(pOptHeader->MajorOperatingSystemVersion));
5504 printLine(GUICookie,szStr);
5505 sprintf_s(szString,SZSTRING_SIZE,"// Minor OS version: 0x%04x", VAL16(pOptHeader->MinorOperatingSystemVersion));
5506 printLine(GUICookie,szStr);
5507 sprintf_s(szString,SZSTRING_SIZE,"// Major image version: 0x%04x", VAL16(pOptHeader->MajorImageVersion));
5508 printLine(GUICookie,szStr);
5509 sprintf_s(szString,SZSTRING_SIZE,"// Minor image version: 0x%04x", VAL16(pOptHeader->MinorImageVersion));
5510 printLine(GUICookie,szStr);
5511 sprintf_s(szString,SZSTRING_SIZE,"// Major subsystem version: 0x%04x", VAL16(pOptHeader->MajorSubsystemVersion));
5512 printLine(GUICookie,szStr);
5513 sprintf_s(szString,SZSTRING_SIZE,"// Minor subsystem version: 0x%04x", VAL16(pOptHeader->MinorSubsystemVersion));
5514 printLine(GUICookie,szStr);
5515 sprintf_s(szString,SZSTRING_SIZE,"// Size of image: 0x%08x", VAL32(pOptHeader->SizeOfImage));
5516 printLine(GUICookie,szStr);
5517 sprintf_s(szString,SZSTRING_SIZE,"// Size of headers: 0x%08x", VAL32(pOptHeader->SizeOfHeaders));
5518 printLine(GUICookie,szStr);
5519 sprintf_s(szString,SZSTRING_SIZE,"// Checksum: 0x%08x", VAL32(pOptHeader->CheckSum));
5520 printLine(GUICookie,szStr);
5521 sprintf_s(szString,SZSTRING_SIZE,"// Subsystem: 0x%04x", VAL16(pOptHeader->Subsystem));
5522 printLine(GUICookie,szStr);
5523 sprintf_s(szString,SZSTRING_SIZE,"// DLL characteristics: 0x%04x", VAL16(pOptHeader->DllCharacteristics));
5524 printLine(GUICookie,szStr);
5525 sprintf_s(szString,SZSTRING_SIZE,"// Size of stack reserve: 0x%08x", VAL32(pOptHeader->SizeOfStackReserve));
5526 printLine(GUICookie,szStr);
5527 sprintf_s(szString,SZSTRING_SIZE,"// Size of stack commit: 0x%08x", VAL32(pOptHeader->SizeOfStackCommit));
5528 printLine(GUICookie,szStr);
5529 sprintf_s(szString,SZSTRING_SIZE,"// Size of heap reserve: 0x%08x", VAL32(pOptHeader->SizeOfHeapReserve));
5530 printLine(GUICookie,szStr);
5531 sprintf_s(szString,SZSTRING_SIZE,"// Size of heap commit: 0x%08x", VAL32(pOptHeader->SizeOfHeapCommit));
5532 printLine(GUICookie,szStr);
5533 sprintf_s(szString,SZSTRING_SIZE,"// Loader flags: 0x%08x", VAL32(pOptHeader->LoaderFlags));
5534 printLine(GUICookie,szStr);
5535 sprintf_s(szString,SZSTRING_SIZE,"// Directories: 0x%08x", VAL32(pOptHeader->NumberOfRvaAndSizes));
5536 printLine(GUICookie,szStr);
5537 DUMP_DIRECTORY("Export Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
5538 DUMP_DIRECTORY("Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
5539 DUMP_DIRECTORY("Resource Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
5540 DUMP_DIRECTORY("Exception Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]);
5541 DUMP_DIRECTORY("Security Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
5542 DUMP_DIRECTORY("Base Relocation Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
5543 DUMP_DIRECTORY("Debug Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]);
5544 DUMP_DIRECTORY("Architecture Specific: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE]);
5545 DUMP_DIRECTORY("Global Pointer: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR]);
5546 DUMP_DIRECTORY("TLS Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]);
5547 DUMP_DIRECTORY("Load Config Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]);
5548 DUMP_DIRECTORY("Bound Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]);
5549 DUMP_DIRECTORY("Import Address Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]);
5550 DUMP_DIRECTORY("Delay Load IAT: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]);
5551 DUMP_DIRECTORY("CLR Header: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]);
5552 printLine(GUICookie,"");
5553
5554 DumpSectionHeaders((IMAGE_SECTION_HEADER*)(pOptHeader+1),pNTHeader->FileHeader.NumberOfSections,GUICookie);
5555 DumpBaseReloc("Base Relocation Table",&pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC],GUICookie);
5556 DumpIAT("Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT],GUICookie);
5557 DumpIAT("Delay Load Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT],GUICookie);
5558 }
5559 else
5560 {
5561 IMAGE_NT_HEADERS64 *pNTHeader = g_pPELoader->ntHeaders64();
5562 IMAGE_OPTIONAL_HEADER64 *pOptHeader = &pNTHeader->OptionalHeader;
5563
5564 strcpy_s(szString,SZSTRING_SIZE,"// ----- PE Optional Header (64 bit):");
5565 printLine(GUICookie,szStr);
5566 sprintf_s(szString,SZSTRING_SIZE,"// Magic: 0x%04x", VAL16(pOptHeader->Magic));
5567 printLine(GUICookie,szStr);
5568 sprintf_s(szString,SZSTRING_SIZE,"// Major linker version: 0x%02x", VAL16(pOptHeader->MajorLinkerVersion));
5569 printLine(GUICookie,szStr);
5570 sprintf_s(szString,SZSTRING_SIZE,"// Minor linker version: 0x%02x", VAL16(pOptHeader->MinorLinkerVersion));
5571 printLine(GUICookie,szStr);
5572 sprintf_s(szString,SZSTRING_SIZE,"// Size of code: 0x%08x", VAL32(pOptHeader->SizeOfCode));
5573 printLine(GUICookie,szStr);
5574 sprintf_s(szString,SZSTRING_SIZE,"// Size of init.data: 0x%08x", VAL32(pOptHeader->SizeOfInitializedData));
5575 printLine(GUICookie,szStr);
5576 sprintf_s(szString,SZSTRING_SIZE,"// Size of uninit.data: 0x%08x", VAL32(pOptHeader->SizeOfUninitializedData));
5577 printLine(GUICookie,szStr);
5578 sprintf_s(szString,SZSTRING_SIZE,"// Addr. of entry point: 0x%08x", VAL32(pOptHeader->AddressOfEntryPoint));
5579 printLine(GUICookie,szStr);
5580 dwAddrOfEntryPoint = VAL32(pOptHeader->AddressOfEntryPoint);
5581 dwEntryPointSize = (VAL16(pCOFF->Machine)==IMAGE_FILE_MACHINE_IA64) ? 48 : 12;
5582 sprintf_s(szString,SZSTRING_SIZE,"// Base of code: 0x%08x", VAL32(pOptHeader->BaseOfCode));
5583 printLine(GUICookie,szStr);
5584 sprintf_s(szString,SZSTRING_SIZE,"// Image base: 0x%016I64x", VAL64(pOptHeader->ImageBase));
5585 printLine(GUICookie,szStr);
5586 sprintf_s(szString,SZSTRING_SIZE,"// Section alignment: 0x%08x", VAL32(pOptHeader->SectionAlignment));
5587 printLine(GUICookie,szStr);
5588 sprintf_s(szString,SZSTRING_SIZE,"// File alignment: 0x%08x", VAL32(pOptHeader->FileAlignment));
5589 printLine(GUICookie,szStr);
5590 sprintf_s(szString,SZSTRING_SIZE,"// Major OS version: 0x%04x", VAL16(pOptHeader->MajorOperatingSystemVersion));
5591 printLine(GUICookie,szStr);
5592 sprintf_s(szString,SZSTRING_SIZE,"// Minor OS version: 0x%04x", VAL16(pOptHeader->MinorOperatingSystemVersion));
5593 printLine(GUICookie,szStr);
5594 sprintf_s(szString,SZSTRING_SIZE,"// Major image version: 0x%04x", VAL16(pOptHeader->MajorImageVersion));
5595 printLine(GUICookie,szStr);
5596 sprintf_s(szString,SZSTRING_SIZE,"// Minor image version: 0x%04x", VAL16(pOptHeader->MinorImageVersion));
5597 printLine(GUICookie,szStr);
5598 sprintf_s(szString,SZSTRING_SIZE,"// Major subsystem version: 0x%04x", VAL16(pOptHeader->MajorSubsystemVersion));
5599 printLine(GUICookie,szStr);
5600 sprintf_s(szString,SZSTRING_SIZE,"// Minor subsystem version: 0x%04x", VAL16(pOptHeader->MinorSubsystemVersion));
5601 printLine(GUICookie,szStr);
5602 sprintf_s(szString,SZSTRING_SIZE,"// Size of image: 0x%08x", VAL32(pOptHeader->SizeOfImage));
5603 printLine(GUICookie,szStr);
5604 sprintf_s(szString,SZSTRING_SIZE,"// Size of headers: 0x%08x", VAL32(pOptHeader->SizeOfHeaders));
5605 printLine(GUICookie,szStr);
5606 sprintf_s(szString,SZSTRING_SIZE,"// Checksum: 0x%08x", VAL32(pOptHeader->CheckSum));
5607 printLine(GUICookie,szStr);
5608 sprintf_s(szString,SZSTRING_SIZE,"// Subsystem: 0x%04x", VAL16(pOptHeader->Subsystem));
5609 printLine(GUICookie,szStr);
5610 sprintf_s(szString,SZSTRING_SIZE,"// DLL characteristics: 0x%04x", VAL16(pOptHeader->DllCharacteristics));
5611 printLine(GUICookie,szStr);
5612 sprintf_s(szString,SZSTRING_SIZE,"// Size of stack reserve: 0x%016I64x", VAL64(pOptHeader->SizeOfStackReserve));
5613 printLine(GUICookie,szStr);
5614 sprintf_s(szString,SZSTRING_SIZE,"// Size of stack commit: 0x%016I64x", VAL64(pOptHeader->SizeOfStackCommit));
5615 printLine(GUICookie,szStr);
5616 sprintf_s(szString,SZSTRING_SIZE,"// Size of heap reserve: 0x%016I64x", VAL64(pOptHeader->SizeOfHeapReserve));
5617 printLine(GUICookie,szStr);
5618 sprintf_s(szString,SZSTRING_SIZE,"// Size of heap commit: 0x%016I64x", VAL64(pOptHeader->SizeOfHeapCommit));
5619 printLine(GUICookie,szStr);
5620 sprintf_s(szString,SZSTRING_SIZE,"// Loader flags: 0x%08x", VAL32(pOptHeader->LoaderFlags));
5621 printLine(GUICookie,szStr);
5622 sprintf_s(szString,SZSTRING_SIZE,"// Directories: 0x%08x", VAL32(pOptHeader->NumberOfRvaAndSizes));
5623 printLine(GUICookie,szStr);
5624
5625 DUMP_DIRECTORY("Export Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
5626 DUMP_DIRECTORY("Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
5627 DUMP_DIRECTORY("Resource Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
5628 DUMP_DIRECTORY("Exception Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]);
5629 DUMP_DIRECTORY("Security Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
5630 DUMP_DIRECTORY("Base Relocation Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]);
5631 DUMP_DIRECTORY("Debug Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]);
5632 DUMP_DIRECTORY("Architecture Specific: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE]);
5633 DUMP_DIRECTORY("Global Pointer: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR]);
5634 DUMP_DIRECTORY("TLS Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]);
5635 DUMP_DIRECTORY("Load Config Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]);
5636 DUMP_DIRECTORY("Bound Import Directory: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]);
5637 DUMP_DIRECTORY("Import Address Table: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]);
5638 DUMP_DIRECTORY("Delay Load IAT: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]);
5639 DUMP_DIRECTORY("CLR Header: ", pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]);
5640 printLine(GUICookie,"");
5641
5642 DumpSectionHeaders((IMAGE_SECTION_HEADER*)(pOptHeader+1),pNTHeader->FileHeader.NumberOfSections,GUICookie);
5643 DumpBaseReloc("Base Relocation Table",&pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC],GUICookie);
5644 DumpIAT("Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT],GUICookie);
5645 DumpIAT("Delay Load Import Address Table", &pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT],GUICookie);
5646 }
5647 if(dwAddrOfEntryPoint != 0) DumpEntryPoint(dwAddrOfEntryPoint,dwEntryPointSize,GUICookie);
5648 printLine(GUICookie,"");
5649 printLine(GUICookie,"");
5650 if (!CORHeader)
5651 {
5652 printLine(GUICookie,RstrUTF(IDS_E_COMIMAGE));
5653 return;
5654 }
5655 strcpy_s(szString,SZSTRING_SIZE,"// ----- CLR Header:");
5656 printLine(GUICookie,szStr);
5657
5658 sprintf_s(szString,SZSTRING_SIZE,"// Header size: 0x%08x", VAL32(CORHeader->cb));
5659 printLine(GUICookie,szStr);
5660 sprintf_s(szString,SZSTRING_SIZE,"// Major runtime version: 0x%04x", VAL16(CORHeader->MajorRuntimeVersion));
5661 printLine(GUICookie,szStr);
5662 sprintf_s(szString,SZSTRING_SIZE,"// Minor runtime version: 0x%04x", VAL16(CORHeader->MinorRuntimeVersion));
5663 printLine(GUICookie,szStr);
5664 // Metadata
5665 DUMP_DIRECTORY("Metadata Directory: ", CORHeader->MetaData);
5666 sprintf_s(szString,SZSTRING_SIZE,"// Flags: 0x%08x", VAL32(CORHeader->Flags));
5667 printLine(GUICookie,szStr);
5668 sprintf_s(szString,SZSTRING_SIZE,"// Entry point token: 0x%08x",
5669 VAL32(IMAGE_COR20_HEADER_FIELD(*CORHeader, EntryPointToken)));
5670 printLine(GUICookie,szStr);
5671 // Binding
5672 DUMP_DIRECTORY("Resources Directory: ", CORHeader->Resources);
5673 DUMP_DIRECTORY("Strong Name Signature: ", CORHeader->StrongNameSignature);
5674 DUMP_DIRECTORY("CodeManager Table: ", CORHeader->CodeManagerTable);
5675
5676 // Fixups
5677 DUMP_DIRECTORY("VTableFixups Directory: ", CORHeader->VTableFixups);
5678 DUMP_DIRECTORY("Export Address Table: ", CORHeader->ExportAddressTableJumps);
5679
5680 // Managed Native Code
5681 DUMP_DIRECTORY("Precompile Header: ", CORHeader->ManagedNativeHeader);
5682
5683 DumpMetadataHeader("Metadata Header",&(CORHeader->MetaData),GUICookie);
5684}
5685#ifdef _PREFAST_
5686#pragma warning(pop)
5687#endif
5688
5689
5690void DumpHeaderDetails(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
5691{
5692 printLine(GUICookie,"");
5693 DumpCodeManager(CORHeader,GUICookie);
5694 printLine(GUICookie,"");
5695 DumpVTables(CORHeader,GUICookie);
5696 printLine(GUICookie,"");
5697 DumpEATTable(CORHeader,GUICookie);
5698 printLine(GUICookie,"");
5699}
5700
5701
5702void WritePerfData(const char *KeyDesc, const char *KeyName, const char *UnitDesc, const char *UnitName, void* Value, BOOL IsInt)
5703{
5704
5705 DWORD BytesWritten;
5706
5707 if(!g_fDumpToPerfWriter) return;
5708
5709 if (!g_PerfDataFilePtr)
5710 {
5711 if((g_PerfDataFilePtr = WszCreateFile(W("c:\\temp\\perfdata.dat"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL) ) == INVALID_HANDLE_VALUE)
5712 {
5713 printLine(NULL,"PefTimer::LogStoppedTime(): Unable to open the FullPath file. No performance data will be generated");
5714 g_fDumpToPerfWriter = FALSE;
5715 return;
5716 }
5717 WriteFile(g_PerfDataFilePtr,"ExecTime=0\r\n",13,&BytesWritten,NULL);
5718 WriteFile(g_PerfDataFilePtr,"ExecUnit=bytes\r\n",17,&BytesWritten,NULL);
5719 WriteFile(g_PerfDataFilePtr,"ExecUnitDescr=File Size\r\n",26,&BytesWritten,NULL);
5720 WriteFile(g_PerfDataFilePtr,"ExeciDirection=False\r\n",23,&BytesWritten,NULL);
5721 }
5722
5723 char ValueStr[10];
5724 char TmpStr[201];
5725
5726 if (IsInt)
5727 {
5728 sprintf_s(ValueStr,10,"%d",(int)*(int*)Value);
5729 }
5730 else
5731 {
5732 sprintf_s(ValueStr,10,"%5.2f",(float)*(float*)Value);
5733 }
5734 sprintf_s(TmpStr, 201, "%s=%s\r\n", KeyName, ValueStr);
5735 WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
5736
5737 sprintf_s(TmpStr, 201, "%s Descr=%s\r\n", KeyName, KeyDesc);
5738 WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
5739
5740 sprintf_s(TmpStr, 201, "%s Unit=%s\r\n", KeyName, UnitName);
5741 WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
5742
5743 sprintf_s(TmpStr, 201, "%s Unit Descr=%s\r\n", KeyName, UnitDesc);
5744 WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
5745
5746 sprintf_s(TmpStr, 201, "%s IDirection=%s\r\n", KeyName, "False");
5747 WriteFile(g_PerfDataFilePtr, TmpStr, (DWORD)strlen(TmpStr), &BytesWritten, NULL);
5748}
5749
5750void WritePerfDataInt(const char *KeyDesc, const char *KeyName, const char *UnitDesc, const char *UnitName, int Value)
5751{
5752 WritePerfData(KeyDesc,KeyName,UnitDesc,UnitName, (void*)&Value, TRUE);
5753}
5754void WritePerfDataFloat(const char *KeyDesc, const char *KeyName, const char *UnitDesc, const char *UnitName, float Value)
5755{
5756 WritePerfData(KeyDesc,KeyName,UnitDesc,UnitName, (void*)&Value, FALSE);
5757}
5758
5759
5760IMetaDataTables *pITables = NULL;
5761//ULONG sizeRec, count;
5762//int size, size2;
5763int metaSize = 0;
5764__int64 fTableSeen;
5765inline void TableSeen(unsigned long n) { fTableSeen |= (I64(1) << n); }
5766inline int IsTableSeen(unsigned long n) { return (fTableSeen & (I64(1) << n)) ? 1 : 0;}
5767inline void TableSeenReset() { fTableSeen = 0;}
5768
5769void DumpTable(unsigned long Table, const char *TableName, void* GUICookie)
5770{
5771 char *szStr = &szString[0];
5772 const char **ppTableName = 0;
5773 int size;
5774 ULONG sizeRec, count;
5775
5776 // Record that this table has been seen.
5777 TableSeen(Table);
5778
5779 // If no name passed in, get from table info.
5780 if (!TableName)
5781 ppTableName = &TableName;
5782
5783 pITables->GetTableInfo(Table, &sizeRec, &count, NULL, NULL, ppTableName);
5784 if(count > 0)
5785 {
5786 metaSize += size = count * sizeRec;
5787 WritePerfDataInt(TableName,TableName,"count","count",count);
5788 WritePerfDataInt(TableName,TableName,"bytes","bytes",size);
5789 sprintf_s(szString,SZSTRING_SIZE,"// %-14s- %4d (%d bytes)", TableName, count, size);
5790 printLine(GUICookie,szStr);
5791 }
5792}
5793
5794
5795
5796#ifdef _PREFAST_
5797#pragma warning(push)
5798#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
5799#endif
5800void DumpStatistics(IMAGE_COR20_HEADER *CORHeader, void* GUICookie)
5801{
5802 int fileSize, miscPESize, miscCOMPlusSize, methodHeaderSize, methodBodySize;
5803 int methodBodies, fatHeaders, tinyHeaders, deprecatedHeaders;
5804 int size, size2;
5805 int fatSections, smallSections;
5806 ULONG methodDefs;
5807 ULONG i;
5808 ULONG sizeRec, count;
5809 char buf[MAX_MEMBER_LENGTH];
5810 char* szStr = &szString[0];
5811
5812 TableSeenReset();
5813 metaSize = 0;
5814
5815 sprintf_s(szString,SZSTRING_SIZE,"// File size : %d", fileSize = SafeGetFileSize(g_pPELoader->getHFile(), NULL));
5816 printLine(GUICookie,szStr);
5817
5818 WritePerfDataInt("FileSize","FileSize","standard byte","bytes",fileSize);
5819
5820 if (g_pPELoader->IsPE32())
5821 {
5822 size = VAL32(((IMAGE_DOS_HEADER*) g_pPELoader->getHModule())->e_lfanew) +
5823 sizeof(IMAGE_NT_HEADERS32) - sizeof(IMAGE_OPTIONAL_HEADER32) +
5824 VAL16(g_pPELoader->ntHeaders32()->FileHeader.SizeOfOptionalHeader) +
5825 VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER);
5826 size2 = (size + VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.FileAlignment) - 1) & ~(VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.FileAlignment) - 1);
5827 }
5828 else
5829 {
5830 size = VAL32(((IMAGE_DOS_HEADER*) g_pPELoader->getHModule())->e_lfanew) +
5831 sizeof(IMAGE_NT_HEADERS64) - sizeof(IMAGE_OPTIONAL_HEADER64) +
5832 VAL16(g_pPELoader->ntHeaders64()->FileHeader.SizeOfOptionalHeader) +
5833 VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER);
5834 size2 = (size + VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.FileAlignment) - 1) & ~(VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.FileAlignment) - 1);
5835 }
5836
5837 DWORD sizeOfHeaders;
5838
5839 if (g_pPELoader->IsPE32())
5840 {
5841 sizeOfHeaders = VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.SizeOfHeaders);
5842
5843 WritePerfDataInt("PE header size", "PE header size", "standard byte", "bytes", sizeOfHeaders);
5844 WritePerfDataInt("PE header size used", "PE header size used", "standard byte", "bytes", size);
5845 WritePerfDataFloat("PE header size", "PE header size", "percentage", "percentage", (float)((sizeOfHeaders * 100) / fileSize));
5846 sprintf_s(szString,SZSTRING_SIZE,"// PE header size : %d (%d used) (%5.2f%%)",
5847 sizeOfHeaders, size, (double) (sizeOfHeaders * 100) / fileSize);
5848
5849 printLine(GUICookie,szStr);
5850 miscPESize = 0;
5851
5852 for (i=0; i < VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.NumberOfRvaAndSizes); ++i)
5853 {
5854 // Skip the CLR header.
5855 if (i != 15) miscPESize += (int) VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.DataDirectory[i].Size);
5856 }
5857 }
5858 else
5859 {
5860 sizeOfHeaders = VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.SizeOfHeaders);
5861
5862 WritePerfDataInt("PE+ header size", "PE header size", "standard byte", "bytes", sizeOfHeaders);
5863 WritePerfDataInt("PE+ header size used", "PE header size used", "standard byte", "bytes", size);
5864 WritePerfDataFloat("PE+ header size", "PE header size", "percentage", "percentage", (float)((sizeOfHeaders * 100) / fileSize));
5865
5866 sprintf_s(szString,SZSTRING_SIZE,"// PE header size : %d (%d used) (%5.2f%%)",
5867 sizeOfHeaders, size, (double) (sizeOfHeaders * 100) / fileSize);
5868
5869 printLine(GUICookie,szStr);
5870 miscPESize = 0;
5871
5872 for (i=0; i < VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.NumberOfRvaAndSizes); ++i)
5873 {
5874 // Skip the CLR header.
5875 if (i != IMAGE_DIRECTORY_ENTRY_COMHEADER) miscPESize += (int) VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.DataDirectory[i].Size);
5876 }
5877 }
5878
5879 WritePerfDataInt("PE additional info", "PE additional info", "standard byte", "bytes",miscPESize);
5880 WritePerfDataFloat("PE additional info", "PE additional info", "percentage", "percent", (float) ((miscPESize * 100) / fileSize));
5881
5882 sprintf_s(buf, MAX_MEMBER_LENGTH, "PE additional info : %d", miscPESize);
5883 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (miscPESize * 100) / fileSize);
5884 printLine(GUICookie,szStr);
5885
5886 WORD numberOfSections;
5887 if (g_pPELoader->IsPE32())
5888 {
5889 numberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
5890 }
5891 else
5892 {
5893 numberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
5894 }
5895
5896 WritePerfDataInt("Num.of PE sections", "Num.of PE sections", "Nbr of sections", "sections",numberOfSections);
5897 sprintf_s(szString,SZSTRING_SIZE,"// Num.of PE sections : %d", numberOfSections);
5898
5899 printLine(GUICookie,szStr);
5900
5901 WritePerfDataInt("CLR header size", "CLR header size", "byte", "bytes",VAL32(CORHeader->cb));
5902 WritePerfDataFloat("CLR header size", "CLR header size", "percentage", "percent",(float) ((VAL32(CORHeader->cb) * 100) / fileSize));
5903
5904 sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR header size : %d", VAL32(CORHeader->cb));
5905 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (VAL32(CORHeader->cb) * 100) / fileSize);
5906 printLine(GUICookie,szStr);
5907
5908 DWORD dwMetaSize = g_cbMetaData;
5909 WritePerfDataInt("CLR meta-data size", "CLR meta-data size", "bytes", "bytes",dwMetaSize);
5910 WritePerfDataFloat("CLR meta-data size", "CLR meta-data size", "percentage", "percent",(float) ((dwMetaSize * 100) / fileSize));
5911
5912 sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR meta-data size : %d", dwMetaSize);
5913 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (dwMetaSize * 100) / fileSize);
5914 printLine(GUICookie,szStr);
5915
5916 IMAGE_DATA_DIRECTORY *pFirst = &CORHeader->Resources;
5917 ULONG32 iCount = (ULONG32)((BYTE *) &CORHeader->ManagedNativeHeader - (BYTE *) &CORHeader->Resources) / sizeof(IMAGE_DATA_DIRECTORY) + 1;
5918 miscCOMPlusSize = 0;
5919 for (ULONG32 iDir=0; iDir<iCount; iDir++)
5920 {
5921 miscCOMPlusSize += VAL32(pFirst->Size);
5922 pFirst++;
5923 }
5924
5925 WritePerfDataInt("CLR Additional info", "CLR Additional info", "bytes", "bytes",miscCOMPlusSize);
5926 WritePerfDataFloat("CLR Additional info", "CLR Additional info", "percentage", "percent",(float) ((miscCOMPlusSize * 100) / fileSize));
5927
5928 sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR additional info : %d", miscCOMPlusSize);
5929 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (miscCOMPlusSize * 100) / fileSize);
5930 printLine(GUICookie,szStr);
5931
5932 // Go through each method def collecting some statistics.
5933 methodHeaderSize = methodBodySize = 0;
5934 methodBodies = fatHeaders = tinyHeaders = deprecatedHeaders = fatSections = smallSections = 0;
5935 methodDefs = g_pImport->GetCountWithTokenKind(mdtMethodDef);
5936 for (i=1; i <= methodDefs; ++i) {
5937 ULONG rva;
5938 DWORD flags;
5939
5940 if (FAILED(g_pImport->GetMethodImplProps(TokenFromRid(i, mdtMethodDef), &rva, &flags)))
5941 {
5942 continue;
5943 }
5944 if ((rva != 0)&&(IsMiIL(flags) || IsMiOPTIL(flags))) // We don't handle native yet.
5945 {
5946 ++methodBodies;
5947
5948 COR_ILMETHOD_FAT *pMethod;
5949 g_pPELoader->getVAforRVA(rva, (void **) &pMethod);
5950 if (pMethod->IsFat())
5951 {
5952 ++fatHeaders;
5953
5954 methodHeaderSize += pMethod->GetSize() * 4;
5955 methodBodySize += pMethod->GetCodeSize();
5956
5957 // Add in the additional sections.
5958 BYTE *sectsBegin = (BYTE *) (pMethod->GetCode() + pMethod->GetCodeSize());
5959 const COR_ILMETHOD_SECT *pSect = pMethod->GetSect();
5960 const COR_ILMETHOD_SECT *pOldSect;
5961 if (pSect != NULL) {
5962 // Keep skipping a pointer past each section.
5963 do
5964 {
5965 pOldSect = pSect;
5966 if (((COR_ILMETHOD_SECT_FAT *) pSect)->GetKind() & CorILMethod_Sect_FatFormat)
5967 {
5968 ++fatSections;
5969 pSect = (COR_ILMETHOD_SECT *)((BYTE *) pSect + ((COR_ILMETHOD_SECT_FAT *) pSect)->GetDataSize());
5970 }
5971 else
5972 {
5973 ++smallSections;
5974 pSect = (COR_ILMETHOD_SECT *)((BYTE *) pSect + ((COR_ILMETHOD_SECT_SMALL *) pSect)->DataSize);
5975 }
5976 pSect = (COR_ILMETHOD_SECT *) (((UINT_PTR) pSect + 3) & ~3);
5977 }
5978 while (pOldSect->More());
5979
5980 // Add on the section sizes.
5981 methodHeaderSize += (int) ((BYTE *) pSect - sectsBegin);
5982 }
5983 }
5984 else if (((COR_ILMETHOD_TINY *) pMethod)->IsTiny())
5985 {
5986 ++tinyHeaders;
5987 methodHeaderSize += sizeof(COR_ILMETHOD_TINY);
5988 methodBodySize += ((COR_ILMETHOD_TINY *) pMethod)->GetCodeSize();
5989 }
5990 else
5991 {
5992 _ASSERTE(!"Unrecognized header type");
5993 }
5994 }
5995 }
5996
5997
5998 WritePerfDataInt("CLR method headers", "CLR method headers", "bytes", "bytes",methodHeaderSize);
5999 WritePerfDataFloat("CLR method headers", "CLR method headers", "percentage", "percent",(float) ((methodHeaderSize * 100) / fileSize));
6000
6001 sprintf_s(buf, MAX_MEMBER_LENGTH, "CLR method headers : %d", methodHeaderSize);
6002 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (methodHeaderSize * 100) / fileSize);
6003 printLine(GUICookie,szStr);
6004
6005 WritePerfDataInt("Managed code", "Managed code", "bytes", "bytes",methodBodySize);
6006 WritePerfDataFloat("Managed code", "Managed code", "percentage", "percent",(float) ((methodBodySize * 100) / fileSize));
6007
6008 sprintf_s(buf, MAX_MEMBER_LENGTH, "Managed code : %d", methodBodySize);
6009 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (methodBodySize * 100) / fileSize);
6010 printLine(GUICookie,szStr);
6011
6012 if (g_pPELoader->IsPE32())
6013 {
6014 DWORD sizeOfInitializedData = VAL32(g_pPELoader->ntHeaders32()->OptionalHeader.SizeOfInitializedData);
6015
6016 WritePerfDataInt("Data", "Data", "bytes", "bytes",sizeOfInitializedData);
6017 WritePerfDataFloat("Data", "Data", "percentage", "percent",(float) ((sizeOfInitializedData * 100) / fileSize));
6018
6019 sprintf_s(buf, MAX_MEMBER_LENGTH, "Data : %d", sizeOfInitializedData);
6020 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (sizeOfInitializedData * 100) / fileSize);
6021 printLine(GUICookie,szStr);
6022
6023 size = fileSize - g_pPELoader->ntHeaders32()->OptionalHeader.SizeOfHeaders - miscPESize - CORHeader->cb -
6024 g_cbMetaData - miscCOMPlusSize -
6025 sizeOfInitializedData -
6026 methodHeaderSize - methodBodySize;
6027 }
6028 else
6029 {
6030 DWORD sizeOfInitializedData = VAL32(g_pPELoader->ntHeaders64()->OptionalHeader.SizeOfInitializedData);
6031
6032 WritePerfDataInt("Data", "Data", "bytes", "bytes",sizeOfInitializedData);
6033 WritePerfDataFloat("Data", "Data", "percentage", "percent",(float) ((sizeOfInitializedData * 100) / fileSize));
6034
6035 sprintf_s(buf, MAX_MEMBER_LENGTH, "Data : %d", sizeOfInitializedData);
6036 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (sizeOfInitializedData * 100) / fileSize);
6037 printLine(GUICookie,szStr);
6038
6039 size = fileSize - g_pPELoader->ntHeaders64()->OptionalHeader.SizeOfHeaders - miscPESize - CORHeader->cb -
6040 g_cbMetaData - miscCOMPlusSize -
6041 sizeOfInitializedData -
6042 methodHeaderSize - methodBodySize;
6043 }
6044
6045 WritePerfDataInt("Unaccounted", "Unaccounted", "bytes", "bytes",size);
6046 WritePerfDataFloat("Unaccounted", "Unaccounted", "percentage", "percent",(float) ((size * 100) / fileSize));
6047
6048 sprintf_s(buf, MAX_MEMBER_LENGTH, "Unaccounted : %d", size);
6049 sprintf_s(szString,SZSTRING_SIZE,"// %-40s (%5.2f%%)", buf, (double) (size * 100) / fileSize);
6050 printLine(GUICookie,szStr);
6051
6052
6053 // Detail...
6054 if (g_pPELoader->IsPE32())
6055 {
6056 numberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
6057
6058 WritePerfDataInt("Num.of PE sections", "Num.of PE sections", "bytes", "bytes",numberOfSections);
6059 printLine(GUICookie,"");
6060 sprintf_s(szString,SZSTRING_SIZE,"// Num.of PE sections : %d", numberOfSections);
6061 printLine(GUICookie,szStr);
6062
6063 IMAGE_SECTION_HEADER *pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
6064
6065 for (i=0; i < numberOfSections; ++i)
6066 {
6067 WritePerfDataInt((char*)pSecHdr->Name,(char*)pSecHdr->Name, "bytes", "bytes",VAL32(pSecHdr->SizeOfRawData));
6068 sprintf_s(szString,SZSTRING_SIZE,"// %-8s - %d", pSecHdr->Name, VAL32(pSecHdr->SizeOfRawData));
6069 printLine(GUICookie,szStr);
6070 ++pSecHdr;
6071 }
6072 }
6073 else
6074 {
6075 numberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
6076
6077 WritePerfDataInt("Num.of PE sections", "Num.of PE sections", "bytes", "bytes",numberOfSections);
6078 printLine(GUICookie,"");
6079 sprintf_s(szString,SZSTRING_SIZE,"// Num.of PE sections : %d", numberOfSections);
6080 printLine(GUICookie,szStr);
6081
6082 IMAGE_SECTION_HEADER *pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
6083
6084 for (i=0; i < numberOfSections; ++i)
6085 {
6086 WritePerfDataInt((char*)pSecHdr->Name,(char*)pSecHdr->Name, "bytes", "bytes",pSecHdr->SizeOfRawData);
6087 sprintf_s(szString,SZSTRING_SIZE,"// %-8s - %d", pSecHdr->Name, pSecHdr->SizeOfRawData);
6088 printLine(GUICookie,szStr);
6089 ++pSecHdr;
6090 }
6091 }
6092
6093 if (FAILED(g_pPubImport->QueryInterface(IID_IMetaDataTables, (void**)&pITables)))
6094 {
6095 sprintf_s(szString,SZSTRING_SIZE,"// Unable to get IMetaDataTables interface");
6096 printLine(GUICookie,szStr);
6097 return;
6098 }
6099
6100 if (pITables == 0)
6101 {
6102 printLine(GUICookie,RstrUTF(IDS_E_MDDETAILS));
6103 return;
6104 }
6105 else
6106 {
6107 DWORD Size = g_cbMetaData;
6108 WritePerfDataInt("CLR meta-data size", "CLR meta-data size", "bytes", "bytes",Size);
6109 printLine(GUICookie,"");
6110 sprintf_s(szString,SZSTRING_SIZE,"// CLR meta-data size : %d", Size);
6111 printLine(GUICookie,szStr);
6112 metaSize = 0;
6113
6114 pITables->GetTableInfo(TBL_Module, &sizeRec, &count, NULL, NULL, NULL);
6115 TableSeen(TBL_Module);
6116 metaSize += size = count * sizeRec; \
6117 WritePerfDataInt("Module (count)", "Module (count)", "count", "count",count);
6118 WritePerfDataInt("Module (bytes)", "Module (bytes)", "bytes", "bytes",size);
6119 sprintf_s(szString,SZSTRING_SIZE,"// %-14s- %4d (%d bytes)", "Module", count, size); \
6120 printLine(GUICookie,szStr);
6121
6122 if ((count = g_pImport->GetCountWithTokenKind(mdtTypeDef)) > 0)
6123 {
6124 int flags, interfaces = 0, explicitLayout = 0;
6125 for (i=1; i <= count; ++i)
6126 {
6127 if (FAILED(g_pImport->GetTypeDefProps(TokenFromRid(i, mdtTypeDef), (ULONG *) &flags, NULL)))
6128 {
6129 continue;
6130 }
6131 if (flags & tdInterface) ++interfaces;
6132 if (flags & tdExplicitLayout) ++explicitLayout;
6133 }
6134 // Get count from table -- count reported by GetCount... doesn't include the "global" typedef.
6135 pITables->GetTableInfo(TBL_TypeDef, &sizeRec, &count, NULL, NULL, NULL);
6136 TableSeen(TBL_TypeDef);
6137 metaSize += size = count * sizeRec;
6138
6139 WritePerfDataInt("TypeDef (count)", "TypeDef (count)", "count", "count", count);
6140 WritePerfDataInt("TypeDef (bytes)", "TypeDef (bytes)", "bytes", "bytes", size);
6141 WritePerfDataInt("interfaces", "interfaces", "count", "count", interfaces);
6142 WritePerfDataInt("explicitLayout", "explicitLayout", "count", "count", explicitLayout);
6143
6144 sprintf_s(buf, MAX_MEMBER_LENGTH, " TypeDef - %4d (%d bytes)", count, size);
6145 sprintf_s(szString,SZSTRING_SIZE,"// %-38s %d interfaces, %d explicit layout", buf, interfaces, explicitLayout);
6146 printLine(GUICookie,szStr);
6147 }
6148 }
6149
6150 pITables->GetTableInfo(TBL_TypeRef, &sizeRec, &count, NULL, NULL, NULL);
6151 TableSeen(TBL_TypeRef);
6152 if (count > 0)
6153 {
6154 metaSize += size = count * sizeRec; \
6155 WritePerfDataInt("TypeRef (count)", "TypeRef (count)", "count", "count", count);
6156 WritePerfDataInt("TypeRef (bytes)", "TypeRef (bytes)", "bytes", "bytes", size);
6157 sprintf_s(szString,SZSTRING_SIZE,"// %-14s- %4d (%d bytes)", "TypeRef", count, size); \
6158 printLine(GUICookie,szStr);
6159 }
6160
6161 if ((count = g_pImport->GetCountWithTokenKind(mdtMethodDef)) > 0)
6162 {
6163 int flags, abstract = 0, native = 0;
6164 for (i=1; i <= count; ++i)
6165 {
6166 if (FAILED(g_pImport->GetMethodDefProps(TokenFromRid(i, mdtMethodDef), (DWORD *)&flags)))
6167 {
6168 sprintf_s(szString, SZSTRING_SIZE, "// Invalid MethodDef %08X record", TokenFromRid(i, mdtMethodDef));
6169 printLine(GUICookie, szStr);
6170 return;
6171 }
6172 if (flags & mdAbstract) ++abstract;
6173 }
6174 pITables->GetTableInfo(TBL_Method, &sizeRec, NULL, NULL, NULL, NULL);
6175 TableSeen(TBL_Method);
6176 if (count > 0)
6177 {
6178 metaSize += size = count * sizeRec;
6179
6180 WritePerfDataInt("MethodDef (count)", "MethodDef (count)", "count", "count", count);
6181 WritePerfDataInt("MethodDef (bytes)", "MethodDef (bytes)", "bytes", "bytes", size);
6182 WritePerfDataInt("abstract", "abstract", "count", "count", abstract);
6183 WritePerfDataInt("native", "native", "count", "count", native);
6184 WritePerfDataInt("methodBodies", "methodBodies", "count", "count", methodBodies);
6185
6186 sprintf_s(buf, MAX_MEMBER_LENGTH, " MethodDef - %4d (%d bytes)", count, size);
6187 sprintf_s(szString,SZSTRING_SIZE,"// %-38s %d abstract, %d native, %d bodies", buf, abstract, native, methodBodies);
6188 printLine(GUICookie,szStr);
6189 }
6190 }
6191
6192 if ((count = g_pImport->GetCountWithTokenKind(mdtFieldDef)) > 0)
6193 {
6194 int flags, constants = 0;
6195
6196 for (i=1; i <= count; ++i)
6197 {
6198 if (FAILED(g_pImport->GetFieldDefProps(TokenFromRid(i, mdtFieldDef), (DWORD *)&flags)))
6199 {
6200 sprintf_s(szString, SZSTRING_SIZE, "// Invalid FieldDef %08X record", TokenFromRid(i, mdtFieldDef));
6201 printLine(GUICookie, szStr);
6202 return;
6203 }
6204 if ((flags & (fdStatic|fdInitOnly)) == (fdStatic|fdInitOnly)) ++constants;
6205 }
6206 pITables->GetTableInfo(TBL_Field, &sizeRec, NULL, NULL, NULL, NULL);
6207 metaSize += size = count * sizeRec;
6208
6209 WritePerfDataInt("FieldDef (count)", "FieldDef (count)", "count", "count", count);
6210 WritePerfDataInt("FieldDef (bytes)", "FieldDef (bytes)", "bytes", "bytes", size);
6211 WritePerfDataInt("constant", "constant", "count", "count", constants);
6212
6213 sprintf_s(buf, MAX_MEMBER_LENGTH, " FieldDef - %4d (%d bytes)", count, size);
6214 sprintf_s(szString,SZSTRING_SIZE,"// %-38s %d constant", buf, constants);
6215 printLine(GUICookie,szStr);
6216 TableSeen(TBL_Field);
6217 }
6218
6219 DumpTable(TBL_MemberRef, "MemberRef", GUICookie);
6220 DumpTable(TBL_Param, "ParamDef", GUICookie);
6221 DumpTable(TBL_MethodImpl, "MethodImpl", GUICookie);
6222 DumpTable(TBL_Constant, "Constant", GUICookie);
6223 DumpTable(TBL_CustomAttribute, "CustomAttribute", GUICookie);
6224 DumpTable(TBL_FieldMarshal, "NativeType", GUICookie);
6225 DumpTable(TBL_ClassLayout, "ClassLayout", GUICookie);
6226 DumpTable(TBL_FieldLayout, "FieldLayout", GUICookie);
6227 DumpTable(TBL_StandAloneSig, "StandAloneSig", GUICookie);
6228 DumpTable(TBL_InterfaceImpl, "InterfaceImpl", GUICookie);
6229 DumpTable(TBL_PropertyMap, "PropertyMap", GUICookie);
6230 DumpTable(TBL_Property, "Property", GUICookie);
6231 DumpTable(TBL_MethodSemantics, "MethodSemantic", GUICookie);
6232 DumpTable(TBL_DeclSecurity, "Security", GUICookie);
6233 DumpTable(TBL_TypeSpec, "TypeSpec", GUICookie);
6234 DumpTable(TBL_ModuleRef, "ModuleRef", GUICookie);
6235 DumpTable(TBL_Assembly, "Assembly", GUICookie);
6236 DumpTable(TBL_AssemblyProcessor, "AssemblyProcessor", GUICookie);
6237 DumpTable(TBL_AssemblyOS, "AssemblyOS", GUICookie);
6238 DumpTable(TBL_AssemblyRef, "AssemblyRef", GUICookie);
6239 DumpTable(TBL_AssemblyRefProcessor, "AssemblyRefProcessor", GUICookie);
6240 DumpTable(TBL_AssemblyRefOS, "AssemblyRefOS", GUICookie);
6241 DumpTable(TBL_File, "File", GUICookie);
6242 DumpTable(TBL_ExportedType, "ExportedType", GUICookie);
6243 DumpTable(TBL_ManifestResource, "ManifestResource", GUICookie);
6244 DumpTable(TBL_NestedClass, "NestedClass", GUICookie);
6245
6246 // Rest of the tables.
6247 pITables->GetNumTables(&count);
6248 for (i=0; i<count; ++i)
6249 {
6250 if (!IsTableSeen(i))
6251 DumpTable(i, NULL, GUICookie);
6252 }
6253
6254 // String heap
6255 pITables->GetStringHeapSize(&sizeRec);
6256 if (sizeRec > 0)
6257 {
6258 metaSize += sizeRec;
6259 WritePerfDataInt("Strings", "Strings", "bytes", "bytes",sizeRec);
6260 sprintf_s(szString,SZSTRING_SIZE,"// Strings - %5d bytes", sizeRec);
6261 printLine(GUICookie,szStr);
6262 }
6263 // Blob heap
6264 pITables->GetBlobHeapSize(&sizeRec);
6265 if (sizeRec > 0)
6266 {
6267 metaSize += sizeRec;
6268 WritePerfDataInt("Blobs", "Blobs", "bytes", "bytes",sizeRec);
6269 sprintf_s(szString,SZSTRING_SIZE,"// Blobs - %5d bytes", sizeRec);
6270 printLine(GUICookie,szStr);
6271 }
6272 // User String Heap
6273 pITables->GetUserStringHeapSize(&sizeRec);
6274 if (sizeRec > 0)
6275 {
6276 metaSize += sizeRec;
6277 WritePerfDataInt("UserStrings", "UserStrings", "bytes", "bytes",sizeRec);
6278 sprintf_s(szString,SZSTRING_SIZE,"// UserStrings - %5d bytes", sizeRec);
6279 printLine(GUICookie,szStr);
6280 }
6281 // Guid heap
6282 pITables->GetGuidHeapSize(&sizeRec);
6283 if (sizeRec > 0)
6284 {
6285 metaSize += sizeRec;
6286 WritePerfDataInt("Guids", "Guids", "bytes", "bytes", sizeRec);
6287 sprintf_s(szString,SZSTRING_SIZE,"// Guids - %5d bytes", sizeRec);
6288 printLine(GUICookie,szStr);
6289 }
6290
6291 if (g_cbMetaData - metaSize > 0)
6292 {
6293 WritePerfDataInt("Uncategorized", "Uncategorized", "bytes", "bytes",g_cbMetaData - metaSize);
6294 sprintf_s(szString,SZSTRING_SIZE,"// Uncategorized - %5d bytes", g_cbMetaData - metaSize);
6295 printLine(GUICookie,szStr);
6296 }
6297
6298 if (miscCOMPlusSize != 0)
6299 {
6300 WritePerfDataInt("CLR additional info", "CLR additional info", "bytes", "bytes", miscCOMPlusSize);
6301 sprintf_s(szString,SZSTRING_SIZE,"// CLR additional info : %d", miscCOMPlusSize);
6302 printLine(GUICookie,"");
6303 printLine(GUICookie,szStr);
6304
6305 if (CORHeader->CodeManagerTable.Size != 0)
6306 {
6307 WritePerfDataInt("CodeManagerTable", "CodeManagerTable", "bytes", "bytes", VAL32(CORHeader->CodeManagerTable.Size));
6308 sprintf_s(szString,SZSTRING_SIZE,"// CodeManagerTable - %d", VAL32(CORHeader->CodeManagerTable.Size));
6309 printLine(GUICookie,szStr);
6310 }
6311
6312 if (CORHeader->VTableFixups.Size != 0)
6313 {
6314 WritePerfDataInt("VTableFixups", "VTableFixups", "bytes", "bytes", VAL32(CORHeader->VTableFixups.Size));
6315 sprintf_s(szString,SZSTRING_SIZE,"// VTableFixups - %d", VAL32(CORHeader->VTableFixups.Size));
6316 printLine(GUICookie,szStr);
6317 }
6318
6319 if (CORHeader->Resources.Size != 0)
6320 {
6321 WritePerfDataInt("Resources", "Resources", "bytes", "bytes", VAL32(CORHeader->Resources.Size));
6322 sprintf_s(szString,SZSTRING_SIZE,"// Resources - %d", VAL32(CORHeader->Resources.Size));
6323 printLine(GUICookie,szStr);
6324 }
6325 }
6326 WritePerfDataInt("CLR method headers", "CLR method headers", "count", "count", methodHeaderSize);
6327 sprintf_s(szString,SZSTRING_SIZE,"// CLR method headers : %d", methodHeaderSize);
6328 printLine(GUICookie,"");
6329 printLine(GUICookie,szStr);
6330 WritePerfDataInt("Num.of method bodies", "Num.of method bodies", "count", "count",methodBodies);
6331 sprintf_s(szString,SZSTRING_SIZE,"// Num.of method bodies - %d", methodBodies);
6332 printLine(GUICookie,szStr);
6333 WritePerfDataInt("Num.of fat headers", "Num.of fat headers", "count", "count", fatHeaders);
6334 sprintf_s(szString,SZSTRING_SIZE,"// Num.of fat headers - %d", fatHeaders);
6335 printLine(GUICookie,szStr);
6336 WritePerfDataInt("Num.of tiny headers", "Num.of tiny headers", "count", "count", tinyHeaders);
6337 sprintf_s(szString,SZSTRING_SIZE,"// Num.of tiny headers - %d", tinyHeaders);
6338 printLine(GUICookie,szStr);
6339
6340 if (deprecatedHeaders > 0) {
6341 WritePerfDataInt("Num.of old headers", "Num.of old headers", "count", "count", deprecatedHeaders);
6342 sprintf_s(szString,SZSTRING_SIZE,"// Num.of old headers - %d", deprecatedHeaders);
6343 printLine(GUICookie,szStr);
6344 }
6345
6346 if (fatSections != 0 || smallSections != 0) {
6347 WritePerfDataInt("Num.of fat sections", "Num.of fat sections", "count", "count", fatSections);
6348 sprintf_s(szString,SZSTRING_SIZE,"// Num.of fat sections - %d", fatSections);
6349 printLine(GUICookie,szStr);
6350
6351 WritePerfDataInt("Num.of small section", "Num.of small section", "count", "count", smallSections);
6352 sprintf_s(szString,SZSTRING_SIZE,"// Num.of small sections - %d", smallSections);
6353 printLine(GUICookie,szStr);
6354 }
6355
6356 WritePerfDataInt("Managed code", "Managed code", "bytes", "bytes", methodBodySize);
6357 sprintf_s(szString,SZSTRING_SIZE,"// Managed code : %d", methodBodySize);
6358 printLine(GUICookie,"");
6359 printLine(GUICookie,szStr);
6360
6361 if (methodBodies != 0) {
6362 WritePerfDataInt("Ave method size", "Ave method size", "bytes", "bytes", methodBodySize / methodBodies);
6363 sprintf_s(szString,SZSTRING_SIZE,"// Ave method size - %d", methodBodySize / methodBodies);
6364 printLine(GUICookie,szStr);
6365 }
6366
6367 if (pITables)
6368 pITables->Release();
6369
6370 if(g_fDumpToPerfWriter)
6371 CloseHandle((char*) g_PerfDataFilePtr);
6372}
6373#ifdef _PREFAST_
6374#pragma warning(pop)
6375#endif
6376
6377void DumpHexbytes(__inout __nullterminated char* szptr,BYTE *pb, DWORD fromPtr, DWORD toPtr, DWORD limPtr)
6378{
6379 char sz[256];
6380 int k = 0,i;
6381 DWORD curPtr = 0;
6382 bool printsz = FALSE;
6383 BYTE zero = 0;
6384 *szptr = 0;
6385 for(i = 0,k = 0,curPtr=fromPtr; curPtr < toPtr; i++,k++,curPtr++,pb++)
6386 {
6387
6388 if(k == 16)
6389 {
6390 if(printsz) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" // %s"),sz);
6391 printLine(g_pFile,szString);
6392 szptr = &szString[0];
6393 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
6394 k = 0;
6395 printsz = FALSE;
6396 }
6397 if(curPtr >= limPtr) pb = &zero; // at limPtr and after, pad with 0
6398 else
6399 {
6400 PAL_CPP_TRY
6401 {
6402 sz[k] = *pb; // check the ptr validity
6403 }
6404 PAL_CPP_CATCH_ALL
6405 {
6406 pb = &zero;
6407 } PAL_CPP_ENDTRY;
6408 }
6409 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %2.2X", *pb);
6410 if(isprint(*pb))
6411 {
6412 if(g_fDumpRTF)
6413 {
6414 if((*pb == '\\')||(*pb=='{')||(*pb=='}')) sz[k++]='\\';
6415 sz[k] = *pb;
6416 }
6417 else if(g_fDumpHTML)
6418 {
6419 if(*pb == '<') { sz[k] = 0; strcat_s(sz,256-k,LTN()); k+=(int)(strlen(LTN())); }
6420 else if(*pb == '>') { sz[k] = 0; strcat_s(sz,256-k,GTN()); k+=(int)(strlen(GTN())); }
6421 }
6422 else sz[k] = *pb;
6423 printsz = TRUE;
6424 }
6425 else
6426 {
6427 sz[k] = '.';
6428 }
6429 sz[k+1] = 0;
6430 }
6431 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),") ");
6432 if(printsz)
6433 {
6434 for(i = k; i < 16; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," ");
6435 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// %s"),sz);
6436 }
6437 printLine(g_pFile,szString);
6438}
6439
6440struct VTableEntry
6441{
6442 DWORD dwAddr;
6443 WORD wCount;
6444 WORD wType;
6445};
6446
6447struct ExpDirTable
6448{
6449 DWORD dwFlags;
6450 DWORD dwDateTime;
6451 WORD wVMajor;
6452 WORD wVMinor;
6453 DWORD dwNameRVA;
6454 DWORD dwOrdinalBase;
6455 DWORD dwNumATEntries;
6456 DWORD dwNumNamePtrs;
6457 DWORD dwAddrTableRVA;
6458 DWORD dwNamePtrRVA;
6459 DWORD dwOrdTableRVA;
6460};
6461
6462void DumpEATEntries(void* GUICookie,
6463 IMAGE_NT_HEADERS32 *pNTHeader32, IMAGE_OPTIONAL_HEADER32 *pOptHeader32,
6464 IMAGE_NT_HEADERS64 *pNTHeader64, IMAGE_OPTIONAL_HEADER64 *pOptHeader64)
6465{
6466 IMAGE_DATA_DIRECTORY *pExportDir = NULL;
6467 IMAGE_SECTION_HEADER *pSecHdr = NULL;
6468 DWORD i,j,N;
6469 BOOL bpOpt = FALSE;
6470
6471 if (g_pPELoader->IsPE32())
6472 {
6473 pExportDir = pOptHeader32->DataDirectory;
6474 pSecHdr = IMAGE_FIRST_SECTION(pNTHeader32);
6475 N = VAL16(pNTHeader32->FileHeader.NumberOfSections);
6476
6477 if (pOptHeader32->NumberOfRvaAndSizes)
6478 bpOpt = TRUE;
6479 }
6480 else
6481 {
6482 pExportDir = pOptHeader64->DataDirectory;
6483 pSecHdr = IMAGE_FIRST_SECTION(pNTHeader64);
6484 N = VAL16(pNTHeader64->FileHeader.NumberOfSections);
6485
6486 if (pOptHeader64->NumberOfRvaAndSizes)
6487 bpOpt = TRUE;
6488
6489 }
6490 if(bpOpt)
6491 {
6492 ExpDirTable *pExpTable = NULL;
6493 if(pExportDir->Size)
6494 {
6495#ifdef _DEBUG
6496 printLine(GUICookie,COMMENT((char*)0)); // start multiline comment
6497 sprintf_s(szString,SZSTRING_SIZE,"// Export dir VA=%X size=%X ",VAL32(pExportDir->VirtualAddress),VAL32(pExportDir->Size));
6498 printLine(GUICookie,szString);
6499#endif
6500 DWORD vaExpTable = VAL32(pExportDir->VirtualAddress);
6501 for (i=0; i < N; i++,pSecHdr++)
6502 {
6503 if((vaExpTable >= VAL32(pSecHdr->VirtualAddress))&&
6504 (vaExpTable < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
6505 {
6506 pExpTable = (ExpDirTable*)( g_pPELoader->base()
6507 + VAL32(pSecHdr->PointerToRawData)
6508 + vaExpTable - VAL32(pSecHdr->VirtualAddress));
6509#ifdef _DEBUG
6510 sprintf_s(szString,SZSTRING_SIZE,"// in section '%s': VA=%X Misc.VS=%X PRD=%X ",(char*)(pSecHdr->Name),
6511 VAL32(pSecHdr->VirtualAddress),VAL32(pSecHdr->Misc.VirtualSize),VAL32(pSecHdr->PointerToRawData));
6512 printLine(GUICookie,szString);
6513 sprintf_s(szString,SZSTRING_SIZE,"// Export Directory Table:"); printLine(GUICookie,szString);
6514 sprintf_s(szString,SZSTRING_SIZE,"// dwFlags = %X",VAL32(pExpTable->dwFlags)); printLine(GUICookie,szString);
6515 sprintf_s(szString,SZSTRING_SIZE,"// dwDateTime = %X",VAL32(pExpTable->dwDateTime)); printLine(GUICookie,szString);
6516 sprintf_s(szString,SZSTRING_SIZE,"// wVMajor = %X",VAL16(pExpTable->wVMajor)); printLine(GUICookie,szString);
6517 sprintf_s(szString,SZSTRING_SIZE,"// wVMinor = %X",VAL16(pExpTable->wVMinor)); printLine(GUICookie,szString);
6518 sprintf_s(szString,SZSTRING_SIZE,"// dwNameRVA = %X",VAL32(pExpTable->dwNameRVA)); printLine(GUICookie,szString);
6519 sprintf_s(szString,SZSTRING_SIZE,"// dwOrdinalBase = %X",VAL32(pExpTable->dwOrdinalBase)); printLine(GUICookie,szString);
6520 sprintf_s(szString,SZSTRING_SIZE,"// dwNumATEntries = %X",VAL32(pExpTable->dwNumATEntries)); printLine(GUICookie,szString);
6521 sprintf_s(szString,SZSTRING_SIZE,"// dwNumNamePtrs = %X",VAL32(pExpTable->dwNumNamePtrs)); printLine(GUICookie,szString);
6522 sprintf_s(szString,SZSTRING_SIZE,"// dwAddrTableRVA = %X",VAL32(pExpTable->dwAddrTableRVA)); printLine(GUICookie,szString);
6523 sprintf_s(szString,SZSTRING_SIZE,"// dwNamePtrRVA = %X",VAL32(pExpTable->dwNamePtrRVA)); printLine(GUICookie,szString);
6524 sprintf_s(szString,SZSTRING_SIZE,"// dwOrdTableRVA = %X",VAL32(pExpTable->dwOrdTableRVA)); printLine(GUICookie,szString);
6525 if(pExpTable->dwNameRVA)
6526 {
6527 char* szName;
6528 if(g_pPELoader->getVAforRVA(VAL32(pExpTable->dwNameRVA), (void **) &szName))
6529 sprintf_s(szString,SZSTRING_SIZE,"// DLL Name: '%s'",szName);
6530 else
6531 sprintf_s(szString,SZSTRING_SIZE,"// DLL Name: BAD RVA: 0x%8.8X",VAL32(pExpTable->dwNameRVA));
6532
6533 printLine(GUICookie,szString);
6534 }
6535#endif
6536 if(pExpTable->dwNumATEntries && pExpTable->dwAddrTableRVA)
6537 {
6538 DWORD* pExpAddr;
6539 BYTE *pCont;
6540 DWORD dwTokRVA;
6541 mdToken* pTok;
6542 g_pPELoader->getVAforRVA(VAL32(pExpTable->dwAddrTableRVA), (void **) &pExpAddr);
6543#ifdef _DEBUG
6544 sprintf_s(szString,SZSTRING_SIZE,"// Export Address Table:"); printLine(GUICookie,szString);
6545#endif
6546 g_nEATableRef = VAL32(pExpTable->dwNumATEntries);
6547 if (g_prEATableRef == NULL)
6548 {
6549 g_prEATableRef = new DynamicArray<EATableRef>;
6550 }
6551
6552 (*g_prEATableRef)[g_nEATableRef].tkTok = 0; // to avoid multiple reallocations of DynamicArray
6553 for(j=0; j < VAL32(pExpTable->dwNumATEntries); j++,pExpAddr++)
6554 {
6555 g_pPELoader->getVAforRVA(VAL32(*pExpAddr), (void **) &pCont);
6556#ifdef _DEBUG
6557 sprintf_s(szString,SZSTRING_SIZE,"// [%d]: RVA=%X VA=%p(",j,VAL32(*pExpAddr),pCont);
6558 DumpByteArray(szString,pCont,16,GUICookie);
6559 printLine(GUICookie,szString);
6560#endif
6561 (*g_prEATableRef)[j].tkTok = 0;
6562
6563 if(g_pPELoader->IsPE32())
6564 {
6565 dwTokRVA = VAL32(*((DWORD*)(pCont+2))); // first two bytes - JumpIndirect (0x25FF)
6566 dwTokRVA -= VAL32((DWORD)pOptHeader32->ImageBase);
6567 }
6568 else
6569 {
6570 ULONGLONG ullTokRVA;
6571 if(pNTHeader64->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64)
6572 ullTokRVA = VAL64(*((ULONGLONG*)(pCont+8)));
6573 else
6574 ullTokRVA = VAL64(*((ULONGLONG*)(pCont+2)));
6575
6576 dwTokRVA =(DWORD)(ullTokRVA - VAL64((DWORD)pOptHeader64->ImageBase));
6577 }
6578 if(g_pPELoader->getVAforRVA(dwTokRVA,(void**)&pTok))
6579 (*g_prEATableRef)[j].tkTok = VAL32(*pTok);
6580
6581 (*g_prEATableRef)[j].pszName = NULL;
6582
6583 }
6584 }
6585 if(pExpTable->dwNumNamePtrs && pExpTable->dwNamePtrRVA && pExpTable->dwOrdTableRVA)
6586 {
6587 DWORD *pNamePtr;
6588 WORD *pOrd;
6589 char* szName;
6590 g_pPELoader->getVAforRVA(VAL32(pExpTable->dwNamePtrRVA), (void **) &pNamePtr);
6591 g_pPELoader->getVAforRVA(VAL32(pExpTable->dwOrdTableRVA), (void **) &pOrd);
6592#ifdef _DEBUG
6593 sprintf_s(szString,SZSTRING_SIZE,"// Export Names:"); printLine(GUICookie,szString);
6594#endif
6595 for(j=0; j < VAL32(pExpTable->dwNumATEntries); j++,pNamePtr++,pOrd++)
6596 {
6597 g_pPELoader->getVAforRVA(VAL32(*pNamePtr), (void **) &szName);
6598#ifdef _DEBUG
6599 sprintf_s(szString,SZSTRING_SIZE,"// [%d]: NamePtr=%X Ord=%X Name='%s'",j,VAL32(*pNamePtr),*pOrd,szName);
6600 printLine(GUICookie,szString);
6601#endif
6602 (*g_prEATableRef)[VAL16(*pOrd)].pszName = szName;
6603 }
6604 }
6605 g_nEATableBase = pExpTable->dwOrdinalBase;
6606 break;
6607 }
6608 }
6609#ifdef _DEBUG
6610 printLine(GUICookie,COMMENT((char*)-1)); // end multiline comment
6611#endif
6612 }
6613 }
6614}
6615// helper to avoid mixing of SEH and stack objects with destructors
6616void DumpEATEntriesWrapper(void* GUICookie,
6617 IMAGE_NT_HEADERS32 *pNTHeader32, IMAGE_OPTIONAL_HEADER32 *pOptHeader32,
6618 IMAGE_NT_HEADERS64 *pNTHeader64, IMAGE_OPTIONAL_HEADER64 *pOptHeader64)
6619{
6620 PAL_CPP_TRY
6621 {
6622 DumpEATEntries(GUICookie, pNTHeader32, pOptHeader32, pNTHeader64, pOptHeader64);
6623 }
6624 PAL_CPP_CATCH_ALL
6625 {
6626 printError(GUICookie,"// ERROR READING EXPORT ADDRESS TABLE");
6627 if (g_prEATableRef != NULL)
6628 {
6629 SDELETE(g_prEATableRef);
6630 }
6631 g_nEATableRef = 0;
6632 }
6633 PAL_CPP_ENDTRY
6634}
6635
6636void DumpVtable(void* GUICookie)
6637{
6638 // VTable : primary processing
6639 DWORD pVTable=0;
6640 VTableEntry* pVTE;
6641 DWORD i,j,k;
6642 char* szptr;
6643
6644 IMAGE_NT_HEADERS32 *pNTHeader32 = NULL;
6645 IMAGE_OPTIONAL_HEADER32 *pOptHeader32 = NULL;
6646
6647 IMAGE_NT_HEADERS64 *pNTHeader64 = NULL;
6648 IMAGE_OPTIONAL_HEADER64 *pOptHeader64 = NULL;
6649
6650 if (g_pPELoader->IsPE32())
6651 {
6652 pNTHeader32 = g_pPELoader->ntHeaders32();
6653 pOptHeader32 = &pNTHeader32->OptionalHeader;
6654
6655 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".imagebase"),VAL32(pOptHeader32->ImageBase));
6656 printLine(GUICookie,szString);
6657 j = VAL16(pOptHeader32->Subsystem);
6658 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".file alignment"),VAL32(pOptHeader32->FileAlignment));
6659 printLine(GUICookie,szString);
6660 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".stackreserve"),VAL32(pOptHeader32->SizeOfStackReserve));
6661 printLine(GUICookie,szString);
6662 }
6663 else
6664 {
6665 pNTHeader64 = g_pPELoader->ntHeaders64();
6666 pOptHeader64 = &pNTHeader64->OptionalHeader;
6667
6668 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%016I64x", g_szAsmCodeIndent,KEYWORD(".imagebase"),VAL64(pOptHeader64->ImageBase));
6669 printLine(GUICookie,szString);
6670 j = VAL16(pOptHeader64->Subsystem);
6671 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".file alignment"),VAL32(pOptHeader64->FileAlignment));
6672 printLine(GUICookie,szString);
6673 sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%016I64x", g_szAsmCodeIndent,KEYWORD(".stackreserve"),VAL64(pOptHeader64->SizeOfStackReserve));
6674 printLine(GUICookie,szString);
6675 }
6676 szptr = &szString[0];
6677 szptr += sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%04x", g_szAsmCodeIndent,KEYWORD(".subsystem"),j);
6678 {
6679 const char* psz[15] = {"// UNKNOWN",
6680 "// NATIVE",
6681 "// WINDOWS_GUI",
6682 "// WINDOWS_CUI",
6683 "// <illegal value>",
6684 "// OS2_CUI",
6685 "// <illegal value>",
6686 "// POSIX_CUI",
6687 "// NATIVE_WINDOWS",
6688 "// WINDOWS_CE_GUI",
6689 "// EFI_APPLICATION",
6690 "// EFI_BOOT_SERVICE_DRIVER",
6691 "// EFI_RUNTIME_DRIVER",
6692 "// EFI_ROM",
6693 "// XBOX"
6694 };
6695 if(j > 14) j = 4; // <illegal value>
6696 sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s",COMMENT(psz[j]));
6697 }
6698 printLine(GUICookie,szString);
6699
6700 szptr = &szString[0];
6701 i = (DWORD)VAL32(g_CORHeader->Flags);
6702 szptr += sprintf_s(szString,SZSTRING_SIZE,"%s%s 0x%08x", g_szAsmCodeIndent,KEYWORD(".corflags"),i);
6703 if(i != 0)
6704 {
6705 char sz[256], *szp = sz;
6706 szp += sprintf_s(szp,256," // ");
6707 if(i & COMIMAGE_FLAGS_ILONLY) szp += sprintf_s(szp,256-(szp-sz)," ILONLY");
6708 if(COR_IS_32BIT_REQUIRED(i))
6709 szp += sprintf_s(szp,256-(szp-sz)," 32BITREQUIRED");
6710 if(COR_IS_32BIT_PREFERRED(i))
6711 szp += sprintf_s(szp,256-(szp-sz)," 32BITPREFERRED");
6712 if(i & COMIMAGE_FLAGS_IL_LIBRARY) szp += sprintf_s(szp,256-(szp-sz)," IL_LIBRARY");
6713 if(i & COMIMAGE_FLAGS_TRACKDEBUGDATA) szp += sprintf_s(szp,256-(szp-sz)," TRACKDEBUGDATA");
6714 szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(sz));
6715 }
6716 printLine(GUICookie,szString);
6717
6718 sprintf_s(szString,SZSTRING_SIZE,"%s// Image base: 0x%p",g_szAsmCodeIndent,g_pPELoader->base());
6719 printLine(GUICookie,COMMENT(szString));
6720
6721 DumpEATEntriesWrapper(GUICookie, pNTHeader32, pOptHeader32, pNTHeader64, pOptHeader64);
6722
6723 g_nVTableRef = 0;
6724 if(VAL32(g_CORHeader->VTableFixups.Size))
6725 {
6726 IMAGE_SECTION_HEADER *pSecHdr = NULL;
6727 DWORD dwNumberOfSections;
6728
6729 if (g_pPELoader->IsPE32())
6730 {
6731 pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
6732 dwNumberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
6733 }
6734 else
6735 {
6736 pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
6737 dwNumberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
6738 }
6739
6740 pVTable = VAL32(g_CORHeader->VTableFixups.VirtualAddress);
6741
6742 for (i=0; i < dwNumberOfSections; i++,pSecHdr++)
6743 {
6744 if(((DWORD)pVTable >= VAL32(pSecHdr->VirtualAddress))&&
6745 ((DWORD)pVTable < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
6746 {
6747 pVTE = (VTableEntry*)( g_pPELoader->base()
6748 + VAL32(pSecHdr->PointerToRawData)
6749 + pVTable - VAL32(pSecHdr->VirtualAddress));
6750 for(j=VAL32(g_CORHeader->VTableFixups.Size),k=0; j > 0; pVTE++, j-=sizeof(VTableEntry),k++)
6751 {
6752 szptr = &szString[0];
6753 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s [%d] ",g_szAsmCodeIndent,KEYWORD(".vtfixup"),VAL16(pVTE->wCount));
6754 DWORD dwSize = VAL16(pVTE->wCount) * 4;
6755 WORD wType = VAL16(pVTE->wType);
6756 if(wType & COR_VTABLE_32BIT)
6757 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("int32 "));
6758 else if(wType & COR_VTABLE_64BIT)
6759 {
6760 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("int64 "));
6761 dwSize <<= 1;
6762 }
6763 if(wType & COR_VTABLE_FROM_UNMANAGED)
6764 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("fromunmanaged "));
6765 if(wType & COR_VTABLE_CALL_MOST_DERIVED)
6766 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("callmostderived "));
6767 if(wType & 0x8 /*COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN*/)
6768 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("retainappdomain "));
6769 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("at "));
6770 szptr = DumpDataPtr(szptr,VAL32(pVTE->dwAddr), dwSize);
6771 // Walk every v-table fixup entry and dump the slots.
6772 {
6773 BYTE *pSlot;
6774 if (g_pPELoader->getVAforRVA(VAL32(pVTE->dwAddr), (void **) &pSlot))
6775 {
6776 char* szptr0 = szptr;
6777 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," //");
6778 for (WORD iSlot=0; iSlot<VAL16(pVTE->wCount); iSlot++)
6779 {
6780 mdMethodDef tkMethod = VAL32(*(DWORD *) pSlot);
6781 if (VAL16(pVTE->wType) & COR_VTABLE_32BIT)
6782 {
6783 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %08X", VAL32(*(DWORD *)pSlot));
6784 pSlot += sizeof(DWORD);
6785 }
6786 else
6787 {
6788 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %016I64X", VAL64(*(unsigned __int64 *)pSlot));
6789 pSlot += sizeof(unsigned __int64);
6790 }
6791 if (g_prVTableRef == NULL)
6792 {
6793 g_prVTableRef = new DynamicArray<VTableRef>;
6794 }
6795 (*g_prVTableRef)[g_nVTableRef].tkTok = tkMethod;
6796 (*g_prVTableRef)[g_nVTableRef].wEntry = (WORD)k;
6797 (*g_prVTableRef)[g_nVTableRef].wSlot = iSlot;
6798 g_nVTableRef++;
6799
6800 //ValidateToken(tkMethod, mdtMethodDef);
6801 }
6802 sprintf_s(szptr0,SZSTRING_REMAINING_SIZE(szptr0),COMMENT(szptr0));
6803 }
6804 else
6805 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %s",ERRORMSG(RstrUTF(IDS_E_BOGUSRVA)));
6806 }
6807 printLine(GUICookie,szString);
6808 }
6809 break;
6810 }
6811 }
6812 }
6813}
6814// MetaInfo integration:
6815void DumpMI(__in __nullterminated const char *str)
6816{
6817 static BOOL fInit = TRUE;
6818 static char* szStr = &szString[0];
6819 static void* GUICookie;
6820 char* pch;
6821 // Reset
6822 if(str == (char*)-1)
6823 {
6824 fInit = TRUE;
6825 return;
6826 }
6827 // Init
6828 if(fInit)
6829 {
6830 strcpy_s(szString,5,"// ");
6831 fInit = FALSE;
6832 GUICookie = (void*)str;
6833
6834 return;
6835 }
6836 // Normal work
6837 strcat_s(szString,SZSTRING_SIZE,str);
6838 if((pch = strchr(szStr,'\n')))
6839 {
6840 *pch = 0;
6841 printLine(GUICookie,szStr);
6842 pch++;
6843 memcpy(&szString[3], pch, strlen(pch)+1);
6844 }
6845}
6846
6847void DumpMetaInfo(__in __nullterminated const WCHAR* pwzFileName, __in_opt __nullterminated const char* pszObjFileName, void* GUICookie)
6848{
6849 const WCHAR* pch = wcsrchr(pwzFileName,L'.');
6850
6851 DumpMI((char*)GUICookie); // initialize the print function for DumpMetaInfo
6852
6853 if(pch && (!_wcsicmp(pch+1,W("lib")) || !_wcsicmp(pch+1,W("obj"))))
6854 { // This works only when all the rest does not
6855 // Init and run.
6856 if (metaDataGetDispenser(CLSID_CorMetaDataDispenser,
6857 IID_IMetaDataDispenserEx, (void **)&g_pDisp))
6858 {
6859 WCHAR *pwzObjFileName=NULL;
6860 if (pszObjFileName)
6861 {
6862 int nLength = (int) strlen(pszObjFileName)+1;
6863 pwzObjFileName = new WCHAR[nLength];
6864 memset(pwzObjFileName,0,sizeof(WCHAR)*nLength);
6865 WszMultiByteToWideChar(CP_UTF8,0,pszObjFileName,-1,pwzObjFileName,nLength);
6866 }
6867 DisplayFile((wchar_t*)pwzFileName, true, g_ulMetaInfoFilter, pwzObjFileName, DumpMI);
6868 g_pDisp->Release();
6869 g_pDisp = NULL;
6870 if (pwzObjFileName) VDELETE(pwzObjFileName);
6871 }
6872 }
6873 else
6874 {
6875 HRESULT hr = S_OK;
6876 if(g_pDisp == NULL)
6877 {
6878 hr = metaDataGetDispenser(CLSID_CorMetaDataDispenser,
6879 IID_IMetaDataDispenserEx, (void **)&g_pDisp);
6880 }
6881 if(SUCCEEDED(hr))
6882 {
6883 g_ValModuleType = ValidatorModuleTypePE;
6884 if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport(NULL);
6885 printLine(GUICookie,RstrUTF(IDS_E_MISTART));
6886 //MDInfo metaDataInfo(g_pPubImport, g_pAssemblyImport, (LPCWSTR)pwzFileName, DumpMI, g_ulMetaInfoFilter);
6887 MDInfo metaDataInfo(g_pDisp,(LPCWSTR)pwzFileName, DumpMI, g_ulMetaInfoFilter);
6888 metaDataInfo.DisplayMD();
6889 printLine(GUICookie,RstrUTF(IDS_E_MIEND));
6890 }
6891 }
6892 DumpMI((char*)-1); // reset the print function for DumpMetaInfo
6893}
6894
6895void DumpPreamble()
6896{
6897 printLine(g_pFile,"");
6898 if(g_fDumpHTML)
6899 {
6900 printLine(g_pFile, "<FONT SIZE=4><B>");
6901 }
6902 else if(g_fDumpRTF)
6903 {
6904 }
6905 sprintf_s(szString,SZSTRING_SIZE,"// Microsoft (R) .NET Framework IL Disassembler. Version " VER_FILEVERSION_STR);
6906 printLine(g_pFile,COMMENT(szString));
6907 if(g_fDumpHTML)
6908 {
6909 printLine(g_pFile, "</B></FONT>");
6910 }
6911 else if(g_fDumpRTF)
6912 {
6913 }
6914 printLine(g_pFile,"");
6915 if(g_fLimitedVisibility || (!g_fShowCA) || (!g_fDumpAsmCode)
6916 || (g_Mode & (MODE_DUMP_CLASS | MODE_DUMP_CLASS_METHOD | MODE_DUMP_CLASS_METHOD_SIG)))
6917 {
6918 printLine(g_pFile,"");
6919 printLine(g_pFile,COMMENT(RstrUTF(IDS_E_PARTDASM)));
6920 printLine(g_pFile,"");
6921 }
6922
6923 if(g_fLimitedVisibility)
6924 {
6925 strcpy_s(szString, SZSTRING_SIZE, RstrUTF(IDS_E_ONLYITEMS));
6926 if(!g_fHidePub) strcat_s(szString, SZSTRING_SIZE," Public");
6927 if(!g_fHidePriv) strcat_s(szString, SZSTRING_SIZE," Private");
6928 if(!g_fHideFam) strcat_s(szString, SZSTRING_SIZE," Family");
6929 if(!g_fHideAsm) strcat_s(szString, SZSTRING_SIZE," Assembly");
6930 if(!g_fHideFAA) strcat_s(szString, SZSTRING_SIZE," FamilyANDAssembly");
6931 if(!g_fHidePrivScope) strcat_s(szString, SZSTRING_SIZE," PrivateScope");
6932 printLine(g_pFile,COMMENT(szString));
6933 }
6934}
6935
6936void DumpSummary()
6937{
6938 ULONG i;
6939 const char *pcClass,*pcNS,*pcMember, *pcSig;
6940 char szFQN[4096];
6941 HENUMInternal hEnum;
6942 mdToken tkMember;
6943 CQuickBytes qbMemberSig;
6944 PCCOR_SIGNATURE pComSig;
6945 ULONG cComSig;
6946 DWORD dwAttrs;
6947 mdToken tkEventType;
6948
6949 printLine(g_pFile,"//============ S U M M A R Y =================================");
6950 if (SUCCEEDED(g_pImport->EnumGlobalFunctionsInit(&hEnum)))
6951 {
6952 while(g_pImport->EnumNext(&hEnum, &tkMember))
6953 {
6954 if (FAILED(g_pImport->GetNameOfMethodDef(tkMember, &pcMember)) ||
6955 FAILED(g_pImport->GetSigOfMethodDef(tkMember, &cComSig, &pComSig)))
6956 {
6957 sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the method record %08X", tkMember);
6958 printLine(g_pFile, szString);
6959 continue;
6960 }
6961 qbMemberSig.Shrink(0);
6962 pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
6963 PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
6964 sprintf_s(szString,SZSTRING_SIZE,"// %08X [GLM] %s : %s", tkMember,ProperName((char*)pcMember),pcSig);
6965 printLine(g_pFile,szString);
6966 }
6967 }
6968 g_pImport->EnumClose(&hEnum);
6969 if (SUCCEEDED(g_pImport->EnumGlobalFieldsInit(&hEnum)))
6970 {
6971 while(g_pImport->EnumNext(&hEnum, &tkMember))
6972 {
6973 if (FAILED(g_pImport->GetNameOfFieldDef(tkMember, &pcMember)) ||
6974 FAILED(g_pImport->GetSigOfFieldDef(tkMember, &cComSig, &pComSig)))
6975 {
6976 sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the field record %08X", tkMember);
6977 printLine(g_pFile, szString);
6978 continue;
6979 }
6980 qbMemberSig.Shrink(0);
6981 pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
6982 PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
6983 sprintf_s(szString,SZSTRING_SIZE,"// %08X [GLF] %s : %s", tkMember,ProperName((char*)pcMember),pcSig);
6984 printLine(g_pFile,szString);
6985 }
6986 }
6987 g_pImport->EnumClose(&hEnum);
6988
6989 for (i = 0; i < g_NumClasses; i++)
6990 {
6991 if (FAILED(g_pImport->GetNameOfTypeDef(g_cl_list[i], &pcClass, &pcNS)))
6992 {
6993 sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the TypeDef record %08X", g_cl_list[i]);
6994 printLine(g_pFile, szString);
6995 continue;
6996 }
6997 PREFIX_ASSUME(ProperName((char*)pcClass) != 0);
6998 if(*pcNS) sprintf_s(szFQN,4096,"%s.%s", ProperName((char*)pcNS),ProperName((char*)pcClass));
6999 else strcpy_s(szFQN,4096,ProperName((char*)pcClass));
7000 sprintf_s(szString,SZSTRING_SIZE,"// %08X [CLS] %s", g_cl_list[i],szFQN);
7001 printLine(g_pFile,szString);
7002 if(SUCCEEDED(g_pImport->EnumInit(mdtMethodDef, g_cl_list[i], &hEnum)))
7003 {
7004 while(g_pImport->EnumNext(&hEnum, &tkMember))
7005 {
7006 if (FAILED(g_pImport->GetNameOfMethodDef(tkMember, &pcMember)) ||
7007 FAILED(g_pImport->GetSigOfMethodDef(tkMember, &cComSig, &pComSig)))
7008 {
7009 sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the method record %08X", tkMember);
7010 printLine(g_pFile, szString);
7011 continue;
7012 }
7013 qbMemberSig.Shrink(0);
7014 pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
7015 PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
7016 sprintf_s(szString,SZSTRING_SIZE,"// %08X [MET] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
7017 printLine(g_pFile,szString);
7018 }
7019 }
7020 g_pImport->EnumClose(&hEnum);
7021 if(SUCCEEDED(g_pImport->EnumInit(mdtFieldDef, g_cl_list[i], &hEnum)))
7022 {
7023 while(g_pImport->EnumNext(&hEnum, &tkMember))
7024 {
7025 if (FAILED(g_pImport->GetNameOfFieldDef(tkMember, &pcMember)) ||
7026 FAILED(g_pImport->GetSigOfFieldDef(tkMember, &cComSig, &pComSig)))
7027 {
7028 sprintf_s(szString, SZSTRING_SIZE, "// ERROR in the field record %08X", tkMember);
7029 printLine(g_pFile, szString);
7030 continue;
7031 }
7032 qbMemberSig.Shrink(0);
7033 pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
7034 PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
7035 sprintf_s(szString,SZSTRING_SIZE,"// %08X [FLD] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
7036 printLine(g_pFile,szString);
7037 }
7038 }
7039 g_pImport->EnumClose(&hEnum);
7040 if(SUCCEEDED(g_pImport->EnumInit(mdtEvent, g_cl_list[i], &hEnum)))
7041 {
7042 while(g_pImport->EnumNext(&hEnum, &tkMember))
7043 {
7044 if (FAILED(g_pImport->GetEventProps(tkMember,&pcMember,&dwAttrs,&tkEventType)))
7045 {
7046 sprintf_s(szString, SZSTRING_SIZE, "// Invalid Event %08X record", tkMember);
7047 printLine(g_pFile, szString);
7048 continue;
7049 }
7050 qbMemberSig.Shrink(0);
7051 pcSig = "NO TYPE";
7052 if(RidFromToken(tkEventType))
7053 {
7054 switch(TypeFromToken(tkEventType))
7055 {
7056 case mdtTypeRef:
7057 case mdtTypeDef:
7058 case mdtTypeSpec:
7059 pcSig = PrettyPrintClass(&qbMemberSig,tkEventType,g_pImport);
7060 break;
7061 default:
7062 break;
7063 }
7064 }
7065 PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
7066 sprintf_s(szString,SZSTRING_SIZE,"// %08X [EVT] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
7067 printLine(g_pFile,szString);
7068 }
7069 }
7070 g_pImport->EnumClose(&hEnum);
7071 if(SUCCEEDED(g_pImport->EnumInit(mdtProperty, g_cl_list[i], &hEnum)))
7072 {
7073 while(g_pImport->EnumNext(&hEnum, &tkMember))
7074 {
7075 if (FAILED(g_pImport->GetPropertyProps(tkMember,&pcMember,&dwAttrs,&pComSig,&cComSig)))
7076 {
7077 sprintf_s(szString, SZSTRING_SIZE, "// Invalid Property %08X record", tkMember);
7078 printLine(g_pFile, szString);
7079 continue;
7080 }
7081 qbMemberSig.Shrink(0);
7082 pcSig = cComSig ? PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL) : "NO SIGNATURE";
7083 PREFIX_ASSUME(ProperName((char*)pcMember) != 0);
7084 sprintf_s(szString,SZSTRING_SIZE,"// %08X [PRO] %s::%s : %s", tkMember,szFQN,ProperName((char*)pcMember),pcSig);
7085 printLine(g_pFile,szString);
7086 }
7087 }
7088 g_pImport->EnumClose(&hEnum);
7089 }
7090 printLine(g_pFile,"//=============== END SUMMARY ==================================");
7091}
7092void DumpRTFPrefix(void* GUICookie,BOOL fFontDefault)
7093{
7094 g_fDumpRTF = FALSE;
7095 printLine(GUICookie,"{\\rtf1\\ansi");
7096 if(fFontDefault)
7097 printLine(GUICookie,"{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset1 Courier New;}{\\f1\\fswiss\\fcharset1 Arial;}}");
7098 printLine(GUICookie,"{\\colortbl ;\\red0\\green0\\blue128;\\red0\\green128\\blue0;\\red255\\green0\\blue0;}");
7099 printLine(GUICookie,"\\viewkind4\\uc1\\pard\\f0\\fs20");
7100 g_fDumpRTF = TRUE;
7101}
7102void DumpRTFPostfix(void* GUICookie)
7103{
7104 g_fDumpRTF = FALSE;
7105 printLine(GUICookie,"}");
7106 g_fDumpRTF = TRUE;
7107}
7108mdToken ClassOf(mdToken tok)
7109{
7110 mdToken retval=0;
7111 switch(TypeFromToken(tok))
7112 {
7113 case mdtTypeDef:
7114 case mdtTypeRef:
7115 case mdtTypeSpec:
7116 retval = tok;
7117 break;
7118
7119 case mdtFieldDef:
7120 case mdtMethodDef:
7121 case mdtMemberRef:
7122 if (FAILED(g_pImport->GetParentToken(tok, &retval)))
7123 {
7124 retval = mdTokenNil;
7125 }
7126 else
7127 {
7128 retval = ClassOf(retval);
7129 }
7130 break;
7131
7132 default:
7133 break;
7134 }
7135 return retval;
7136}
7137void DumpRefs(BOOL fClassesOnly)
7138{
7139 CQuickBytes out;
7140 DynamicArray<TokPair> *refs = g_refs;
7141 TokPair *newrefs = NULL;
7142 mdToken tkThisUser,tkThisRef;
7143 mdToken tkLastUser = 0xFFFFFFFF, tkLastRef=0xFFFFFFFF;
7144 DWORD i=0,j=0;
7145
7146 g_refs = NULL;
7147 printLine(g_pFile,COMMENT((char*)0));
7148 printLine(g_pFile,"//============ R E F E R E N C E S ===========================");
7149 strcpy_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH,"// ");
7150 if(fClassesOnly && g_NumRefs)
7151 {
7152 if((newrefs = new TokPair[g_NumRefs]))
7153 {
7154 for(i=0; i<g_NumRefs; i++)
7155 {
7156 newrefs[i].tkUser = tkThisUser = ClassOf((*refs)[i].tkUser);
7157 newrefs[i].tkRef = tkThisRef = ClassOf((*refs)[i].tkRef);
7158 if(!tkThisUser) continue;
7159 if(!tkThisRef) continue;
7160 if(tkThisUser == tkThisRef) continue;
7161 for(j = 0; j<i; j++)
7162 {
7163 if((newrefs[j].tkUser==tkThisUser)&&(newrefs[j].tkRef==tkThisRef))
7164 {
7165 newrefs[i].tkRef = 0;
7166 break;
7167 }
7168 }
7169 }
7170 }
7171 else fClassesOnly = FALSE;
7172 }
7173 for(i = 0; i <g_NumRefs; i++)
7174 {
7175 if(fClassesOnly)
7176 {
7177 tkThisUser = newrefs[i].tkUser;
7178 tkThisRef = newrefs[i].tkRef;
7179 }
7180 else
7181 {
7182 tkThisUser = (*refs)[i].tkUser;
7183 tkThisRef = (*refs)[i].tkRef;
7184 }
7185 if(!tkThisUser) continue;
7186 if(!tkThisRef) continue;
7187 if(tkThisUser == tkThisRef) continue;
7188 if((tkThisUser==tkLastUser)&&(tkThisRef==tkLastRef)) continue;
7189
7190 strcpy_s(szString, SZSTRING_SIZE,g_szAsmCodeIndent);
7191 if(tkThisUser != tkLastUser)
7192 {
7193 PrettyPrintToken(szString, tkThisUser, g_pImport,g_pFile,0); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
7194 strcat_s(szString, SZSTRING_SIZE, " references ");
7195 printLine(g_pFile,szString);
7196 tkLastUser = tkThisUser;
7197 }
7198 strcpy_s(szString, SZSTRING_SIZE,g_szAsmCodeIndent);
7199 strcat_s(szString, SZSTRING_SIZE," - ");
7200 PrettyPrintToken(szString, tkThisRef, g_pImport,g_pFile,0); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
7201 printLine(g_pFile,szString);
7202 tkLastRef = tkThisRef;
7203
7204 }
7205
7206 printLine(g_pFile,"//=============== END REFERENCES =============================");
7207 printLine(g_pFile,COMMENT((char*)-1));
7208 g_refs = refs;
7209 if(newrefs) VDELETE(newrefs);
7210}
7211
7212void CloseNamespace(__inout __nullterminated char* szString)
7213{
7214 if(strlen(g_szNamespace))
7215 {
7216 char* szptr = &szString[0];
7217 if(g_szAsmCodeIndent[0]) g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
7218 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s ",g_szAsmCodeIndent, UNSCOPE());
7219 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT("// end of namespace %s"),ProperName(g_szNamespace));
7220 printLine(g_pFile,szString);
7221 printLine(g_pFile,"");
7222 g_szNamespace[0] = 0;
7223 }
7224}
7225
7226FILE* OpenOutput(__in __nullterminated const WCHAR* wzFileName)
7227{
7228 FILE* pfile = NULL;
7229 if(g_uCodePage == 0xFFFFFFFF) _wfopen_s(&pfile,wzFileName,W("wb"));
7230 else _wfopen_s(&pfile,wzFileName,W("wt"));
7231
7232 if(pfile)
7233 {
7234 if(g_uCodePage == CP_UTF8) fwrite("\357\273\277",3,1,pfile);
7235 else if(g_uCodePage == 0xFFFFFFFF) fwrite("\377\376",2,1,pfile);
7236 }
7237 return pfile;
7238}
7239
7240FILE* OpenOutput(__in __nullterminated const char* szFileName)
7241{
7242 return OpenOutput(UtfToUnicode(szFileName));
7243}
7244
7245//
7246// Init PELoader, dump file header info
7247//
7248#ifdef _PREFAST_
7249#pragma warning(push)
7250#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
7251#endif
7252BOOL DumpFile()
7253{
7254 BOOL fSuccess = FALSE;
7255 static WCHAR wzInputFileName[MAX_FILENAME_LENGTH];
7256 static char szFilenameANSI[MAX_FILENAME_LENGTH*3];
7257 IMetaDataDispenser *pMetaDataDispenser = NULL;
7258 const char *pszFilename = g_szInputFile;
7259 const DWORD openFlags = ofRead | (g_fProject ? 0 : ofNoTransform);
7260
7261 {
7262 if(g_fDumpHTML)
7263 {
7264 printLine(g_pFile, "<HTML>");
7265 printLine(g_pFile, "<HEAD>");
7266 sprintf_s(szString,SZSTRING_SIZE,"<TITLE> %s - IL DASM</TITLE>",g_szInputFile);
7267 printLine(g_pFile, szString);
7268 printLine(g_pFile, "</HEAD>");
7269 printLine(g_pFile, "<BODY>");
7270 printLine(g_pFile, "<FONT SIZE=3 FACE=\"Arial\">");
7271 printLine(g_pFile, "<PRE>");
7272 }
7273 else if(g_fDumpRTF)
7274 {
7275 DumpRTFPrefix(g_pFile,TRUE);
7276 }
7277 DumpPreamble();
7278 }
7279 {
7280 char* pch = strrchr(g_szInputFile,'.');
7281 if(pch && (!_stricmp(pch+1,"lib") || !_stricmp(pch+1,"obj")))
7282 {
7283 DumpMetaInfo(g_wszFullInputFile,g_pszObjFileName,g_pFile);
7284 return FALSE;
7285 }
7286 }
7287
7288 if(g_pPELoader) goto DoneInitialization; // skip initialization, it's already done
7289
7290 g_pPELoader = new PELoader();
7291 if (g_pPELoader == NULL)
7292 {
7293 printError(g_pFile,RstrUTF(IDS_E_INITLDR));
7294 goto exit;
7295 }
7296
7297 memset(wzInputFileName,0,sizeof(WCHAR)*MAX_FILENAME_LENGTH);
7298 WszMultiByteToWideChar(CP_UTF8,0,pszFilename,-1,wzInputFileName,MAX_FILENAME_LENGTH);
7299 memset(szFilenameANSI,0,MAX_FILENAME_LENGTH*3);
7300 WszWideCharToMultiByte(g_uConsoleCP,0,wzInputFileName,-1,szFilenameANSI,MAX_FILENAME_LENGTH*3,NULL,NULL);
7301 fSuccess = g_pPELoader->open(wzInputFileName);
7302
7303 if (fSuccess == FALSE)
7304 {
7305 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_FILEOPEN), pszFilename);
7306 printError(g_pFile,szString);
7307 SDELETE(g_pPELoader);
7308 g_pPELoader = NULL;
7309 goto exit;
7310 }
7311 fSuccess = FALSE;
7312
7313 if (g_pPELoader->getCOMHeader(&g_CORHeader) == FALSE)
7314 {
7315 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_NOCORHDR), pszFilename);
7316 printError(g_pFile,szString);
7317 if (g_fDumpHeader)
7318 DumpHeader(g_CORHeader,g_pFile);
7319 goto exit;
7320 }
7321
7322 if (VAL16(g_CORHeader->MajorRuntimeVersion) == 1 || VAL16(g_CORHeader->MajorRuntimeVersion) > COR_VERSION_MAJOR)
7323 {
7324 sprintf_s(szString,SZSTRING_SIZE,"CORHeader->MajorRuntimeVersion = %d",VAL16(g_CORHeader->MajorRuntimeVersion));
7325 printError(g_pFile,szString);
7326 printError(g_pFile,RstrUTF(IDS_E_BADCORHDR));
7327 goto exit;
7328 }
7329 g_tkEntryPoint = VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)); // integration with MetaInfo
7330
7331
7332#if defined(_DEBUG) && defined(FEATURE_PREJIT)
7333 if (g_fNGenNativeMetadata)
7334 {
7335 //if this is an ngen image, use the native metadata.
7336 if( !g_CORHeader->ManagedNativeHeader.Size )
7337 {
7338 printError( g_pFile, "/native only works on NGen images." );
7339 goto exit;
7340 }
7341 CORCOMPILE_HEADER * pNativeHeader;
7342 g_pPELoader->getVAforRVA(VAL32(g_CORHeader->ManagedNativeHeader.VirtualAddress), (void**)&pNativeHeader);
7343
7344 if (pNativeHeader->Signature != CORCOMPILE_SIGNATURE)
7345 {
7346 printError( g_pFile, "/native only works on NGen images." );
7347 goto exit;
7348 }
7349
7350 g_pPELoader->getVAforRVA(VAL32(pNativeHeader->ManifestMetaData.VirtualAddress), &g_pMetaData);
7351 g_cbMetaData = VAL32(pNativeHeader->ManifestMetaData.Size);
7352 }
7353 else
7354#endif
7355 {
7356 if (g_pPELoader->getVAforRVA(VAL32(g_CORHeader->MetaData.VirtualAddress),&g_pMetaData) == FALSE)
7357 {
7358 printError(g_pFile, RstrUTF(IDS_E_OPENMD));
7359 if (g_fDumpHeader)
7360 DumpHeader(g_CORHeader, g_pFile);
7361 goto exit;
7362 }
7363 g_cbMetaData = VAL32(g_CORHeader->MetaData.Size);
7364 }
7365
7366 if (FAILED(getMetaDataInternalInterface(
7367 (BYTE *)g_pMetaData,
7368 g_cbMetaData,
7369 openFlags,
7370 IID_IMDInternalImport,
7371 (LPVOID *)&g_pImport)))
7372 {
7373 if (g_fDumpHeader)
7374 DumpHeader(g_CORHeader, g_pFile);
7375 printError(g_pFile, RstrUTF(IDS_E_OPENMD));
7376 goto exit;
7377 }
7378
7379 TokenSigInit(g_pImport);
7380 if (FAILED(metaDataGetDispenser(CLSID_CorMetaDataDispenser, IID_IMetaDataDispenser, (LPVOID*)&pMetaDataDispenser)))
7381 {
7382 if (g_fDumpHeader)
7383 DumpHeader(g_CORHeader, g_pFile);
7384 printError(g_pFile, RstrUTF(IDS_E_OPENMD));
7385 goto exit;
7386 }
7387 if (FAILED(pMetaDataDispenser->OpenScopeOnMemory(g_pMetaData, g_cbMetaData, openFlags, IID_IMetaDataImport2, (LPUNKNOWN *)&g_pPubImport )))
7388 {
7389 if (g_fDumpHeader)
7390 DumpHeader(g_CORHeader, g_pFile);
7391 printError(g_pFile, RstrUTF(IDS_E_OPENMD));
7392 goto exit;
7393 }
7394
7395 if((g_uNCA = g_pImport->GetCountWithTokenKind(mdtCustomAttribute)))
7396 {
7397 g_rchCA = new char[g_uNCA+1];
7398 _ASSERTE(g_rchCA);
7399 }
7400
7401 EnumClasses();
7402 EnumTypedefs();
7403
7404DoneInitialization:
7405 if(g_uNCA)
7406 {
7407 _ASSERTE(g_rchCA);
7408 memset(g_rchCA,0,g_uNCA+1);
7409 }
7410#ifndef _DEBUG
7411 if(HasSuppressingAttribute())
7412 {
7413 if (g_fDumpHeader)
7414 DumpHeader(g_CORHeader,g_pFile);
7415 if(g_fDumpMetaInfo)
7416 DumpMetaInfo(g_wszFullInputFile,NULL,g_pFile);
7417 printError(g_pFile,RstrUTF(IDS_E_SUPPRESSED));
7418 goto CloseFileAndExit;
7419 }
7420#endif
7421
7422 {
7423 // Dump the CLR header info if requested.
7424 printLine(g_pFile,COMMENT((char*)0)); // start multiline comment
7425 if (g_fDumpHeader)
7426 {
7427 DumpHeader(g_CORHeader,g_pFile);
7428 DumpHeaderDetails(g_CORHeader,g_pFile);
7429 }
7430 else
7431 DumpVTables(g_CORHeader,g_pFile);
7432 if (g_fDumpStats)
7433 DumpStatistics(g_CORHeader,g_pFile);
7434
7435 if(g_fDumpClassList) PrintClassList();
7436 // MetaInfo integration:
7437 if(g_fDumpMetaInfo) DumpMetaInfo(g_wszFullInputFile,NULL,g_pFile);
7438
7439 if(g_fDumpSummary) DumpSummary();
7440 printLine(g_pFile,COMMENT((char*)-1)); // end multiline comment
7441
7442 if(g_fShowRefs) g_refs = new DynamicArray<TokPair>;
7443
7444 if (g_fDumpAsmCode)
7445 {
7446 g_szNamespace[0] = 0;
7447 if(g_tkClassToDump) //g_tkClassToDump is set in EnumClasses
7448 {
7449 DumpClass(TopEncloser(g_tkClassToDump), VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)),g_pFile,7); //7-dump everything at once
7450 CloseNamespace(szString);
7451 goto ReportAndExit;
7452 }
7453 {
7454 HENUMInternal hEnumMethod;
7455 ULONG ulNumGlobalFunc=0;
7456 if (SUCCEEDED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod)))
7457 {
7458 ulNumGlobalFunc = g_pImport->EnumGetCount(&hEnumMethod);
7459 g_pImport->EnumClose(&hEnumMethod);
7460 }
7461
7462 }
7463 //DumpVtable(g_pFile);
7464 DumpMscorlib(g_pFile);
7465 if(g_fDumpTypeList) DumpTypelist(g_pFile);
7466 DumpManifest(g_pFile);
7467 DumpTypedefs(g_pFile);
7468 /* First dump the classes w/o members*/
7469 if(g_fForwardDecl && g_NumClasses)
7470 {
7471 printLine(g_pFile,COMMENT("//"));
7472 printLine(g_pFile,COMMENT("// ============== CLASS STRUCTURE DECLARATION =================="));
7473 printLine(g_pFile,COMMENT("//"));
7474 for (DWORD i = 0; i < g_NumClasses; i++)
7475 {
7476 if(g_cl_enclosing[i] == mdTypeDefNil) // nested classes are dumped within enclosing ones
7477 {
7478 DumpClass(g_cl_list[i], VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)),g_pFile,2); // 2=header+nested classes
7479 }
7480 }
7481 CloseNamespace(szString);
7482 printLine(g_pFile,"");
7483 printLine(g_pFile,COMMENT("// ============================================================="));
7484 printLine(g_pFile,"");
7485 }
7486 /* Second, dump the global fields and methods */
7487 DumpGlobalFields();
7488 DumpGlobalMethods(VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)));
7489 /* Third, dump the classes with members */
7490 if(g_NumClasses)
7491 {
7492 printLine(g_pFile,"");
7493 printLine(g_pFile,COMMENT("// =============== CLASS MEMBERS DECLARATION ==================="));
7494 if(g_fForwardDecl)
7495 {
7496 printLine(g_pFile,COMMENT("// note that class flags, 'extends' and 'implements' clauses"));
7497 printLine(g_pFile,COMMENT("// are provided here for information only"));
7498 }
7499 printLine(g_pFile,"");
7500 for (DWORD i = 0; i < g_NumClasses; i++)
7501 {
7502 if(g_cl_enclosing[i] == mdTypeDefNil) // nested classes are dumped within enclosing ones
7503 {
7504 DumpClass(g_cl_list[i], VAL32(IMAGE_COR20_HEADER_FIELD(*g_CORHeader, EntryPointToken)),g_pFile,7); //7=everything
7505 }
7506 }
7507 CloseNamespace(szString);
7508 printLine(g_pFile,"");
7509 printLine(g_pFile,COMMENT("// ============================================================="));
7510 printLine(g_pFile,"");
7511 }
7512 if(g_fShowCA)
7513 {
7514 if(g_uNCA) _ASSERTE(g_rchCA);
7515 for(DWORD i=1; i<= g_uNCA; i++)
7516 {
7517 if(g_rchCA[i] == 0) DumpCustomAttribute(TokenFromRid(i,mdtCustomAttribute),g_pFile,true);
7518 }
7519 }
7520
7521
7522 // If there were "ldptr", dump the .rdata section with labels
7523 if(g_iPtrCount)
7524 {
7525 //first, sort the pointers
7526 int i,j;
7527 bool swapped;
7528 do {
7529 swapped = FALSE;
7530
7531 for(i = 1; i < g_iPtrCount; i++)
7532 {
7533 if((*g_pPtrTags)[i-1] > (*g_pPtrTags)[i])
7534 {
7535 j = (*g_pPtrTags)[i-1];
7536 (*g_pPtrTags)[i-1] = (*g_pPtrTags)[i];
7537 (*g_pPtrTags)[i] = j;
7538 j = (*g_pPtrSize)[i-1];
7539 (*g_pPtrSize)[i-1] = (*g_pPtrSize)[i];
7540 (*g_pPtrSize)[i] = j;
7541 swapped = TRUE;
7542 }
7543 }
7544 } while(swapped);
7545
7546 //second, dump data for each ptr as binarray
7547
7548 IMAGE_SECTION_HEADER *pSecHdr = NULL;
7549 if(g_pPELoader->IsPE32())
7550 pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
7551 else
7552 pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
7553
7554 DWORD dwNumberOfSections;
7555 if(g_pPELoader->IsPE32())
7556 dwNumberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
7557 else
7558 dwNumberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
7559
7560 DWORD fromPtr,toPtr,limPtr;
7561 char* szptr;
7562 for(j = 0; j < g_iPtrCount; j++)
7563 {
7564 BYTE *pb;
7565
7566 fromPtr = (*g_pPtrTags)[j];
7567 for (i=0; i < (int)dwNumberOfSections; i++,pSecHdr++)
7568 {
7569 if((fromPtr >= VAL32(pSecHdr->VirtualAddress))&&
7570 (fromPtr < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize))) break;
7571 }
7572 if(i == (int)dwNumberOfSections)
7573 {
7574 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_ROGUEPTR), fromPtr);
7575 printLine(g_pFile,szString);
7576 break;
7577 }
7578 // OK, now we have the section; what about end of BLOB?
7579 const char* szTls = "D_";
7580 if(strcmp((char*)(pSecHdr->Name),".tls")==0) szTls = "T_";
7581 else if(strcmp((char*)(pSecHdr->Name),".text")==0) szTls = "I_";
7582 if(j == g_iPtrCount-1)
7583 {
7584 toPtr = VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize);
7585 }
7586 else
7587 {
7588 toPtr = (*g_pPtrTags)[j+1];
7589 if(toPtr > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize))
7590 {
7591 toPtr = VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize);
7592 }
7593 }
7594 if(toPtr - fromPtr > (*g_pPtrSize)[j]) toPtr = fromPtr + (*g_pPtrSize)[j];
7595 limPtr = toPtr; // at limPtr and after, pad with 0
7596 if(limPtr > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->SizeOfRawData))
7597 limPtr = VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->SizeOfRawData);
7598 PrintBlob:
7599 szptr = szString;
7600 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s%s ",g_szAsmCodeIndent,KEYWORD(".data"));
7601 if(*szTls=='T') szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("tls "));
7602 else if(*szTls=='I') szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("cil "));
7603 if(fromPtr >= limPtr)
7604 { // uninitialized data
7605 sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%8.8X = %s[%d]",szTls,fromPtr,KEYWORD("int8"),toPtr-fromPtr);
7606 printLine(g_pFile,szString);
7607 }
7608 else
7609 { // initialized data
7610 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%8.8X = %s (",szTls,fromPtr,KEYWORD("bytearray"));
7611 printLine(g_pFile,szString);
7612 szptr = szString;
7613 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s ",g_szAsmCodeIndent);
7614 pb = g_pPELoader->base()
7615 + VAL32(pSecHdr->PointerToRawData)
7616 + fromPtr - VAL32(pSecHdr->VirtualAddress);
7617 // now fromPtr is the beginning of the BLOB, and toPtr is [exclusive] end of it
7618 DumpHexbytes(szptr, pb, fromPtr, toPtr, limPtr);
7619 }
7620 // to preserve alignment, dump filler if any
7621 if(limPtr == toPtr) // don't need filler if it's the last item in section
7622 {
7623 if((j < g_iPtrCount-1)&&(toPtr < (DWORD)((*g_pPtrTags)[j+1])))
7624 {
7625 DWORD align;
7626 DWORD stptr = (DWORD)(*g_pPtrTags)[j+1];
7627 for(align = 1; (align & stptr)==0; align = align << 1);
7628 align -= 1;
7629 if(toPtr & align)
7630 {
7631 fromPtr = toPtr;
7632 toPtr = (toPtr + align)&~align;
7633 goto PrintBlob;
7634 }
7635 }
7636 }
7637 }
7638 }
7639ReportAndExit:
7640 printLine(g_pFile,COMMENT(RstrUTF(IDS_E_DASMOK)));
7641 fSuccess = TRUE;
7642 }
7643 fSuccess = TRUE;
7644#ifndef FEATURE_PAL
7645 if(g_pFile) // dump .RES file (if any), if not to console
7646 {
7647 WCHAR wzResFileName[2048], *pwc;
7648 memset(wzResFileName,0,sizeof(wzResFileName));
7649 WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzResFileName,2048);
7650 pwc = wcsrchr(wzResFileName,L'.');
7651 if(pwc == NULL) pwc = &wzResFileName[wcslen(wzResFileName)];
7652 wcscpy_s(pwc, 2048 - (pwc - wzResFileName), L".res");
7653 DWORD ret = DumpResourceToFile(wzResFileName);
7654 switch(ret)
7655 {
7656 case 0: szString[0] = 0; break;
7657 case 1: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_W_CREATEDW32RES)/*"// WARNING: Created Win32 resource file %ls"*/,
7658 UnicodeToUtf(wzResFileName)); break;
7659 case 0xDFFFFFFF: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_CORRUPTW32RES)/*"// ERROR: Corrupt Win32 resources"*/); break;
7660 case 0xEFFFFFFF: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_CANTOPENW32RES)/*"// ERROR: Unable to open file %ls"*/,
7661 UnicodeToUtf(wzResFileName)); break;
7662 case 0xFFFFFFFF: sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_CANTACCESSW32RES)/*"// ERROR: Unable to access Win32 resources"*/); break;
7663 }
7664 if(szString[0])
7665 {
7666 if(ret == 1) printLine(g_pFile,COMMENT(szString));
7667 else printError(g_pFile,szString);
7668 }
7669 }
7670#endif
7671 if(g_fShowRefs) DumpRefs(TRUE);
7672 if(g_fDumpHTML)
7673 {
7674 printLine(g_pFile, "</PRE>");
7675 printLine(g_pFile, "</BODY>");
7676 printLine(g_pFile, "</HTML>");
7677 }
7678 else if(g_fDumpRTF)
7679 {
7680 DumpRTFPostfix(g_pFile);
7681 }
7682
7683#ifndef _DEBUG
7684CloseFileAndExit:
7685#endif
7686 if(g_pFile)
7687 {
7688 fclose(g_pFile);
7689 g_pFile = NULL;
7690 }
7691 }
7692
7693exit:
7694 if (pMetaDataDispenser)
7695 pMetaDataDispenser->Release();
7696 return fSuccess;
7697}
7698#ifdef _PREFAST_
7699#pragma warning(pop)
7700#endif
7701
7702#ifdef _MSC_VER
7703#pragma warning(default : 4640)
7704#endif
7705
7706
7707