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// ==++==
6//
7
8//
9// ==--==
10#include "strike.h"
11#include "util.h"
12#include "genericstackprobe.h"
13
14/**********************************************************************\
15* Routine Description: *
16* *
17* This function is called to find the name of a TypeDef using *
18* metadata API. *
19* *
20\**********************************************************************/
21// Caller should guard against exception
22// !!! mdName should have at least mdNameLen WCHAR
23static HRESULT NameForTypeDef_s(mdTypeDef tkTypeDef, IMetaDataImport *pImport,
24 __out_ecount (capacity_mdName) WCHAR *mdName, size_t capacity_mdName)
25{
26 DWORD flags;
27 ULONG nameLen;
28
29 HRESULT hr = pImport->GetTypeDefProps(tkTypeDef, mdName,
30 mdNameLen, &nameLen,
31 &flags, NULL);
32 if (hr != S_OK) {
33 return hr;
34 }
35
36 if (!IsTdNested(flags)) {
37 return hr;
38 }
39 mdTypeDef tkEnclosingClass;
40 hr = pImport->GetNestedClassProps(tkTypeDef, &tkEnclosingClass);
41 if (hr != S_OK) {
42 return hr;
43 }
44 WCHAR *name = (WCHAR*)_alloca((nameLen+1)*sizeof(WCHAR));
45 wcscpy_s (name, nameLen+1, mdName);
46 hr = NameForTypeDef_s(tkEnclosingClass,pImport,mdName, capacity_mdName);
47 if (hr != S_OK) {
48 return hr;
49 }
50 size_t Len = _wcslen (mdName);
51 if (Len < mdNameLen-2) {
52 mdName[Len++] = L'+';
53 mdName[Len] = L'\0';
54 }
55 Len = mdNameLen-1 - Len;
56 if (Len > nameLen) {
57 Len = nameLen;
58 }
59 wcsncat_s (mdName,capacity_mdName,name,Len);
60 return hr;
61}
62
63/**********************************************************************\
64* Routine Description: *
65* *
66* This function is called to find the name of a TypeDef using *
67* metadata API. *
68* *
69\**********************************************************************/
70// Caller should guard against exception
71// !!! mdName should have at least mdNameLen WCHAR
72/*
73static HRESULT NameForTypeDefNew(mdTypeDef tkTypeDef, IMDInternalImport *pImport,
74 WCHAR *mdName)
75{
76 DWORD flags;
77 ULONG nameLen;
78 char *name = (char *)_alloca((mdNameLen+1)*sizeof(char));
79 char *namesp = (char *)_alloca((mdNameLen+1)*sizeof(char));
80
81 HRESULT hr = pImport->GetNameOfTypeDef(tkTypeDef, name, namesp);
82 if (FAILED(hr))
83 {
84 return hr;
85 }
86
87 strcpy (namesp, ".");
88 strcpy (namesp, name);
89 MultiByteToWideChar (CP_ACP,0,namesp,-1,mdName,mdNameLen);
90 return hr;
91}
92*/
93
94/**********************************************************************\
95* Routine Description: *
96* *
97* Find the Module MD Importer given the name of the Module. *
98* *
99\**********************************************************************/
100IMetaDataImport* MDImportForModule(DacpModuleData* pModule)
101{
102 IMetaDataImport *pRet = NULL;
103 ToRelease<IXCLRDataModule> module;
104 HRESULT hr = g_sos->GetModule(pModule->Address, &module);
105
106 if (SUCCEEDED(hr))
107 hr = module->QueryInterface(IID_IMetaDataImport, (LPVOID *) &pRet);
108
109 if (SUCCEEDED(hr))
110 return pRet;
111
112 return NULL;
113}
114
115IMetaDataImport* MDImportForModule(DWORD_PTR pModule)
116{
117 DacpModuleData moduleData;
118 if(moduleData.Request(g_sos, TO_CDADDR(pModule))==S_OK)
119 return MDImportForModule(&moduleData);
120 else
121 return NULL;
122}
123
124/**********************************************************************\
125* Routine Description: *
126* *
127* Find the name for a metadata token given an importer. *
128* *
129\**********************************************************************/
130HRESULT NameForToken_s(mdTypeDef mb, IMetaDataImport *pImport, __out_ecount (capacity_mdName) WCHAR *mdName, size_t capacity_mdName,
131 bool bClassName)
132{
133 mdName[0] = L'\0';
134 if ((mb & 0xff000000) != mdtTypeDef
135 && (mb & 0xff000000) != mdtFieldDef
136 && (mb & 0xff000000) != mdtMethodDef)
137 {
138 //ExtOut("unsupported\n");
139 return E_FAIL;
140 }
141
142 HRESULT hr = E_FAIL;
143
144 PAL_CPP_TRY
145 {
146 static WCHAR name[MAX_CLASSNAME_LENGTH];
147 if ((mb & 0xff000000) == mdtTypeDef)
148 {
149 hr = NameForTypeDef_s (mb, pImport, mdName, capacity_mdName);
150 }
151 else if ((mb & 0xff000000) == mdtFieldDef)
152 {
153 mdTypeDef mdClass;
154 ULONG size;
155 hr = pImport->GetMemberProps(mb, &mdClass,
156 name, sizeof(name)/sizeof(WCHAR)-1, &size,
157 NULL, NULL, NULL, NULL,
158 NULL, NULL, NULL, NULL);
159 if (SUCCEEDED (hr))
160 {
161 if (mdClass != mdTypeDefNil && bClassName)
162 {
163 hr = NameForTypeDef_s (mdClass, pImport, mdName, capacity_mdName);
164 wcscat_s (mdName, capacity_mdName, W("."));
165 }
166 name[size] = L'\0';
167 wcscat_s (mdName, capacity_mdName, name);
168 }
169 }
170 else if ((mb & 0xff000000) == mdtMethodDef)
171 {
172 mdTypeDef mdClass;
173 ULONG size;
174 hr = pImport->GetMethodProps(mb, &mdClass,
175 name, sizeof(name)/sizeof(WCHAR)-1, &size,
176 NULL, NULL, NULL, NULL, NULL);
177 if (SUCCEEDED (hr))
178 {
179 if (mdClass != mdTypeDefNil && bClassName)
180 {
181 hr = NameForTypeDef_s (mdClass, pImport, mdName, capacity_mdName);
182 wcscat_s (mdName, capacity_mdName, W("."));
183 }
184 name[size] = L'\0';
185 wcscat_s (mdName, capacity_mdName, name);
186 }
187 }
188 else
189 {
190 ExtOut ("Unsupported token type\n");
191 hr = E_FAIL;
192 }
193 }
194 PAL_CPP_CATCH_ALL
195 {
196 hr = E_FAIL;
197 }
198 PAL_CPP_ENDTRY
199 return hr;
200}
201
202/**********************************************************************\
203* Routine Description: *
204* *
205* Find the name for a metadata token given an importer. *
206* *
207\**********************************************************************/
208/*
209HRESULT NameForTokenNew(mdTypeDef mb, IMDInternalImport *pImport, WCHAR *mdName, size_t capacity_mdName,
210 bool bClassName)
211{
212
213 // TODO: Change calls to use the secure versions (string as well as to functions defined here)
214 // Simply uncommenting this function will not result in a clean compile
215 // --chirayuk @ 11/23/2004
216
217 mdName[0] = L'\0';
218 if ((mb & 0xff000000) != mdtTypeDef
219 && (mb & 0xff000000) != mdtFieldDef
220 && (mb & 0xff000000) != mdtMethodDef)
221 {
222 //ExtOut("unsupported\n");
223 return E_FAIL;
224 }
225
226 HRESULT hr;
227
228 __try
229 {
230 static WCHAR name[MAX_CLASSNAME_LENGTH];
231 if (TypeFromToken(mb) == mdtTypeDef)
232 {
233 hr = NameForTypeDefNew (mb, pImport, mdName);
234 }
235 else if (TypeFromToken(mb) == mdtFieldDef)
236 {
237 mdTypeDef mdClass;
238 ULONG size;
239 MultiByteToWideChar (CP_ACP,0,pImport->GetNameOfFieldDef(mb),-1,name,MAX_CLASSNAME_LENGTH);
240
241 hr = pImport->GetParentToken (mb, &mdClass);
242 if (SUCCEEDED (hr))
243 {
244 if (mdClass != mdTypeDefNil && bClassName)
245 {
246 hr = NameForTypeDefNew (mdClass, pImport, mdName);
247 _wcscat (mdName, W("."));
248 }
249 name[size] = L'\0';
250 _wcscat (mdName, name);
251 }
252 }
253 else if (TypeFromToken(mb) == mdtMethodDef)
254 {
255 mdTypeDef mdClass;
256 ULONG size;
257
258 MultiByteToWideChar (CP_ACP,0,pImport->GetNameOfMethodDef(mb),-1,name,MAX_CLASSNAME_LENGTH);
259 hr = pImport->GetParentToken (mb, &mdClass);
260 if (SUCCEEDED (hr))
261 {
262 if (mdClass != mdTypeDefNil && bClassName)
263 {
264 hr = NameForTypeDefNew (mdClass, pImport, mdName);
265 _wcscat (mdName, W("."));
266 }
267 name[size] = L'\0';
268 _wcscat (mdName, name);
269 }
270 }
271 else
272 {
273 ExtOut ("Unsupported token type\n");
274 hr = E_FAIL;
275 }
276 }
277 __except (EXCEPTION_EXECUTE_HANDLER)
278 {
279 //ExtOut("Metadata operation failure\n");
280 hr = E_FAIL;
281 }
282 return hr;
283}
284*/
285
286/**********************************************************************\
287* Routine Description: *
288* *
289* This function is called to find the name of a metadata token *
290* using metadata API. *
291* *
292\**********************************************************************/
293void NameForToken_s(DWORD_PTR ModuleAddr, mdTypeDef mb, __out_ecount (capacity_mdName) WCHAR *mdName, size_t capacity_mdName,
294 bool bClassName)
295{
296 DacpModuleData ModuleData;
297 mdName[0] = L'\0';
298 if(ModuleData.Request(g_sos, TO_CDADDR(ModuleAddr))==S_OK)
299 NameForToken_s(&ModuleData,mb,mdName,capacity_mdName,bClassName);
300}
301
302BOOL IsValidToken(DWORD_PTR ModuleAddr, mdTypeDef mb)
303{
304 DacpModuleData ModuleData;
305 if(ModuleData.Request(g_sos, TO_CDADDR(ModuleAddr))==S_OK)
306 {
307 ToRelease<IMetaDataImport> pImport = MDImportForModule(&ModuleData);
308 if (pImport)
309 {
310 if (pImport->IsValidToken (mb))
311 return TRUE;
312 }
313 }
314 return FALSE;
315}
316
317void NameForToken_s(DacpModuleData *pModule, mdTypeDef mb, __out_ecount (capacity_mdName) WCHAR *mdName, size_t capacity_mdName,
318 bool bClassName)
319{
320 mdName[0] = L'\0';
321 HRESULT hr = 0;
322 ToRelease<IMetaDataImport> pImport = MDImportForModule(pModule);
323 if (pImport)
324 {
325 hr = NameForToken_s (mb, pImport, mdName, capacity_mdName, bClassName);
326 }
327
328 if (!pImport || !SUCCEEDED (hr))
329 {
330 const SIZE_T capacity_moduleName = mdNameLen+19;
331 LPWSTR moduleName = (LPWSTR)alloca(capacity_moduleName * sizeof(WCHAR)); // for the "Dynamic Module In " below
332 FileNameForModule(pModule,moduleName);
333 if (moduleName[0] == L'\0') {
334 DacpAssemblyData assembly;
335 assembly.Request(g_sos,pModule->Assembly);
336 if (assembly.isDynamic) {
337 wcscpy_s(moduleName, capacity_moduleName, W("Dynamic "));
338 }
339 wcscat_s (moduleName, capacity_moduleName, W("Module in "));
340 if(g_sos->GetAssemblyName(pModule->Assembly, mdNameLen, g_mdName, NULL)==S_OK)
341 {
342 wcscat_s(moduleName, capacity_moduleName, g_mdName);
343 }
344 }
345 swprintf_s (mdName, capacity_mdName,
346 W(" mdToken: %08x (%ws)"),
347 mb,
348 moduleName[0] ? moduleName : W("Unknown Module") );
349 }
350}
351
352#define STRING_BUFFER_LEN 1024
353
354class MDInfo
355{
356public:
357 MDInfo (DWORD_PTR ModuleAddr)
358 {
359 m_pImport = MDImportForModule(ModuleAddr);
360 if (!m_pImport)
361 ExtOut("Unable to get IMetaDataImport for module %p\n", ModuleAddr);
362 m_pSigBuf = NULL;
363 }
364
365 MDInfo (IMetaDataImport * pImport)
366 {
367 m_pImport = pImport;
368 m_pImport->AddRef();
369 m_pSigBuf = NULL;
370 }
371
372 void GetMethodName(mdTypeDef token, CQuickBytes *fullName);
373 GetSignatureStringResults GetMethodSignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, CQuickBytes *fullName);
374 GetSignatureStringResults GetSignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, CQuickBytes *fullName);
375
376 LPCWSTR TypeDefName(mdTypeDef inTypeDef);
377 LPCWSTR TypeRefName(mdTypeRef tr);
378 LPCWSTR TypeDeforRefName(mdToken inToken);
379private:
380 // helper to init signature buffer
381 void InitSigBuffer()
382 {
383 ((LPWSTR)m_pSigBuf->Ptr())[0] = L'\0';
384 }
385
386 HRESULT AddToSigBuffer(LPCWSTR string);
387
388 HRESULT GetFullNameForMD(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, LONG *plSigBlobRemaining OPTIONAL);
389 HRESULT GetOneElementType(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, ULONG *pcb);
390
391 ToRelease<IMetaDataImport> m_pImport;
392 // Signature buffer.
393 CQuickBytes *m_pSigBuf;
394
395 // temporary buffer for TypeDef or TypeRef name. Consume immediately
396 // because other functions may overwrite it.
397 static WCHAR m_szTempBuf[MAX_CLASSNAME_LENGTH];
398
399 static WCHAR m_szName[MAX_CLASSNAME_LENGTH];
400};
401
402WCHAR MDInfo::m_szTempBuf[MAX_CLASSNAME_LENGTH];
403WCHAR MDInfo::m_szName[MAX_CLASSNAME_LENGTH];
404
405GetSignatureStringResults GetMethodSignatureString (PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, DWORD_PTR dwModuleAddr, CQuickBytes *sigString)
406{
407 MDInfo mdInfo(dwModuleAddr);
408
409 return mdInfo.GetMethodSignature(pbSigBlob, ulSigBlob, sigString);
410}
411
412
413GetSignatureStringResults GetSignatureString (PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, DWORD_PTR dwModuleAddr, CQuickBytes *sigString)
414{
415 MDInfo mdInfo(dwModuleAddr);
416
417 return mdInfo.GetSignature(pbSigBlob, ulSigBlob, sigString);
418}
419
420void GetMethodName(mdMethodDef methodDef, IMetaDataImport * pImport, CQuickBytes *fullName)
421{
422 MDInfo mdInfo(pImport);
423
424 mdInfo.GetMethodName(methodDef, fullName);
425}
426
427
428// Tables for mapping element type to text
429const WCHAR *g_wszMapElementType[] =
430{
431 W("End"), // 0x0
432 W("Void"), // 0x1
433 W("Boolean"),
434 W("Char"),
435 W("I1"),
436 W("UI1"),
437 W("I2"), // 0x6
438 W("UI2"),
439 W("I4"),
440 W("UI4"),
441 W("I8"),
442 W("UI8"),
443 W("R4"),
444 W("R8"),
445 W("String"),
446 W("Ptr"), // 0xf
447 W("ByRef"), // 0x10
448 W("ValueClass"),
449 W("Class"),
450 W("CopyCtor"),
451 W("MDArray"), // 0x14
452 W("GENArray"),
453 W("TypedByRef"),
454 W("VALUEARRAY"),
455 W("I"),
456 W("U"),
457 W("R"), // 0x1a
458 W("FNPTR"),
459 W("Object"),
460 W("SZArray"),
461 W("GENERICArray"),
462 W("CMOD_REQD"),
463 W("CMOD_OPT"),
464 W("INTERNAL"),
465};
466
467const WCHAR *g_wszCalling[] =
468{
469 W("[DEFAULT]"),
470 W("[C]"),
471 W("[STDCALL]"),
472 W("[THISCALL]"),
473 W("[FASTCALL]"),
474 W("[VARARG]"),
475 W("[FIELD]"),
476 W("[LOCALSIG]"),
477 W("[PROPERTY]"),
478 W("[UNMANAGED]"),
479};
480
481void MDInfo::GetMethodName(mdTypeDef token, CQuickBytes *fullName)
482{
483 if (m_pImport == NULL) {
484 return;
485 }
486
487 HRESULT hr;
488 mdTypeDef memTypeDef;
489 ULONG nameLen;
490 DWORD flags;
491 PCCOR_SIGNATURE pbSigBlob;
492 ULONG ulSigBlob;
493 ULONG ulCodeRVA;
494 ULONG ulImplFlags;
495
496 m_pSigBuf = fullName;
497 InitSigBuffer();
498
499 WCHAR szFunctionName[1024];
500
501 hr = m_pImport->GetMethodProps(token, &memTypeDef,
502 szFunctionName, _countof(szFunctionName), &nameLen,
503 &flags, &pbSigBlob, &ulSigBlob, &ulCodeRVA, &ulImplFlags);
504 if (FAILED (hr))
505 {
506 return;
507 }
508
509 szFunctionName[nameLen] = L'\0';
510 m_szName[0] = L'\0';
511 if (memTypeDef != mdTypeDefNil)
512 {
513 hr = NameForTypeDef_s (memTypeDef, m_pImport, m_szName, _countof(m_szName));
514 if (SUCCEEDED (hr)) {
515 wcscat_s (m_szName, _countof(m_szName), W("."));
516 }
517 }
518 wcscat_s (m_szName, _countof(m_szName), szFunctionName);
519
520 LONG lSigBlobRemaining;
521 hr = GetFullNameForMD(pbSigBlob, ulSigBlob, &lSigBlobRemaining);
522
523 // We should have consumed all signature blob. If not, dump the sig in hex.
524 // Also dump in hex if so requested.
525 if (lSigBlobRemaining != 0)
526 {
527 // Did we not consume enough, or try to consume too much?
528 if (lSigBlobRemaining < 0)
529 ExtOut("ERROR IN SIGNATURE: Signature should be larger.\n");
530 else
531 ExtOut("ERROR IN SIGNATURE: Not all of signature blob was consumed. %d byte(s) remain\n", lSigBlobRemaining);
532 }
533
534 if (FAILED(hr))
535 ExtOut("ERROR!! Bad signature blob value!");
536}
537
538
539GetSignatureStringResults MDInfo::GetMethodSignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, CQuickBytes *fullName)
540{
541 if (!m_pImport)
542 return GSS_ERROR;
543
544 m_pSigBuf = fullName;
545 InitSigBuffer();
546
547 m_szName[0] = '\0';
548
549 LONG lSigBlobRemaining;
550 if (FAILED(GetFullNameForMD(pbSigBlob, ulSigBlob, &lSigBlobRemaining)))
551 return GSS_ERROR;
552
553 if (lSigBlobRemaining < 0)
554 return GSS_INSUFFICIENT_DATA;
555
556 return GSS_SUCCESS;
557}
558
559
560GetSignatureStringResults MDInfo::GetSignature(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, CQuickBytes *fullName)
561{
562 if (!m_pImport)
563 return GSS_ERROR;
564
565 m_pSigBuf = fullName;
566 InitSigBuffer();
567
568 m_szName[0] = '\0';
569
570 ULONG cb;
571 if (FAILED(GetOneElementType(pbSigBlob, ulSigBlob, &cb)))
572 {
573 if (cb > ulSigBlob)
574 return GSS_INSUFFICIENT_DATA;
575 else
576 return GSS_ERROR;
577 }
578
579 return GSS_SUCCESS;
580}
581
582
583inline bool isCallConv(unsigned sigByte, CorCallingConvention conv)
584{
585 return ((sigByte & IMAGE_CEE_CS_CALLCONV_MASK) == (unsigned) conv);
586}
587
588#ifndef IfFailGoto
589#define IfFailGoto(EXPR, LABEL) \
590do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0)
591#endif
592
593#ifndef IfFailGo
594#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit)
595#endif
596
597#ifndef IfFailRet
598#define IfFailRet(EXPR) do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0)
599#endif
600
601#ifndef _ASSERTE
602#define _ASSERTE(expr)
603#endif
604
605HRESULT MDInfo::GetFullNameForMD(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, LONG *plSigBlobRemaining)
606{
607 ULONG cbCur = 0;
608 ULONG cb;
609 ULONG ulData = NULL;
610 ULONG ulArgs;
611 HRESULT hr = NOERROR;
612
613 cb = CorSigUncompressData(pbSigBlob, &ulData);
614
615 // 0 is a valid calling convention byte (IMAGE_CEE_CS_CALLCONV_DEFAULT w/ no flags)
616 //if (ulData == NULL)
617 // goto ErrExit;
618
619 AddToSigBuffer (g_wszCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]);
620 if (cb>ulSigBlob)
621 goto ErrExit;
622 cbCur += cb;
623 ulSigBlob -= cb;
624
625 if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
626 AddToSigBuffer ( W(" [hasThis]"));
627 if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
628 AddToSigBuffer ( W(" [explicit]"));
629
630 AddToSigBuffer (W(" "));
631 if ( isCallConv(ulData,IMAGE_CEE_CS_CALLCONV_FIELD) )
632 {
633 // display field type
634 if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
635 goto ErrExit;
636 AddToSigBuffer ( W(" "));
637 AddToSigBuffer ( m_szName);
638 if (cb>ulSigBlob)
639 goto ErrExit;
640 cbCur += cb;
641 ulSigBlob -= cb;
642 }
643 else
644 {
645 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulArgs);
646 if (cb>ulSigBlob)
647 goto ErrExit;
648 cbCur += cb;
649 ulSigBlob -= cb;
650
651 if (ulData != IMAGE_CEE_CS_CALLCONV_LOCAL_SIG)
652 {
653 // display return type when it is not a local varsig
654 if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
655 goto ErrExit;
656 AddToSigBuffer (W(" "));
657 AddToSigBuffer (m_szName);
658 AddToSigBuffer ( W("("));
659 if (cb>ulSigBlob)
660 goto ErrExit;
661 cbCur += cb;
662 ulSigBlob -= cb;
663 }
664
665 ULONG i = 0;
666 while (i < ulArgs && ulSigBlob > 0)
667 {
668 ULONG ulDataUncompress;
669
670 // Handle the sentinal for varargs because it isn't counted in the args.
671 CorSigUncompressData(&pbSigBlob[cbCur], &ulDataUncompress);
672 ++i;
673
674 if (FAILED(hr = GetOneElementType(&pbSigBlob[cbCur], ulSigBlob, &cb)))
675 goto ErrExit;
676 if (i != ulArgs) {
677 AddToSigBuffer ( W(","));
678 }
679 if (cb>ulSigBlob)
680 goto ErrExit;
681
682 cbCur += cb;
683 ulSigBlob -= cb;
684 }
685 AddToSigBuffer ( W(")"));
686 }
687
688 // Nothing consumed but not yet counted.
689 cb = 0;
690
691ErrExit:
692
693 if (plSigBlobRemaining)
694 *plSigBlobRemaining = (ulSigBlob - cb);
695
696 return hr;
697}
698
699LPCWSTR MDInfo::TypeDefName(mdTypeDef inTypeDef)
700{
701 if (m_pImport == NULL) {
702 return W("");
703 }
704
705 HRESULT hr;
706
707 hr = m_pImport->GetTypeDefProps(
708 // [IN] The import scope.
709 inTypeDef, // [IN] TypeDef token for inquiry.
710 m_szTempBuf, // [OUT] Put name here.
711 MAX_CLASSNAME_LENGTH , // [IN] size of name buffer in wide chars.
712 NULL, // [OUT] put size of name (wide chars) here.
713 NULL, // [OUT] Put flags here.
714 NULL); // [OUT] Put base class TypeDef/TypeRef here.
715
716 if (FAILED(hr)) return (W("NoName"));
717 return (m_szTempBuf);
718} // LPCWSTR MDInfo::TypeDefName()
719LPCWSTR MDInfo::TypeRefName(mdTypeRef tr)
720{
721 if (m_pImport == NULL) {
722 return W("");
723 }
724
725 HRESULT hr;
726
727 hr = m_pImport->GetTypeRefProps(
728 tr, // The class ref token.
729 NULL, // Resolution scope.
730 m_szTempBuf, // Put the name here.
731 MAX_CLASSNAME_LENGTH, // Size of the name buffer, wide chars.
732 NULL); // Put actual size of name here.
733 if (FAILED(hr)) return (W("NoName"));
734
735 return (m_szTempBuf);
736} // LPCWSTR MDInfo::TypeRefName()
737
738LPCWSTR MDInfo::TypeDeforRefName(mdToken inToken)
739{
740 if (RidFromToken(inToken))
741 {
742 if (TypeFromToken(inToken) == mdtTypeDef)
743 return (TypeDefName((mdTypeDef) inToken));
744 else if (TypeFromToken(inToken) == mdtTypeRef)
745 return (TypeRefName((mdTypeRef) inToken));
746 else
747 return (W("[InvalidReference]"));
748 }
749 else
750 return (W(""));
751} // LPCWSTR MDInfo::TypeDeforRefName()
752
753
754HRESULT MDInfo::AddToSigBuffer(LPCWSTR string)
755{
756 HRESULT hr;
757 IfFailRet(m_pSigBuf->ReSize((_wcslen((LPWSTR)m_pSigBuf->Ptr()) + _wcslen(string) + 1) * sizeof(WCHAR)));
758 wcscat_s((LPWSTR)m_pSigBuf->Ptr(), m_pSigBuf->Size()/sizeof(WCHAR),string);
759 return NOERROR;
760}
761
762HRESULT MDInfo::GetOneElementType(PCCOR_SIGNATURE pbSigBlob, ULONG ulSigBlob, ULONG *pcb)
763{
764 HRESULT hr = S_OK; // A result.
765 ULONG cbCur = 0;
766 ULONG cb;
767 ULONG ulData;
768 ULONG ulTemp;
769 int iTemp = 0;
770 mdToken tk;
771 const size_t capacity_buffer = 9;
772
773 cb = CorSigUncompressData(pbSigBlob, &ulData);
774
775 if (cb == ULONG(-1)) {
776 hr = E_FAIL;
777 goto ErrExit;
778 }
779
780 cbCur += cb;
781
782 // Handle the modifiers.
783 if (ulData & ELEMENT_TYPE_MODIFIER)
784 {
785 if (ulData == ELEMENT_TYPE_SENTINEL)
786 IfFailGo(AddToSigBuffer(W("<ELEMENT_TYPE_SENTINEL> ")));
787 else if (ulData == ELEMENT_TYPE_PINNED)
788 IfFailGo(AddToSigBuffer(W("PINNED ")));
789 else
790 {
791 hr = E_FAIL;
792 goto ErrExit;
793 }
794 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
795 goto ErrExit;
796 cbCur += cb;
797 goto ErrExit;
798 }
799
800 // Handle the underlying element types.
801 if (ulData >= ELEMENT_TYPE_MAX)
802 {
803 hr = E_FAIL;
804 goto ErrExit;
805 }
806 while (ulData == ELEMENT_TYPE_PTR || ulData == ELEMENT_TYPE_BYREF)
807 {
808 IfFailGo(AddToSigBuffer(g_wszMapElementType[ulData]));
809 IfFailGo(AddToSigBuffer(W(" ")));
810 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
811 cbCur += cb;
812 }
813
814 // Generics
815 if (ulData == ELEMENT_TYPE_VAR)
816 {
817 IfFailGo(AddToSigBuffer(W("__Canon")));
818
819 // The next byte represents which generic parameter is referred to. We
820 // do not currently use this information, so just bypass this byte.
821 cbCur++;
822
823 goto ErrExit;
824 }
825
826 // A generic instance, e.g. IEnumerable<String>
827 if (ulData == ELEMENT_TYPE_GENERICINST)
828 {
829 // Print out the base type.
830 IfFailGo(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb));
831 cbCur += cb;
832
833 // Get the number of generic arguments.
834 ULONG numParams = 0;
835 IfFailGo(CorSigUncompressData(&pbSigBlob[cbCur], 1, &numParams, &cb));
836 cbCur += cb;
837
838 // Print out the list of arguments
839 IfFailGo(AddToSigBuffer(W("<")));
840 for (ULONG i = 0; i < numParams; i++)
841 {
842 if (i > 0)
843 IfFailGo(AddToSigBuffer(W(",")));
844
845 IfFailGo(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb));
846 cbCur += cb;
847 }
848 IfFailGo(AddToSigBuffer(W(">")));
849 goto ErrExit;
850 }
851
852 // Past this point we must have something which directly maps to a value in g_wszMapElementType.
853 IfFailGo(AddToSigBuffer(g_wszMapElementType[ulData]));
854 if (CorIsPrimitiveType((CorElementType)ulData) ||
855 ulData == ELEMENT_TYPE_TYPEDBYREF ||
856 ulData == ELEMENT_TYPE_OBJECT ||
857 ulData == ELEMENT_TYPE_I ||
858 ulData == ELEMENT_TYPE_U)
859 {
860 // If this is a primitive type, we are done
861 goto ErrExit;
862 }
863
864 AddToSigBuffer(W(" "));
865 if (ulData == ELEMENT_TYPE_VALUETYPE ||
866 ulData == ELEMENT_TYPE_CLASS ||
867 ulData == ELEMENT_TYPE_CMOD_REQD ||
868 ulData == ELEMENT_TYPE_CMOD_OPT)
869 {
870 cb = CorSigUncompressToken(&pbSigBlob[cbCur], &tk);
871 cbCur += cb;
872
873 // get the name of type ref. Don't care if truncated
874 if (TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtTypeRef)
875 {
876 IfFailGo(AddToSigBuffer(TypeDeforRefName(tk)));
877 }
878 else
879 {
880 _ASSERTE(TypeFromToken(tk) == mdtTypeSpec);
881 WCHAR buffer[capacity_buffer];
882 _itow_s (tk, buffer, capacity_buffer, 16);
883 IfFailGo(AddToSigBuffer(buffer));
884 }
885 if (ulData == ELEMENT_TYPE_CMOD_REQD ||
886 ulData == ELEMENT_TYPE_CMOD_OPT)
887 {
888 IfFailGo(AddToSigBuffer(W(" ")));
889 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
890 goto ErrExit;
891 cbCur += cb;
892 }
893
894 goto ErrExit;
895 }
896 if (ulData == ELEMENT_TYPE_SZARRAY)
897 {
898 // display the base type of SZARRAY or GENERICARRAY
899 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
900 goto ErrExit;
901 cbCur += cb;
902 goto ErrExit;
903 }
904 if (ulData == ELEMENT_TYPE_FNPTR)
905 {
906 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
907 cbCur += cb;
908 if (ulData & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
909 IfFailGo(AddToSigBuffer(W("[explicit] ")));
910 if (ulData & IMAGE_CEE_CS_CALLCONV_HASTHIS)
911 IfFailGo(AddToSigBuffer(W("[hasThis] ")));
912
913 IfFailGo(AddToSigBuffer(g_wszCalling[ulData & IMAGE_CEE_CS_CALLCONV_MASK]));
914
915 // Get number of args
916 ULONG numArgs;
917 cb = CorSigUncompressData(&pbSigBlob[cbCur], &numArgs);
918 cbCur += cb;
919
920 // do return type
921 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
922 goto ErrExit;
923 cbCur += cb;
924
925 IfFailGo(AddToSigBuffer(W("(")));
926 while (numArgs > 0)
927 {
928 if (cbCur > ulSigBlob)
929 goto ErrExit;
930 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
931 goto ErrExit;
932 cbCur += cb;
933 --numArgs;
934 if (numArgs > 0)
935 IfFailGo(AddToSigBuffer(W(",")));
936 }
937 IfFailGo(AddToSigBuffer(W(")")));
938 goto ErrExit;
939 }
940
941 if (ulData == ELEMENT_TYPE_INTERNAL)
942 {
943 IfFailGo(AddToSigBuffer(W("MT ")));
944
945 void *pvMethodTable;
946 cb = CorSigUncompressPointer(&pbSigBlob[cbCur], (void**)&pvMethodTable);
947 cbCur += cb;
948
949 const size_t capacity_szMethodTableValue = 10;
950 WCHAR szMethodTableValue[10];
951 itow_s_ptr((INT_PTR)pvMethodTable, szMethodTableValue, capacity_szMethodTableValue, 16);
952
953 IfFailGo(AddToSigBuffer(szMethodTableValue));
954 IfFailGo(AddToSigBuffer(W(" ")));
955
956 IfFailGo(g_sos->GetMethodTableName(TO_CDADDR(pvMethodTable), mdNameLen, g_mdName, NULL));
957 IfFailGo(AddToSigBuffer(g_mdName));
958
959 goto ErrExit;
960 }
961
962
963 if(ulData != ELEMENT_TYPE_ARRAY) return E_FAIL;
964
965 // display the base type of SDARRAY
966 if (FAILED(GetOneElementType(&pbSigBlob[cbCur], ulSigBlob-cbCur, &cb)))
967 goto ErrExit;
968 cbCur += cb;
969
970 IfFailGo(AddToSigBuffer(W(" ")));
971 // display the rank of MDARRAY
972 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
973 cbCur += cb;
974 WCHAR buffer[capacity_buffer];
975 _itow_s (ulData, buffer, capacity_buffer, 10);
976 IfFailGo(AddToSigBuffer(buffer));
977 if (ulData == 0)
978 // we are done if no rank specified
979 goto ErrExit;
980
981 IfFailGo(AddToSigBuffer(W(" ")));
982 // how many dimensions have size specified?
983 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
984 cbCur += cb;
985 _itow_s (ulData, buffer, capacity_buffer, 10);
986 IfFailGo(AddToSigBuffer(buffer));
987 if (ulData == 0) {
988 IfFailGo(AddToSigBuffer(W(" ")));
989 }
990 while (ulData)
991 {
992
993 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulTemp);
994 _itow_s (ulTemp, buffer, capacity_buffer, 10);
995 IfFailGo(AddToSigBuffer(buffer));
996 IfFailGo(AddToSigBuffer(W(" ")));
997 cbCur += cb;
998 ulData--;
999 }
1000 // how many dimensions have lower bounds specified?
1001 cb = CorSigUncompressData(&pbSigBlob[cbCur], &ulData);
1002 cbCur += cb;
1003 _itow_s (ulData, buffer, capacity_buffer, 10);
1004 IfFailGo(AddToSigBuffer(buffer));
1005 while (ulData)
1006 {
1007
1008 cb = CorSigUncompressSignedInt(&pbSigBlob[cbCur], &iTemp);
1009 _itow_s (iTemp, buffer, capacity_buffer, 10);
1010 IfFailGo(AddToSigBuffer(buffer));
1011 IfFailGo(AddToSigBuffer(W(" ")));
1012 cbCur += cb;
1013 ulData--;
1014 }
1015
1016ErrExit:
1017 if (cbCur > ulSigBlob)
1018 hr = E_FAIL;
1019 *pcb = cbCur;
1020 return hr;
1021}
1022
1023//*****************************************************************************
1024// Used when the method is tiny (< 64 bytes), and there are no local vars
1025//*****************************************************************************
1026typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY
1027{
1028 bool IsTiny() const { return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat); }
1029 DWORD GetLocalVarSigTok() const { return(0); }
1030} COR_ILMETHOD_TINY;
1031
1032
1033//*****************************************************************************
1034// This strucuture is the 'fat' layout, where no compression is attempted.
1035// Note that this structure can be added on at the end, thus making it extensible
1036//*****************************************************************************
1037typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT
1038{
1039 bool IsFat() const { return((Flags & CorILMethod_FormatMask) == CorILMethod_FatFormat); }
1040 mdToken GetLocalVarSigTok() const { return(LocalVarSigTok); }
1041} COR_ILMETHOD_FAT;
1042