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 |
41 | DECLARE_NATIVE_STRING_RESOURCE_TABLE(NATIVE_STRING_RESOURCE_NAME); |
42 | #endif |
43 | |
44 | struct 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 | |
52 | ISymUnmanagedReader* g_pSymReader = NULL; |
53 | |
54 | IMDInternalImport* g_pImport = NULL; |
55 | IMetaDataImport2* g_pPubImport; |
56 | extern IMetaDataAssemblyImport* g_pAssemblyImport; |
57 | PELoader * g_pPELoader; |
58 | void * g_pMetaData; |
59 | unsigned g_cbMetaData; |
60 | IMAGE_COR20_HEADER * ; |
61 | DynamicArray<__int32> *g_pPtrTags = NULL; //to keep track of all "ldptr" |
62 | DynamicArray<DWORD> *g_pPtrSize= NULL; //to keep track of all "ldptr" |
63 | int g_iPtrCount = 0; |
64 | mdToken * g_cl_list = NULL; |
65 | mdToken * g_cl_enclosing = NULL; |
66 | BYTE* g_enum_td_type = NULL; // enum (TD) underlying types |
67 | BYTE* g_enum_tr_type = NULL; // enum (TR) underlying types |
68 | IMDInternalImport** g_asmref_import = NULL; // IMDInternalImports for external assemblies |
69 | DynamicArray<MIDescriptor> *g_pmi_list = NULL; |
70 | DWORD g_NumMI; |
71 | DWORD g_NumClasses; |
72 | DWORD g_NumTypeRefs; |
73 | DWORD g_NumAsmRefs; |
74 | DWORD g_NumModules; |
75 | BOOL g_fDumpIL = TRUE; |
76 | BOOL = FALSE; |
77 | BOOL g_fDumpAsmCode = TRUE; |
78 | extern BOOL g_fDumpTokens; // declared in formatType.cpp |
79 | BOOL g_fDumpStats = FALSE; |
80 | BOOL g_fTDC = TRUE; |
81 | BOOL g_fShowCA = TRUE; |
82 | BOOL g_fCAVerbal = FALSE; |
83 | BOOL g_fShowRefs = FALSE; |
84 | |
85 | BOOL g_fDumpToPerfWriter = FALSE; |
86 | HANDLE g_PerfDataFilePtr = NULL; |
87 | |
88 | BOOL g_fDumpClassList = FALSE; |
89 | BOOL g_fDumpTypeList = FALSE; |
90 | BOOL g_fDumpSummary = FALSE; |
91 | BOOL g_fDecompile = FALSE; // still in progress |
92 | BOOL g_fShowBytes = FALSE; |
93 | BOOL g_fShowSource = FALSE; |
94 | BOOL g_fPrettyPrint = FALSE; |
95 | BOOL g_fInsertSourceLines = FALSE; |
96 | BOOL g_fThisIsInstanceMethod; |
97 | BOOL g_fTryInCode = TRUE; |
98 | |
99 | BOOL g_fLimitedVisibility = FALSE; |
100 | #if defined(_DEBUG) && defined(FEATURE_PREJIT) |
101 | BOOL g_fNGenNativeMetadata = FALSE; |
102 | #endif |
103 | BOOL g_fHidePub = TRUE; |
104 | BOOL g_fHidePriv = TRUE; |
105 | BOOL g_fHideFam = TRUE; |
106 | BOOL g_fHideAsm = TRUE; |
107 | BOOL g_fHideFAA = TRUE; |
108 | BOOL g_fHideFOA = TRUE; |
109 | BOOL g_fHidePrivScope = TRUE; |
110 | |
111 | BOOL g_fProject = FALSE; // if .winmd file, transform to .NET view |
112 | |
113 | extern BOOL g_fQuoteAllNames; // declared in formatType.cpp, init to FALSE |
114 | BOOL g_fForwardDecl=FALSE; |
115 | |
116 | char g_szAsmCodeIndent[MAX_MEMBER_LENGTH]; |
117 | char g_szNamespace[MAX_MEMBER_LENGTH]; |
118 | |
119 | DWORD g_Mode = MODE_DUMP_ALL; |
120 | |
121 | char g_pszClassToDump[MAX_CLASSNAME_LENGTH]; |
122 | char g_pszMethodToDump[MAX_MEMBER_LENGTH]; |
123 | char g_pszSigToDump[MAX_SIGNATURE_LENGTH]; |
124 | |
125 | BOOL g_fCustomInstructionEncodingSystem = FALSE; |
126 | |
127 | COR_FIELD_OFFSET *g_rFieldOffset = NULL; |
128 | ULONG g_cFieldsMax, g_cFieldOffsets; |
129 | |
130 | char* g_pszExeFile; |
131 | char g_szInputFile[MAX_FILENAME_LENGTH]; // in UTF-8 |
132 | WCHAR g_wszFullInputFile[MAX_PATH + 1]; // in UTF-16 |
133 | char g_szOutputFile[MAX_FILENAME_LENGTH]; // in UTF-8 |
134 | char* g_pszObjFileName; |
135 | FILE* g_pFile = NULL; |
136 | |
137 | mdToken g_tkClassToDump = 0; |
138 | mdToken g_tkMethodToDump = 0; |
139 | |
140 | unsigned g_uConsoleCP = CP_ACP; |
141 | unsigned g_uCodePage = g_uConsoleCP; |
142 | |
143 | char* g_rchCA = NULL; // dyn.allocated array of CA dumped/not flags |
144 | unsigned g_uNCA = 0; // num. of CAs |
145 | |
146 | struct ResourceNode; |
147 | extern DynamicArray<LocalComTypeDescr*> *g_pLocalComType; |
148 | extern ULONG g_LocalComTypeNum; |
149 | |
150 | // MetaInfo integration: |
151 | #include "../tools/metainfo/mdinfo.h" |
152 | |
153 | BOOL g_fDumpMetaInfo = FALSE; |
154 | ULONG g_ulMetaInfoFilter = MDInfo::dumpDefault; |
155 | // Validator module type. |
156 | DWORD g_ValModuleType = ValidatorModuleTypeInvalid; |
157 | IMetaDataDispenserEx *g_pDisp = NULL; |
158 | void DisplayFile(__in __nullterminated wchar_t* szFile, |
159 | BOOL isFile, |
160 | ULONG DumpFilter, |
161 | __in_opt __nullterminated wchar_t* szObjFile, |
162 | strPassBackFn pDisplayString); |
163 | extern mdMethodDef g_tkEntryPoint; // integration with MetaInfo |
164 | |
165 | DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName); // see DRES.CPP |
166 | |
167 | struct VTableRef |
168 | { |
169 | mdMethodDef tkTok; |
170 | WORD wEntry; |
171 | WORD wSlot; |
172 | }; |
173 | |
174 | DynamicArray<VTableRef> *g_prVTableRef = NULL; |
175 | ULONG g_nVTableRef = 0; |
176 | |
177 | struct EATableRef |
178 | { |
179 | mdMethodDef tkTok; |
180 | char* pszName; |
181 | }; |
182 | DynamicArray<EATableRef> *g_prEATableRef=NULL; |
183 | ULONG g_nEATableRef = 0; |
184 | ULONG g_nEATableBase = 0; |
185 | |
186 | extern HINSTANCE g_hResources; |
187 | void DumpCustomAttributeProps(mdToken tkCA, mdToken tkType, mdToken tkOwner, BYTE*pBlob, ULONG ulLen, void *GUICookie, bool bWithOwner); |
188 | |
189 | WCHAR* 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 | |
264 | char* 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 | } |
274 | char* RstrUTF(unsigned n) |
275 | { |
276 | return RstrA(n,CP_UTF8); |
277 | } |
278 | |
279 | char* RstrANSI(unsigned n) |
280 | { |
281 | return RstrA(n,g_uConsoleCP); |
282 | } |
283 | |
284 | #if 0 |
285 | void 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 |
303 | extern CQuickBytes * g_szBuf_KEYWORD; |
304 | extern CQuickBytes * ; |
305 | extern CQuickBytes * g_szBuf_ERRORMSG; |
306 | extern CQuickBytes * g_szBuf_ANCHORPT; |
307 | extern CQuickBytes * g_szBuf_JUMPPT; |
308 | extern CQuickBytes * g_szBuf_UnquotedProperName; |
309 | extern CQuickBytes * g_szBuf_ProperName; |
310 | |
311 | #ifdef FEATURE_PAL |
312 | CoreCLRLoader *g_loader; |
313 | #endif |
314 | MetaDataGetDispenserFunc metaDataGetDispenser; |
315 | GetMetaDataInternalInterfaceFunc getMetaDataInternalInterface; |
316 | GetMetaDataInternalInterfaceFromPublicFunc getMetaDataInternalInterfaceFromPublic; |
317 | GetMetaDataPublicInterfaceFromInternalFunc getMetaDataPublicInterfaceFromInternal; |
318 | |
319 | BOOL 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 | |
348 | extern LPCSTR *rAsmRefName; // decl. in formatType.cpp -- for AsmRef aliases |
349 | extern ULONG ulNumAsmRefs; // decl. in formatType.cpp -- for AsmRef aliases |
350 | |
351 | void 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 | |
434 | void 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 | |
499 | HRESULT 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 |
521 | BOOL 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 |
914 | bool 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 |
929 | void 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 | } |
976 | void 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 |
1003 | BOOL 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 | |
1055 | void 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 | |
1145 | BOOL 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 | |
1222 | BOOL 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 | |
1243 | BOOL 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 | |
1257 | char* 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 | |
1304 | void 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 | |
1378 | mdToken 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 | |
1398 | mdToken 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 | } |
1417 | mdToken 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 | |
1500 | unsigned 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 | } |
1569 | mdToken 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,¶m.cPKT,wzName,2048,&cName,&md,&pHash,&cHash,&dwFlags); |
1616 | |
1617 | PAL_TRY(Param *, pParam, ¶m) { |
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 | } |
1659 | AssignAndReturn: |
1660 | return tkTypeDef; |
1661 | } |
1662 | unsigned 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 | |
1694 | BYTE* skipType(BYTE* ptr) |
1695 | { |
1696 | mdToken tk; |
1697 | AGAIN: |
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 |
1814 | BYTE* 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 | |
2171 | BOOL 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 | } |
2267 | BOOL 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 | |
2385 | void DumpCustomAttributeProps(mdToken tkCA, mdToken tkType, mdToken tkOwner, BYTE* pBlob, ULONG ulLen, void *GUICookie, bool bWithOwner) |
2386 | { |
2387 | char* szptr = &szString[0]; |
2388 | BOOL = 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 | |
2529 | void 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 | |
2591 | void 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 | |
2610 | void 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 | |
2722 | void 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 | |
2766 | BOOL 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 | |
2826 | void 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 | |
2897 | void 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 |
2998 | BOOL DisassembleWrapper(IMDInternalImport *pImport, BYTE *, |
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 | |
3018 | BOOL 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 |
3084 | char *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 | |
3195 | void 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. |
3251 | void 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 |
3359 | BOOL 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); |
3434 | lDone: ; |
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 | { |
3781 | ItsMiNative: |
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 | |
3835 | BOOL 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 | |
4035 | BOOL 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 | |
4181 | BOOL 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 | |
4326 | BOOL 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 | { |
4344 | FailedToEnum: |
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 | |
4422 | CloseHandlesAndReturn: |
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 | } |
4430 | BOOL 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 | |
4472 | BOOL 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 | } |
4487 | mdTypeDef 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 | |
4501 | BOOL 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 | |
4826 | void 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 | |
4856 | void 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 | |
4886 | void (IMAGE_COR20_HEADER *, 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. |
4946 | NextEntry: |
4947 | ++pFixup; |
4948 | } |
4949 | |
4950 | exit: |
4951 | printLine(GUICookie,"" ); |
4952 | } |
4953 | |
4954 | |
4955 | void (IMAGE_COR20_HEADER *, 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 | |
5009 | exit: |
5010 | printLine(GUICookie,"" ); |
5011 | } |
5012 | |
5013 | |
5014 | void (IMAGE_COR20_HEADER *, 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 | |
5049 | void (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 | |
5149 | void 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 | } |
5190 | void 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 | |
5255 | struct |
5256 | { |
5257 | DWORD ; |
5258 | BYTE ; |
5259 | BYTE ; |
5260 | BYTE ; |
5261 | BYTE ; |
5262 | ULONGLONG ; |
5263 | ULONGLONG ; |
5264 | }; |
5265 | |
5266 | void (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 | } |
5366 | void 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 |
5399 | void (IMAGE_COR20_HEADER *, void* GUICookie) |
5400 | { |
5401 | char* szStr = &szString[0]; |
5402 | |
5403 | DWORD dwAddrOfEntryPoint=0, dwEntryPointSize=0; |
5404 | |
5405 | PIMAGE_DOS_HEADER = 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 * = g_pPELoader->ntHeaders32(); |
5472 | IMAGE_OPTIONAL_HEADER32 * = &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 * = g_pPELoader->ntHeaders64(); |
5562 | IMAGE_OPTIONAL_HEADER64 * = &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 | |
5690 | void (IMAGE_COR20_HEADER *, 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 | |
5702 | void 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 | |
5750 | void 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 | } |
5754 | void 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 | |
5760 | IMetaDataTables *pITables = NULL; |
5761 | //ULONG sizeRec, count; |
5762 | //int size, size2; |
5763 | int metaSize = 0; |
5764 | __int64 fTableSeen; |
5765 | inline void TableSeen(unsigned long n) { fTableSeen |= (I64(1) << n); } |
5766 | inline int IsTableSeen(unsigned long n) { return (fTableSeen & (I64(1) << n)) ? 1 : 0;} |
5767 | inline void TableSeenReset() { fTableSeen = 0;} |
5768 | |
5769 | void 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 |
5800 | void (IMAGE_COR20_HEADER *, void* GUICookie) |
5801 | { |
5802 | int fileSize, miscPESize, miscCOMPlusSize, , methodBodySize; |
5803 | int methodBodies, , , ; |
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 ; |
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 | |
6377 | void 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 | |
6440 | struct VTableEntry |
6441 | { |
6442 | DWORD dwAddr; |
6443 | WORD wCount; |
6444 | WORD wType; |
6445 | }; |
6446 | |
6447 | struct 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 | |
6462 | void (void* GUICookie, |
6463 | IMAGE_NT_HEADERS32 *, IMAGE_OPTIONAL_HEADER32 *, |
6464 | IMAGE_NT_HEADERS64 *, IMAGE_OPTIONAL_HEADER64 *) |
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 |
6616 | void (void* GUICookie, |
6617 | IMAGE_NT_HEADERS32 *, IMAGE_OPTIONAL_HEADER32 *, |
6618 | IMAGE_NT_HEADERS64 *, IMAGE_OPTIONAL_HEADER64 *) |
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 | |
6636 | void 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 * = NULL; |
6645 | IMAGE_OPTIONAL_HEADER32 * = NULL; |
6646 | |
6647 | IMAGE_NT_HEADERS64 * = NULL; |
6648 | IMAGE_OPTIONAL_HEADER64 * = 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: |
6815 | void 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 | |
6847 | void 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 | |
6895 | void 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 | |
6936 | void 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 | } |
7092 | void 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 | } |
7102 | void DumpRTFPostfix(void* GUICookie) |
7103 | { |
7104 | g_fDumpRTF = FALSE; |
7105 | printLine(GUICookie,"}" ); |
7106 | g_fDumpRTF = TRUE; |
7107 | } |
7108 | mdToken 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 | } |
7137 | void 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 | |
7212 | void 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 | |
7226 | FILE* 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 | |
7240 | FILE* 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 |
7252 | BOOL 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 * ; |
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 | |
7404 | DoneInitialization: |
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 | } |
7639 | ReportAndExit: |
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 |
7684 | CloseFileAndExit: |
7685 | #endif |
7686 | if(g_pFile) |
7687 | { |
7688 | fclose(g_pFile); |
7689 | g_pFile = NULL; |
7690 | } |
7691 | } |
7692 | |
7693 | exit: |
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 | |