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.
7 /*vim: set foldmethod=marker: */
10 #if defined(FEATURE_PREJIT)
13 #include <metadataexports.h>
15 #include <comcallablewrapper.h>
18 #if !defined(FEATURE_CORESYSTEM)
23 #include <formattype.h>
25 #include <pedecoder.h>
28 #include <mdfileformat.h>
30 #if !defined(FEATURE_CORESYSTEM)
33 #define _ASSERTE(x) assert(x)
38 #ifdef USE_GC_INFO_DECODER
39 #include <gcinfodecoder.h>
42 #include <ngenhash.inl>
46 //----------------------------------------------------------------------------
48 // ClrDump functionality
50 //----------------------------------------------------------------------------
52 /////////////////////////////////////////////////////////////////////////////////////////////
54 // Given a compressed integer(*pData), expand the compressed int to *pDataOut.
55 // Return value is the number of bytes that the integer occupies in the compressed format
56 // It is caller's responsibility to ensure pDataOut has at least 4 bytes to be written to.
58 // This function returns -1 if pass in with an incorrectly compressed data, such as
59 // (*pBytes & 0xE0) == 0XE0.
60 /////////////////////////////////////////////////////////////////////////////////////////////
62 * copied from cor.h. Modified to operate on PTR_PCCOR_SIGNATUREs
64 inline ULONG DacSigUncompressBigData(
65 PTR_CCOR_SIGNATURE &pData) // [IN,OUT] compressed data
69 // 1 byte data is handled in DacSigUncompressData
70 // _ASSERTE(*pData & 0x80);
73 if ((*pData & 0xC0) == 0x80) // 10?? ????
75 res = (ULONG)((*pData++ & 0x3f) << 8);
80 res = (*pData++ & 0x1f) << 24;
81 res |= *pData++ << 16;
87 FORCEINLINE ULONG DacSigUncompressData(
88 PTR_CCOR_SIGNATURE &pData) // [IN,OUT] compressed data
90 // Handle smallest data inline.
91 if ((*pData & 0x80) == 0x00) // 0??? ????
93 return DacSigUncompressBigData(pData);
95 //const static mdToken g_tkCorEncodeToken[4] ={mdtTypeDef, mdtTypeRef, mdtTypeSpec, mdtBaseType};
98 inline mdToken DacSigUncompressToken( // return the token.
99 PTR_CCOR_SIGNATURE &pData) // [IN,OUT] compressed data
104 tk = DacSigUncompressData(pData);
105 tkType = g_tkCorEncodeToken[tk & 0x3];
106 tk = TokenFromRid(tk >> 2, tkType);
109 // uncompress encoded element type
110 FORCEINLINE CorElementType DacSigUncompressElementType(//Element type
111 PTR_CCOR_SIGNATURE &pData) // [IN,OUT] compressed data
113 return (CorElementType)*pData++;
118 const char * g_helperNames[] =
120 #define JITHELPER(val, fn, sig) # val,
121 #include <jithelpers.h>
127 #define dim(x) (sizeof(x)/sizeof((x)[0]))
129 void EnumFlagsToString( DWORD value,
130 const NativeImageDumper::EnumMnemonics * table,
131 int count, const WCHAR * sep, SString& output )
133 bool firstValue = true;
134 for( int i = 0; i < count; ++i )
137 const NativeImageDumper::EnumMnemonics& entry = table[i];
138 if( entry.mask != 0 )
139 match = ((entry.mask & value) == entry.value);
141 match = (entry.value == value);
149 output.Append( table[i].mnemonic );
151 value &= ~entry.value;
156 const NativeImageDumper::EnumMnemonics s_ImageSections[] =
158 #define IS_ENTRY(v, s) NativeImageDumper::EnumMnemonics(v, s)
159 IS_ENTRY(IMAGE_SCN_MEM_READ, W("read")),
160 IS_ENTRY(IMAGE_SCN_MEM_WRITE, W("write")),
161 IS_ENTRY(IMAGE_SCN_MEM_EXECUTE, W("execute")),
162 IS_ENTRY(IMAGE_SCN_CNT_CODE, W("code")),
163 IS_ENTRY(IMAGE_SCN_CNT_INITIALIZED_DATA, W("init data")),
164 IS_ENTRY(IMAGE_SCN_CNT_UNINITIALIZED_DATA, W("uninit data")),
167 inline int CheckFlags( DWORD source, DWORD flags )
169 return (source & flags) == flags;
172 HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase,
174 IXCLRDataDisplay * display,
175 IXCLRLibrarySupport * support,
176 IXCLRDisassemblySupport *dis)
179 /* REVISIT_TODO Fri 09/09/2005
182 NativeImageDumper dump(dac_cast<PTR_VOID>(CLRDATA_ADDRESS_TO_TADDR(loadedBase)), name, display,
184 dump.DumpNativeImage();
191 static ULONG bigBufferSize = 8192;
192 static WCHAR bigBuffer[8192];
193 static BYTE bigByteBuffer[1024];
195 //----------------------------------------------------------------------------
199 //----------------------------------------------------------------------------
201 inline T combine(T a, T b)
203 return (T)(((DWORD)a) | ((DWORD)b));
206 inline T combine(T a, T b, T c)
208 return (T)(((DWORD)a) | ((DWORD)b) | ((DWORD)c));
210 #define CLRNATIVEIMAGE_ALWAYS ((CLRNativeImageDumpOptions)~0)
211 #define CHECK_OPT(opt) CheckOptions(CLRNATIVEIMAGE_ ## opt)
212 #define IF_OPT(opt) if( CHECK_OPT(opt) )
213 #define IF_OPT_AND(opt1, opt2) if( CHECK_OPT(opt1) && CHECK_OPT(opt2) )
214 #define IF_OPT_OR(opt1, opt2) if( CHECK_OPT(opt1) || CHECK_OPT(opt2) )
215 #define IF_OPT_OR3(opt1, opt2, opt3) if( CHECK_OPT(opt1) || CHECK_OPT(opt2) || CHECK_OPT(opt3) )
216 #define IF_OPT_OR4(opt1, opt2, opt3, opt4) if( CHECK_OPT(opt1) || CHECK_OPT(opt2) || CHECK_OPT(opt3) || CHECK_OPT(opt4) )
217 #define IF_OPT_OR5(opt1, opt2, opt3, opt4, opt5) if( CHECK_OPT(opt1) || CHECK_OPT(opt2) || CHECK_OPT(opt3) || CHECK_OPT(opt4) || CHECK_OPT(opt5) )
219 #define fieldsize(type, field) (sizeof(((type*)NULL)->field))
222 /*{{{Display helpers*/
223 #define DisplayStartCategory(name, filter)\
224 do { IF_OPT(filter) m_display->StartCategory(name); } while(0)
225 #define DisplayEndCategory(filter)\
226 do { IF_OPT(filter) m_display->EndCategory(); } while(0)
227 #define DisplayStartArray(name, fmt, filter) \
228 do { IF_OPT(filter) m_display->StartArray(name, fmt); } while(0)
229 #define DisplayStartArrayWithOffset(field, fmt, type, filter) \
230 do { IF_OPT(filter) m_display->StartArrayWithOffset( # field, offsetof(type, field), fieldsize(type, field), fmt); } while(0)
232 #define DisplayStartElement( name, filter ) \
233 do { IF_OPT(filter) m_display->StartElement( name ); } while(0)
234 #define DisplayStartStructure( name, ptr, size, filter ) \
235 do { IF_OPT(filter) m_display->StartStructure( name, ptr, size ); } while(0)
236 #define DisplayStartList(fmt, filter) \
237 do { IF_OPT(filter) m_display->StartList(fmt); } while(0)
239 #define DisplayStartStructureWithOffset( field, ptr, size, type, filter ) \
240 do { IF_OPT(filter) m_display->StartStructureWithOffset( # field, offsetof(type, field), fieldsize(type, field), ptr, size ); } while(0)
241 #define DisplayStartVStructure( name, filter ) \
242 do { IF_OPT(filter) m_display->StartVStructure( name ); } while(0)
243 #define DisplayEndVStructure( filter ) \
244 do { IF_OPT(filter) m_display->EndVStructure(); } while(0)
246 #define DisplayEndList(filter) \
247 do { IF_OPT(filter) m_display->EndList(); } while(0)
248 #define DisplayEndArray(footer, filter) \
249 do { IF_OPT(filter) m_display->EndArray(footer); } while(0)
250 #define DisplayEndStructure(filter) \
251 do { IF_OPT(filter) m_display->EndStructure(); } while(0)
253 #define DisplayEndElement(filter) \
254 do { IF_OPT(filter) m_display->EndElement(); } while(0)
256 #define DisplayWriteElementString(name, value, filter) \
257 do { IF_OPT(filter) m_display->WriteElementString(name, value); } while(0)
258 #define DisplayWriteElementStringW(name, value, filter) \
259 do { IF_OPT(filter) m_display->WriteElementStringW(name, value); } while(0)
261 #define DisplayWriteElementStringW(name, value, filter) \
262 do { IF_OPT(filter) m_display->WriteElementStringW(name, value); } while(0)
264 #define DisplayWriteElementInt(name, value, filter) \
265 do { IF_OPT(filter) m_display->WriteElementInt(name, value); } while(0)
266 #define DisplayWriteElementIntWithSuppress(name, value, defVal, filter) \
267 do { IF_OPT(filter) m_display->WriteElementIntWithSuppress(name, value, defVal); } while(0)
268 #define DisplayWriteElementUInt(name, value, filter) \
269 do { IF_OPT(filter) m_display->WriteElementUInt(name, value); } while(0)
270 #define DisplayWriteElementFlag(name, value, filter) \
271 do { IF_OPT(filter) m_display->WriteElementFlag(name, value); } while(0)
272 #define DisplayWriteElementPointer(name, value, filter) \
273 do { IF_OPT(filter) m_display->WriteElementPointer(name, value); } while(0)
274 #define DisplayWriteElementPointerAnnotated(name, value, annotation, filter) \
275 do { IF_OPT(filter) m_display->WriteElementPointerAnnotated(name, value, annotation ); } while(0)
276 #define DisplayWriteEmptyElement(name, filter) \
277 do { IF_OPT(filter) m_display->WriteEmptyElement(name); } while(0)
279 #define DisplayWriteElementEnumerated(name, value, mnemonics, sep, filter) \
283 EnumFlagsToString(value, mnemonics, _countof(mnemonics), sep, buf);\
284 m_display->WriteElementEnumerated( name, value, (const WCHAR*)buf ); \
287 #define DisplayWriteFieldEnumerated(field, value, type, mnemonics, sep, filter)\
291 EnumFlagsToString(value, mnemonics, _countof(mnemonics), sep, buf);\
292 m_display->WriteFieldEnumerated( # field, offsetof(type, field), \
293 fieldsize(type, field), value,\
294 (const WCHAR*)buf ); \
297 #define DisplayWriteElementAddress(name, ptr, size, filter) \
298 do { IF_OPT(filter) m_display->WriteElementAddress( name, ptr, size ); } while(0)
299 #define DisplayWriteElementAddressNamed(eltName, name, ptr, size, filter) \
300 do { IF_OPT(filter) m_display->WriteElementAddressNamed( eltName, name, ptr, size ); } while(0)
301 #define DisplayWriteElementAddressNamedW(eltName, name, ptr, size, filter) \
302 do { IF_OPT(filter) m_display->WriteElementAddressNamedW( eltName, name, ptr, size ); } while(0)
304 #define DisplayWriteFieldString(field, value, type, filter) \
305 do { IF_OPT(filter) m_display->WriteFieldString( # field, offsetof(type, field), fieldsize(type, field), value ); } while(0)
306 #define DisplayWriteFieldStringW(field, value, type, filter) \
307 do { IF_OPT(filter) m_display->WriteFieldStringW( # field, offsetof(type, field), fieldsize(type, field), value ); } while(0)
308 #define DisplayWriteFieldInt(field, value, type, filter) \
309 do { IF_OPT(filter) m_display->WriteFieldInt( # field, offsetof(type, field), fieldsize(type, field), value ); } while(0)
310 #define DisplayWriteFieldUInt(field, value, type, filter) \
311 do { IF_OPT(filter) m_display->WriteFieldUInt( # field, offsetof(type, field), fieldsize(type, field), value ); } while(0)
312 #define DisplayWriteFieldPointer(field, ptr, type, filter) \
313 do { IF_OPT(filter) m_display->WriteFieldPointer( # field, offsetof(type, field), fieldsize(type, field), ptr ); } while(0)
314 #define DisplayWriteFieldPointerWithSize(field, ptr, size, type, filter) \
315 do { IF_OPT(filter) m_display->WriteFieldPointerWithSize( # field, offsetof(type, field), fieldsize(type, field), ptr, size ); } while(0)
316 #define DisplayWriteFieldEmpty(field, type, filter) \
317 do { IF_OPT(filter) m_display->WriteFieldEmpty( # field, offsetof(type, field), fieldsize(type, field) ); } while(0)
318 #define DisplayWriteFieldFlag(field, value, type, filter) \
319 do { IF_OPT(filter) m_display->WriteFieldFlag(# field, offsetof(type, field), fieldsize(type, field), value); } while(0)
320 #define WriteFieldFieldDesc(field, ptr, type, filter) \
321 do { IF_OPT(filter) DoWriteFieldFieldDesc( # field, offsetof(type, field), fieldsize(type, field), ptr ); } while(0)
322 #define WriteFieldMethodDesc(field, ptr, type, filter) \
323 do { IF_OPT(filter) DoWriteFieldMethodDesc( # field, offsetof(type, field), fieldsize(type, field), ptr ); } while(0)
324 #define WriteFieldStr(field, ptr, type, filter) \
325 do { IF_OPT(filter) DoWriteFieldStr( ptr, # field, offsetof(type, field), fieldsize(type, field) ); } while(0)
326 #define WriteFieldMethodTable(field, ptr, type, filter) \
327 do { IF_OPT(filter) DoWriteFieldMethodTable( # field, offsetof(type, field), fieldsize(type, field), ptr ); } while(0)
328 #define WriteFieldMDToken(field, token, type, filter) \
329 do { IF_OPT(filter) DoWriteFieldMDToken( # field, offsetof(type, field), fieldsize(type, field), token ); } while(0)
330 #define WriteFieldAsHex(field, ptr, type, filter) \
331 do { IF_OPT(filter) DoWriteFieldAsHex( # field, offsetof(type, field), fieldsize(type, field), ptr, fieldsize(type, field)); } while(0)
332 #define WriteFieldMDTokenImport(field, token, type, filter, import) \
333 do { IF_OPT(filter) DoWriteFieldMDToken( # field, offsetof(type, field), fieldsize(type, field), token, import); } while(0)
334 #define WriteFieldTypeHandle(field, ptr, type, filter) \
335 do { IF_OPT(filter) DoWriteFieldTypeHandle( # field, offsetof(type, field), fieldsize(type, field), ptr ); } while(0)
336 #define WriteFieldCorElementType(field, et, type, filter) \
337 do { IF_OPT(filter) DoWriteFieldCorElementType( # field, offsetof(type, field), fieldsize(type, field), et ); } while(0)
338 #define DumpFieldStub(field, ptr, type, filter) \
339 do { IF_OPT(filter) DoDumpFieldStub( ptr, offsetof(type, field), fieldsize(type, field), # field ); } while(0)
340 #define DumpComPlusCallInfo(compluscall, filter) \
341 do { IF_OPT(filter) DoDumpComPlusCallInfo( compluscall ); } while(0)
342 #define DisplayWriteFieldPointerAnnotated(field, ptr, annotation, type, filter) \
343 do { IF_OPT(filter) m_display->WriteFieldPointer( # field, offsetof(type, field), fieldsize(type, field), ptr ); } while(0)
344 #define DisplayWriteFieldAddress(field, ptr, size, type, filter) \
345 do { IF_OPT(filter) m_display->WriteFieldAddress( # field, offsetof(type, field), fieldsize(type, field), ptr, size ); } while(0)
346 #define DisplayStartTextElement(name, filter) \
347 do { IF_OPT(filter) m_display->StartTextElement( name ); } while(0)
348 #define DisplayEndTextElement(filter) \
349 do { IF_OPT(filter) m_display->EndTextElement(); } while(0)
350 #define DisplayWriteXmlText( args, filter ) \
351 do { IF_OPT(filter) m_display->WriteXmlText args; } while(0)
352 #define DisplayWriteXmlTextBlock( args, filter ) \
353 do { IF_OPT(filter) m_display->WriteXmlTextBlock args; } while(0)
355 #define CoverageRead( ptr, size ) \
356 do { IF_OPT(DEBUG_COVERAGE) PTR_READ(TO_TADDR(ptr), size); } while(0)
357 #define CoverageReadString( taddr ) \
358 do { PTR_BYTE ptr(TO_TADDR(taddr)); while( *ptr++ ); }while(0)
360 void AppendNilToken( mdToken token, SString& buf )
362 _ASSERTE(RidFromToken(token) == mdTokenNil);
364 const WCHAR * id = NULL;
367 #define mdNilEnt(x) case x: \
370 mdNilEnt(mdModuleNil);
371 mdNilEnt(mdTypeRefNil);
372 mdNilEnt(mdTypeDefNil);
373 mdNilEnt(mdFieldDefNil);
374 mdNilEnt(mdMethodDefNil);
375 mdNilEnt(mdParamDefNil);
376 mdNilEnt(mdInterfaceImplNil);
377 mdNilEnt(mdMemberRefNil);
378 mdNilEnt(mdCustomAttributeNil);
379 mdNilEnt(mdPermissionNil);
380 mdNilEnt(mdSignatureNil);
381 mdNilEnt(mdEventNil);
382 mdNilEnt(mdPropertyNil);
383 mdNilEnt(mdModuleRefNil);
384 mdNilEnt(mdTypeSpecNil);
385 mdNilEnt(mdAssemblyNil);
386 mdNilEnt(mdAssemblyRefNil);
388 mdNilEnt(mdExportedTypeNil);
389 mdNilEnt(mdManifestResourceNil);
391 mdNilEnt(mdGenericParamNil);
392 mdNilEnt(mdGenericParamConstraintNil);
393 mdNilEnt(mdMethodSpecNil);
395 mdNilEnt(mdStringNil);
400 void appendByteArray(SString& buf, const BYTE * bytes, ULONG cbBytes)
402 for( COUNT_T i = 0; i < cbBytes; ++i )
404 buf.AppendPrintf(W("%02x"), bytes[i]);
412 struct OptionDependencies
414 OptionDependencies(CLRNativeImageDumpOptions value,
415 CLRNativeImageDumpOptions dep) : m_value(value),
420 CLRNativeImageDumpOptions m_value;
421 CLRNativeImageDumpOptions m_dep;
424 static OptionDependencies g_dependencies[] =
426 #define OPT_DEP(value, dep) OptionDependencies(CLRNATIVEIMAGE_ ## value,\
427 CLRNATIVEIMAGE_ ## dep)
428 OPT_DEP(RESOURCES, COR_INFO),
429 OPT_DEP(METADATA, COR_INFO),
430 OPT_DEP(PRECODES, MODULE),
431 //Does methoddescs require ModuleTables?
432 OPT_DEP(VERBOSE_TYPES, METHODDESCS),
433 OPT_DEP(GC_INFO, METHODS),
434 OPT_DEP(FROZEN_SEGMENT, MODULE),
435 OPT_DEP(SLIM_MODULE_TBLS, MODULE),
436 OPT_DEP(MODULE_TABLES, SLIM_MODULE_TBLS),
437 OPT_DEP(DISASSEMBLE_CODE, METHODS),
439 OPT_DEP(FIXUP_HISTOGRAM, FIXUP_TABLES),
440 OPT_DEP(FIXUP_THUNKS, FIXUP_TABLES),
445 // Metadata helpers for DAC
446 // This is mostly copied from mscoree.cpp which isn't available in mscordacwks.dll.
449 // This function gets the Dispenser interface given the CLSID and REFIID.
450 STDAPI DLLEXPORT MetaDataGetDispenser(
451 REFCLSID rclsid, // The class to desired.
452 REFIID riid, // Interface wanted on class factory.
453 LPVOID FAR * ppv) // Return interface pointer here.
455 _ASSERTE(rclsid == CLSID_CorMetaDataDispenser);
457 return InternalCreateMetaDataDispenser(riid, ppv);
461 NativeImageDumper::NativeImageDumper(PTR_VOID loadedBase,
462 const WCHAR * const name,
463 IXCLRDataDisplay * display,
464 IXCLRLibrarySupport * support,
465 IXCLRDisassemblySupport *dis)
467 m_decoder(loadedBase),
469 m_baseAddress(loadedBase),
471 m_librarySupport(support),
473 m_assemblyImport(NULL),
474 m_manifestAssemblyImport(NULL),
475 m_dependencies(NULL),
480 m_isMscorlibHardBound(false),
481 m_sectionAlignment(0)
483 IfFailThrow(m_display->GetDumpOptions(&m_dumpOptions));
485 //set up mscorwks stuff.
486 m_mscorwksBase = DacGlobalBase();
487 _ASSERTE(m_mscorwksBase);
488 PEDecoder mscorwksDecoder(dac_cast<PTR_VOID>(m_mscorwksBase));
489 m_mscorwksSize = mscorwksDecoder.GetSize();
490 m_mscorwksPreferred = TO_TADDR(mscorwksDecoder.GetPreferredBase());
491 //add implied options (i.e. if you want to dump the module, you also have
492 //to dump the native info.
493 CLRNativeImageDumpOptions current;
496 current = m_dumpOptions;
497 for( unsigned i = 0; i < _countof(g_dependencies); ++i )
499 if( m_dumpOptions & g_dependencies[i].m_value )
500 m_dumpOptions |= g_dependencies[i].m_dep;
502 }while( current != m_dumpOptions );
503 IF_OPT(DISASSEMBLE_CODE)
505 //configure the disassembler
506 m_dis->SetTranslateAddrCallback(TranslateAddressCallback);
507 m_dis->SetTranslateFixupCallback(TranslateFixupCallback);
508 m_dis->PvClientSet(this);
512 void GuidToString( GUID& guid, SString& s )
514 WCHAR guidString[64];
515 GuidToLPWSTR(guid, guidString, sizeof(guidString) / sizeof(WCHAR));
517 _ASSERTE(guidString[0] == W('{')
518 && guidString[wcslen(guidString) - 1] == W('}'));
519 guidString[wcslen(guidString) - 1] = W('\0');
520 s.Append( guidString + 1 );
523 NativeImageDumper::~NativeImageDumper()
527 inline const void * ptr_add(const void * ptr, COUNT_T size)
529 return reinterpret_cast<const BYTE *>(ptr) + size;
532 //This does pointer arithmetic on a DPtr.
534 inline const DPTR(T) dptr_add(T* ptr, COUNT_T offset)
536 return DPTR(T)(PTR_HOST_TO_TADDR(ptr) + (offset * sizeof(T)));
540 inline const DPTR(T) dptr_sub(T* ptr, COUNT_T offset)
542 return DPTR(T)(PTR_HOST_TO_TADDR(ptr) - (offset * sizeof(T)));
545 inline const DPTR(T) dptr_sub(DPTR(T)* ptr, COUNT_T offset)
547 return DPTR(T)(PTR_HOST_TO_TADDR(ptr) - (offset * sizeof(T)));
552 MDTableType(unsigned t, const char * n) : m_token(t), m_name(n) { }
557 static unsigned s_tableTypes[] =
563 #define MiniMdTable(x) TBL_##x << 24,
590 mdtGenericParamConstraint,
593 const NativeImageDumper::EnumMnemonics s_CorHdrFlags[] =
595 #define CHF_ENTRY(f,v) NativeImageDumper::EnumMnemonics(f, v)
596 CHF_ENTRY(COMIMAGE_FLAGS_ILONLY, W("IL Only")),
597 CHF_ENTRY(COMIMAGE_FLAGS_32BITREQUIRED, W("32-bit Required")),
598 CHF_ENTRY(COMIMAGE_FLAGS_IL_LIBRARY, W("IL Library")),
599 CHF_ENTRY(COMIMAGE_FLAGS_STRONGNAMESIGNED, W("Strong Name Signed")),
600 CHF_ENTRY(COMIMAGE_FLAGS_NATIVE_ENTRYPOINT, W("Has Native Entrypoint")),
601 CHF_ENTRY(COMIMAGE_FLAGS_TRACKDEBUGDATA, W("Track Debug Data")),
602 CHF_ENTRY(COMIMAGE_FLAGS_32BITPREFERRED, W("32-bit Preferred"))
606 void NativeImageDumper::DumpAssemblySignature(CORCOMPILE_ASSEMBLY_SIGNATURE & assemblySignature)
610 GuidToString(assemblySignature.mvid, buf);
611 DisplayWriteFieldStringW( mvid, (const WCHAR*)buf,
612 CORCOMPILE_ASSEMBLY_SIGNATURE,
615 DisplayWriteFieldInt( timeStamp, assemblySignature.timeStamp,
616 CORCOMPILE_ASSEMBLY_SIGNATURE, COR_INFO );
617 DisplayWriteFieldInt( ilImageSize,
618 assemblySignature.ilImageSize,
619 CORCOMPILE_ASSEMBLY_SIGNATURE, COR_INFO );
625 NativeImageDumper::DumpNativeImage()
630 m_display->StartDocument();
632 DisplayStartCategory( "File", PE_INFO );
633 DisplayWriteElementStringW( "path", m_name, PE_INFO );
635 DisplayWriteElementInt( "diskSize", m_decoder.GetSize(), PE_INFO );
636 _ASSERTE(sizeof(IMAGE_DOS_HEADER) < m_decoder.GetSize());
638 PTR_IMAGE_DOS_HEADER dosHeader =
639 PTR_IMAGE_DOS_HEADER(dac_cast<TADDR>(m_baseAddress));
640 DisplayWriteElementAddress( "IMAGE_DOS_HEADER",
641 DPtrToPreferredAddr(dosHeader),
642 sizeof(*dosHeader), PE_INFO );
646 if (!m_decoder.HasNTHeaders())
650 DisplayWriteElementString("isPEFile", "false", PE_INFO);
651 DisplayEndCategory(PE_INFO);
654 m_display->ErrorPrintF("Non-PE file");
656 m_display->EndDocument();
660 CONSISTENCY_CHECK(m_decoder.CheckNTHeaders());
661 if (!m_decoder.CheckNTHeaders())
663 m_display->ErrorPrintF("*** NT headers are not valid ***");
667 DisplayWriteElementString("imageType", m_decoder.Has32BitNTHeaders()
668 ? "32 bit image" : "64 bit image", PE_INFO);
669 DisplayWriteElementAddress("address", (SIZE_T)m_decoder.GetNativePreferredBase(),
670 m_decoder.GetVirtualSize(), PE_INFO);
671 DisplayWriteElementInt( "TimeDateStamp", m_decoder.GetTimeDateStamp(),
674 if( m_decoder.Has32BitNTHeaders() )
676 PTR_IMAGE_NT_HEADERS32 ntHeaders(m_decoder.GetNTHeaders32());
677 //base, size, sectionAlign
678 _ASSERTE(ntHeaders->OptionalHeader.SectionAlignment >=
679 ntHeaders->OptionalHeader.FileAlignment);
680 m_imageSize = ntHeaders->OptionalHeader.SizeOfImage;
681 m_display->NativeImageDimensions(PTR_TO_TADDR(m_decoder.GetBase()),
682 ntHeaders->OptionalHeader.SizeOfImage,
683 ntHeaders->OptionalHeader.SectionAlignment);
684 /* REVISIT_TODO Mon 11/21/2005
685 * I don't understand this. Sections start on a two page boundary, but
686 * data ends on a one page boundary. What's up with that?
688 m_sectionAlignment = GetOsPageSize(); //ntHeaders->OptionalHeader.SectionAlignment;
689 unsigned ntHeaderSize = sizeof(*ntHeaders)
690 - sizeof(ntHeaders->OptionalHeader)
691 + ntHeaders->FileHeader.SizeOfOptionalHeader;
692 DisplayWriteElementAddress( "IMAGE_NT_HEADERS32",
693 DPtrToPreferredAddr(ntHeaders),
694 ntHeaderSize, PE_INFO );
699 PTR_IMAGE_NT_HEADERS64 ntHeaders(m_decoder.GetNTHeaders64());
700 //base, size, sectionAlign
701 _ASSERTE(ntHeaders->OptionalHeader.SectionAlignment >=
702 ntHeaders->OptionalHeader.FileAlignment);
703 m_imageSize = ntHeaders->OptionalHeader.SizeOfImage;
704 m_display->NativeImageDimensions((SIZE_T)ntHeaders->OptionalHeader.ImageBase,
705 ntHeaders->OptionalHeader.SizeOfImage,
706 ntHeaders->OptionalHeader.SectionAlignment);
707 m_sectionAlignment = ntHeaders->OptionalHeader.SectionAlignment;
708 unsigned ntHeaderSize = sizeof(*ntHeaders)
709 - sizeof(ntHeaders->OptionalHeader)
710 + ntHeaders->FileHeader.SizeOfOptionalHeader;
711 DisplayWriteElementAddress( "IMAGE_NT_HEADERS64",
712 DPtrToPreferredAddr(ntHeaders),
713 ntHeaderSize, PE_INFO );
715 DisplayEndCategory(PE_INFO);
719 DisplayStartArray("Sections", W("%-8s%s\t(disk %s) %s"), PE_INFO);
721 for (COUNT_T i = 0; i < m_decoder.GetNumberOfSections(); i++)
723 PTR_IMAGE_SECTION_HEADER section = m_decoder.FindFirstSection() + i;
724 m_display->Section(reinterpret_cast<char *>(section->Name),
725 section->VirtualAddress,
726 section->SizeOfRawData);
727 DisplayStartStructure( "Section", DPtrToPreferredAddr(section),
728 sizeof(*section), PE_INFO );
729 DisplayWriteElementString("name", (const char *)section->Name, PE_INFO);
730 DisplayWriteElementAddress( "address", RvaToDisplay(section->VirtualAddress),
731 section->Misc.VirtualSize, PE_INFO );
732 DisplayWriteElementAddress( "disk", section->PointerToRawData,
733 section->SizeOfRawData, PE_INFO );
735 DisplayWriteElementEnumerated( "access", section->Characteristics,
736 s_ImageSections, W(", "), PE_INFO );
737 DisplayEndStructure( PE_INFO ); //Section
739 DisplayEndArray("Total Sections", PE_INFO);
741 // Image directory info
743 DisplayStartArray( "Directories", W("%-40s%s"), PE_INFO );
745 for ( COUNT_T i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
747 static const char *directoryNames[] =
749 /* 0*/"IMAGE_DIRECTORY_ENTRY_EXPORT",
750 /* 1*/"IMAGE_DIRECTORY_ENTRY_IMPORT",
751 /* 2*/"IMAGE_DIRECTORY_ENTRY_RESOURCE",
752 /* 3*/"IMAGE_DIRECTORY_ENTRY_EXCEPTION",
753 /* 4*/"IMAGE_DIRECTORY_ENTRY_SECURITY",
754 /* 5*/"IMAGE_DIRECTORY_ENTRY_BASERELOC",
755 /* 6*/"IMAGE_DIRECTORY_ENTRY_DEBUG",
756 /* 7*/"IMAGE_DIRECTORY_ENTRY_ARCHITECTURE",
757 /* 8*/"IMAGE_DIRECTORY_ENTRY_GLOBALPTR",
758 /* 9*/"IMAGE_DIRECTORY_ENTRY_TLS",
759 /*10*/"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG",
760 /*11*/"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
761 /*12*/"IMAGE_DIRECTORY_ENTRY_IAT",
762 /*13*/"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT",
763 /*14*/"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
767 IMAGE_DATA_DIRECTORY *entry = m_decoder.GetDirectoryEntry(i);
769 if (entry->VirtualAddress != 0)
771 DisplayStartElement("Directory", PE_INFO);
772 DisplayWriteElementString("name", directoryNames[i], PE_INFO);
773 DisplayWriteElementAddress("address",
774 RvaToDisplay(entry->VirtualAddress),
775 entry->Size, PE_INFO);
777 DisplayEndElement( PE_INFO ); //Directory
780 DisplayEndArray("Total Directories", PE_INFO); //Directories
784 if (!m_decoder.HasCorHeader())
787 DisplayWriteElementString("CLRInfo", "<none>", COR_INFO);
789 m_display->ErrorPrintF("Non-CLR image\n");
791 m_display->EndDocument();
795 CONSISTENCY_CHECK(m_decoder.CheckCorHeader());
796 if (!m_decoder.CheckCorHeader())
798 m_display->ErrorPrintF("*** INVALID CLR Header ***");
799 m_display->EndDocument();
803 DisplayStartCategory("CLRInfo", COR_INFO);
804 PTR_IMAGE_COR20_HEADER pCor(m_decoder.GetCorHeader());
806 #define WRITE_COR20_FIELD( name ) m_display->WriteFieldAddress( \
807 # name, offsetof(IMAGE_COR20_HEADER, name), \
808 fieldsize(IMAGE_COR20_HEADER, name), \
809 RvaToDisplay( pCor-> name . VirtualAddress ), \
812 m_display->StartStructure( "IMAGE_COR20_HEADER",
813 DPtrToPreferredAddr(pCor),
816 DisplayWriteFieldUInt( MajorRuntimeVersion, pCor->MajorRuntimeVersion, IMAGE_COR20_HEADER, COR_INFO );
817 DisplayWriteFieldUInt( MinorRuntimeVersion, pCor->MinorRuntimeVersion, IMAGE_COR20_HEADER, COR_INFO );
819 // Symbol table and startup information
820 WRITE_COR20_FIELD(MetaData);
821 DisplayWriteFieldEnumerated( Flags, pCor->Flags, IMAGE_COR20_HEADER, s_CorHdrFlags, W(", "), COR_INFO );
822 DisplayWriteFieldUInt( EntryPointToken, pCor->EntryPointToken, IMAGE_COR20_HEADER, COR_INFO );
824 // Binding information
825 WRITE_COR20_FIELD(Resources);
826 WRITE_COR20_FIELD(StrongNameSignature);
828 // Regular fixup and binding information
829 WRITE_COR20_FIELD(CodeManagerTable);
830 WRITE_COR20_FIELD(VTableFixups);
831 WRITE_COR20_FIELD(ExportAddressTableJumps);
833 // Precompiled image info
834 WRITE_COR20_FIELD(ManagedNativeHeader);
836 m_display->EndStructure(); //IMAGE_COR20_HEADER
837 #undef WRITE_COR20_FIELD
840 //make sure to touch the strong name signature even if we won't print it.
841 if (m_decoder.HasStrongNameSignature())
843 if (m_decoder.IsStrongNameSigned())
845 DACCOP_IGNORE(CastBetweenAddressSpaces,"nidump is in-proc and doesn't maintain a clean separation of address spaces (target and host are the same.");
846 data = reinterpret_cast<void*>(dac_cast<TADDR>(m_decoder.GetStrongNameSignature(&size)));
852 appendByteArray(sig, (BYTE*)data, size);
854 DisplayWriteElementStringW( "StrongName", (const WCHAR *)sig,
860 DisplayWriteEmptyElement("DelaySigned", COR_INFO);
864 #ifdef FEATURE_READYTORUN
865 if (m_decoder.HasReadyToRunHeader())
866 DisplayWriteElementString( "imageType", "ReadyToRun image", COR_INFO);
869 if (m_decoder.IsILOnly())
870 DisplayWriteElementString( "imageType", "IL only image", COR_INFO);
872 if (m_decoder.HasNativeHeader())
873 DisplayWriteElementString( "imageType", "Native image", COR_INFO);
875 DisplayWriteElementString( "imageType", "Mixed image", COR_INFO);
877 DACCOP_IGNORE(CastBetweenAddressSpaces,"nidump is in-proc and doesn't maintain a clean separation of address spaces (target and host are the same.");
878 data = reinterpret_cast<void*>(dac_cast<TADDR>(m_decoder.GetMetadata(&size)));
882 DWORD dwAssemblyFlags = 0;
883 IfFailThrow(m_manifestAssemblyImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL,
886 NULL, &dwAssemblyFlags));
887 if ((afContentType_WindowsRuntime & dwAssemblyFlags) == afContentType_WindowsRuntime)
889 // The WinMD adapter doesn't implement the IID_IMetaDataTables interface so we can't dump
891 DisplayWriteElementString ("Metadata", "Not supported by WinRT", COR_INFO);
895 WriteElementsMetadata( "Metadata", TO_TADDR(data), size );
899 CoverageRead(TO_TADDR(data), size);
901 if (m_decoder.HasNativeHeader())
903 DACCOP_IGNORE(CastBetweenAddressSpaces,"nidump is in-proc and doesn't maintain a clean separation of address spaces (target and host are the same.");
904 data = reinterpret_cast<void*>(dac_cast<TADDR>(m_decoder.GetNativeManifestMetadata(&size)));
908 WriteElementsMetadata( "NativeManifestMetadata", TO_TADDR(data), size );
912 DisplayWriteElementAddress( "NativeManifestMetadata",
913 DataPtrToDisplay((TADDR)data), size,
918 /* REVISIT_TODO Tue 09/20/2005
919 * Anything to display in the native metadata?
921 CoverageRead(TO_TADDR(data), size);
923 /* REVISIT_TODO Tue 09/20/2005
924 * Dump the debug map? Indexed by method RID... probably a good idea
926 data = reinterpret_cast<void*>(m_decoder.GetNativeDebugMap(&size));
928 DisplayWriteElementAddress( "debugMap", DataPtrToDisplay((TADDR)data), size,
930 CoverageRead(TO_TADDR(data), size);
932 //also read the entire debug map section
933 IMAGE_SECTION_HEADER * dbgmap = FindSection( ".dbgmap" );
936 CoverageRead(TO_TADDR(dbgmap->VirtualAddress)
937 + PTR_TO_TADDR(m_decoder.GetBase()),
938 (ULONG32)ALIGN_UP(dbgmap->Misc.VirtualSize, GetSectionAlignment()));
941 //read the .il and .rsrc sections in their entirety
942 IF_OPT(DEBUG_COVERAGE)
944 IMAGE_SECTION_HEADER *hdr;
945 hdr = FindSection( ".rsrc" );
948 CoverageRead( m_decoder.GetRvaData(hdr->VirtualAddress),
949 (ULONG32)hdr->Misc.VirtualSize );
952 IF_OPT_OR(DEBUG_COVERAGE, IL)
954 IMAGE_SECTION_HEADER *hdr = FindSection( ".text" );
958 m_ILSectionStart = hdr->VirtualAddress;
959 m_ILHostCopy = (BYTE*)PTR_READ(m_decoder.GetRvaData(hdr->VirtualAddress), hdr->Misc.VirtualSize);
961 m_ILSectionSize = hdr->Misc.VirtualSize;
966 m_ILSectionStart = 0;
972 _ASSERTE( (((TADDR)m_ILHostCopy) & 3) == 0 );
973 _ASSERTE((m_ILSectionStart & 3) == 0);
978 data = m_decoder.GetResources(&size);
981 DisplayStartStructure( "resource", DataPtrToDisplay((TADDR)data), size,
983 DisplayStartArray( "Resources", NULL, COR_INFO );
984 HCORENUM hEnum = NULL;
987 mdManifestResource resTokens[1];
989 IfFailThrow(m_assemblyImport->EnumManifestResources(&hEnum,
996 WCHAR resourceName[256];
1000 IfFailThrow(m_assemblyImport->GetManifestResourceProps(resTokens[0],
1002 _countof(resourceName),
1007 if( RidFromToken(impl) != 0 )
1008 continue; //skip all non-zero providers
1009 resourceName[nameLen] = W('\0');
1010 DPTR(DWORD UNALIGNED) res(TO_TADDR(data) + offset);
1011 DWORD resSize = *res;
1012 DisplayWriteElementAddressNamedW( "Resource", resourceName,
1013 DPtrToPreferredAddr(res),
1014 resSize + sizeof(DWORD),
1017 DisplayEndArray( "Total Resources", COR_INFO ); //Resources
1018 DisplayEndStructure( COR_INFO ); //resource
1022 DisplayWriteElementAddress( "resource", DataPtrToDisplay((TADDR)data), size,
1028 m_manifestImport->GetScopeProps(bigBuffer, bigBufferSize, &resultSize, &mvid);
1029 /* REVISIT_TODO Wed 09/07/2005
1030 * The name is the .module entry. Why isn't it present in the ngen image?
1032 TempBuffer guidString;
1033 GuidToString( mvid, guidString );
1034 if( wcslen(bigBuffer) )
1035 DisplayWriteElementStringW( "scopeName", bigBuffer, COR_INFO );
1036 DisplayWriteElementStringW( "mvid", (const WCHAR *)guidString, COR_INFO );
1038 if (m_decoder.HasManagedEntryPoint())
1040 DisplayStartVStructure( "ManagedEntryPoint", COR_INFO );
1041 unsigned token = m_decoder.GetEntryPointToken();
1042 DisplayWriteElementUInt( "Token", token, COR_INFO );
1044 AppendTokenName( token, buf );
1045 DisplayWriteElementStringW( "TokenName", (const WCHAR *)buf, COR_INFO );
1046 DisplayEndVStructure( COR_INFO );
1048 else if (m_decoder.HasNativeEntryPoint())
1050 DisplayWriteElementPointer( "NativeEntryPoint", (SIZE_T)m_decoder.GetNativeEntryPoint(),
1054 /* REVISIT_TODO Mon 11/21/2005
1055 * Dump the version info completely
1057 if( m_decoder.HasNativeHeader() )
1059 PTR_CORCOMPILE_VERSION_INFO versionInfo( m_decoder.GetNativeVersionInfo() );
1061 DisplayStartStructure("CORCOMPILE_VERSION_INFO",
1062 DPtrToPreferredAddr(versionInfo),
1063 sizeof(*versionInfo), COR_INFO);
1065 DisplayStartStructureWithOffset( sourceAssembly,
1066 DPtrToPreferredAddr(versionInfo) + offsetof(CORCOMPILE_VERSION_INFO, sourceAssembly),
1067 sizeof(versionInfo->sourceAssembly),
1068 CORCOMPILE_VERSION_INFO, COR_INFO );
1069 DumpAssemblySignature(versionInfo->sourceAssembly);
1070 DisplayEndStructure(COR_INFO); //sourceAssembly
1073 PTR_CORCOMPILE_DEPENDENCY deps(TO_TADDR(m_decoder.GetNativeDependencies(&numDeps)));
1075 DisplayStartArray( "Dependencies", NULL, COR_INFO );
1077 for( COUNT_T i = 0; i < numDeps; ++i )
1079 DisplayStartStructure("CORCOMPILE_DEPENDENCY", DPtrToPreferredAddr(deps + i),
1080 sizeof(deps[i]), COR_INFO );
1081 WriteFieldMDTokenImport( dwAssemblyRef, deps[i].dwAssemblyRef,
1082 CORCOMPILE_DEPENDENCY, COR_INFO,
1084 WriteFieldMDTokenImport( dwAssemblyDef, deps[i].dwAssemblyDef,
1085 CORCOMPILE_DEPENDENCY, COR_INFO,
1087 DisplayStartStructureWithOffset( signAssemblyDef,
1088 DPtrToPreferredAddr(deps + i) + offsetof(CORCOMPILE_DEPENDENCY, signAssemblyDef),
1089 sizeof(deps[i]).signAssemblyDef,
1090 CORCOMPILE_DEPENDENCY, COR_INFO );
1091 DumpAssemblySignature(deps[i].signAssemblyDef);
1092 DisplayEndStructure(COR_INFO); //signAssemblyDef
1096 if( deps[i].signNativeImage == INVALID_NGEN_SIGNATURE )
1098 buf.Append( W("INVALID_NGEN_SIGNATURE") );
1102 GuidToString(deps[i].signNativeImage, buf);
1104 DisplayWriteFieldStringW( signNativeImage, (const WCHAR*)buf,
1105 CORCOMPILE_DEPENDENCY, COR_INFO );
1107 if( m_librarySupport
1108 && deps[i].signNativeImage != INVALID_NGEN_SIGNATURE )
1111 AppendTokenName(deps[i].dwAssemblyRef, buf, m_import );
1112 IfFailThrow(m_librarySupport->LoadDependency( (const WCHAR*)buf,
1113 deps[i].signNativeImage ));
1120 DisplayEndStructure(COR_INFO); //CORCOMPILE_DEPENDENCY
1122 DisplayEndArray( "Total Dependencies", COR_INFO );
1123 DisplayEndStructure(COR_INFO); //CORCOMPILE_VERSION_INFO
1125 NativeImageDumper::Dependency * traceDependency = OpenDependency(0);
1126 TraceDumpDependency( 0, traceDependency );
1128 for( COUNT_T i = 0; i < numDeps; ++i )
1130 traceDependency = OpenDependency( i + 1 );
1131 TraceDumpDependency( i + 1, traceDependency );
1133 _ASSERTE(m_dependencies[0].pModule != NULL);
1135 /* XXX Wed 12/14/2005
1136 * Now for the real insanity. I need to initialize static classes in
1137 * the DAC. First I need to find mscorlib's dependency entry. Search
1138 * through all of the dependencies to find the one marked as
1139 * fIsMscorlib. If I don't find anything marked that way, then "self"
1142 Dependency * mscorlib = NULL;
1143 for( COUNT_T i = 0; i < m_numDependencies; ++i )
1145 if( m_dependencies[i].fIsMscorlib )
1147 mscorlib = &m_dependencies[i];
1152 //If we're actually dumping mscorlib, remap the mscorlib dependency to our own native image.
1153 if( (mscorlib == NULL) || !wcscmp(m_name, CoreLibName_W))
1155 mscorlib = GetDependency(0);
1156 mscorlib->fIsMscorlib = TRUE;
1157 _ASSERTE(mscorlib->fIsHardbound);
1160 _ASSERTE(mscorlib != NULL);
1161 if( mscorlib->fIsHardbound )
1163 m_isMscorlibHardBound = true;
1165 if( m_isMscorlibHardBound )
1167 //go through the module to the binder.
1168 PTR_Module mscorlibModule = mscorlib->pModule;
1170 PTR_MscorlibBinder binder = mscorlibModule->m_pBinder;
1171 g_Mscorlib = *binder;
1173 PTR_MethodTable mt = MscorlibBinder::GetExistingClass(CLASS__OBJECT);
1174 g_pObjectClass = mt;
1178 if (g_pObjectClass == NULL)
1180 //if mscorlib is not hard bound, then warn the user (many features of nidump are shut off)
1181 m_display->ErrorPrintF( "Assembly %S is soft bound to mscorlib. nidump cannot dump MethodTables completely.\n", m_name );
1182 // TritonTODO: reason?
1183 // reset "hard bound state"
1184 m_isMscorlibHardBound = false;
1190 // @todo: VTable Fixups
1194 DisplayEndCategory(COR_INFO); //CLRInfo
1196 #ifdef FEATURE_READYTORUN
1197 if (m_decoder.HasReadyToRunHeader())
1203 if (m_decoder.HasNativeHeader())
1208 m_display->EndDocument();
1211 void NativeImageDumper::DumpNative()
1213 DisplayStartCategory("NativeInfo", NATIVE_INFO);
1215 CONSISTENCY_CHECK(m_decoder.CheckNativeHeader());
1216 if (!m_decoder.CheckNativeHeader())
1218 m_display->ErrorPrintF("*** INVALID NATIVE HEADER ***\n");
1226 CORCOMPILE_EE_INFO_TABLE * infoTable = m_decoder.GetNativeEEInfoTable();
1228 DisplayStartStructure( "CORCOMPILE_EE_INFO_TABLE",
1229 DataPtrToDisplay(PTR_HOST_TO_TADDR(infoTable)),
1230 sizeof(*infoTable), NATIVE_INFO );
1232 /* REVISIT_TODO Mon 09/26/2005
1233 * Move this further down to include the dumping of the module, and
1236 DisplayEndStructure(NATIVE_INFO); //NativeInfoTable
1237 DisplayEndCategory(NATIVE_INFO); //NativeInfo
1239 //come back here and dump all the fields of the CORCOMPILE_EE_INFO_TABLE
1245 IF_OPT(NATIVE_TABLES)
1248 PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
1250 //this needs to run for precodes to load the tables that identify precode ranges
1251 IF_OPT_OR5(MODULE, METHODTABLES, EECLASSES, TYPEDESCS, PRECODES)
1254 IF_OPT_OR3(FIXUP_TABLES, FIXUP_HISTOGRAM, FIXUP_THUNKS)
1255 DumpFixupTables( module );
1256 IF_OPT_OR3(METHODS, GC_INFO, DISASSEMBLE_CODE )
1257 DumpMethods( module );
1258 IF_OPT_OR3(METHODTABLES, EECLASSES, TYPEDESCS)
1259 DumpTypes( module );
1262 void NativeImageDumper::TraceDumpDependency(int idx, NativeImageDumper::Dependency * dependency)
1266 m_display->ErrorPrintF("Dependency: %d (%p)\n", idx, dependency);
1267 m_display->ErrorPrintF("\tPreferred: %p\n", dependency->pPreferredBase);
1268 m_display->ErrorPrintF("\tLoaded: %p\n", dependency->pLoadedAddress);
1269 m_display->ErrorPrintF("\tSize: %x (%d)\n", dependency->size, dependency->size);
1270 m_display->ErrorPrintF("\tModule: P=%p, L=%p\n", DataPtrToDisplay(dac_cast<TADDR>(dependency->pModule)),
1271 PTR_TO_TADDR(dependency->pModule));
1272 m_display->ErrorPrintF("Mscorlib=%s, Hardbound=%s\n",
1273 (dependency->fIsMscorlib ? "true" : "false"),
1274 (dependency->fIsHardbound ? "true" : "false"));
1275 m_display->ErrorPrintF("Name: %S\n", dependency->name);
1279 void NativeImageDumper::WriteElementsMetadata( const char * elementName,
1280 TADDR data, SIZE_T size )
1282 DisplayStartStructure( elementName,
1283 DataPtrToDisplay(data), size, ALWAYS );
1285 /* XXX Mon 03/13/2006
1286 * Create new metatadata dispenser. When I define the Emit for defining
1287 * assemblyrefs for dependencies, I copy the memory and totally hork any
1288 * mapping back to base addresses.
1290 ReleaseHolder<IMetaDataTables> tables;
1291 ReleaseHolder<IMetaDataDispenserEx> pDispenser;
1292 IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
1293 IID_IMetaDataDispenserEx, (void **) &pDispenser));
1297 TADDR hostCopyStart = TO_TADDR(PTR_READ(data, (ULONG32)size));
1298 TADDR rebasedPointer;
1300 IfFailThrow(pDispenser->GetOption(MetaDataCheckDuplicatesFor, &opt));
1301 V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile;
1302 IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &opt));
1304 IfFailThrow(pDispenser->OpenScopeOnMemory((const void *)hostCopyStart, (DWORD)size,
1305 ofRead, IID_IMetaDataTables,
1306 (IUnknown **) &tables));
1307 DisplayStartArray( "Tables", W("%s"), ALWAYS );
1309 for( unsigned i = 0; i < _countof(s_tableTypes); ++i )
1313 hr = tables->GetTableIndex(s_tableTypes[i], &idx);
1314 _ASSERTE(SUCCEEDED(hr));
1315 ULONG cbRow = 0, cRows = 0, cCols = 0, iKey = 0;
1316 const char * name = NULL;
1318 hr = tables->GetTableInfo(idx, &cbRow, &cRows, &cCols,
1320 _ASSERTE(SUCCEEDED(hr) || hr == E_INVALIDARG);
1321 if( hr == E_INVALIDARG || cRows == 0 )
1323 continue; //no such table.
1326 hr = tables->GetRow(idx, 1, (void**)&ptr);
1328 _ASSERTE(SUCCEEDED(hr));
1330 rebasedPointer = data + (TO_TADDR(ptr) - hostCopyStart);
1331 _ASSERTE( rebasedPointer >= data && rebasedPointer < (data + size) );
1332 DisplayWriteElementAddressNamed( "table", name,
1333 DataPtrToDisplay(rebasedPointer),
1334 cbRow * cRows , ALWAYS );
1336 DisplayStartElement( "table", ALWAYS );
1337 DisplayWriteElementString( "name", name, ALWAYS );
1339 rebasedPointer = data + (TO_TADDR(ptr) - hostCopyStart);
1340 _ASSERTE( rebasedPointer >= data && rebasedPointer < (data + size) );
1341 DisplayWriteElementAddress( "address", DataPtrToDisplay(rebasedPointer),
1342 cbRow * cRows, ALWAYS );
1343 DisplayEndElement( ALWAYS ); //Table
1346 DisplayEndArray( "Total Tables", ALWAYS );
1348 PTR_STORAGESIGNATURE root(data);
1349 _ASSERTE(root->lSignature == STORAGE_MAGIC_SIG);
1350 //the root is followed by the version string who's length is
1351 //root->iVersionString. After that is a storage header that counts the
1352 //number of streams.
1353 PTR_STORAGEHEADER sHdr(data + sizeof(*root) + root->iVersionString);
1354 DisplayStartArray( "Pools", NULL, ALWAYS );
1356 //now check the pools
1358 //start of stream headers
1359 PTR_STORAGESTREAM streamHeader( PTR_TO_TADDR(sHdr) + sizeof(*sHdr) );
1360 for( unsigned i = 0; i < sHdr->iStreams; ++i )
1362 if( streamHeader->iSize > 0 )
1364 DisplayWriteElementAddressNamed( "heap", streamHeader->rcName,
1365 DataPtrToDisplay( data + streamHeader->iOffset ),
1366 streamHeader->iSize, ALWAYS );
1368 //Stream headers aren't fixed size. the size is aligned up based on a
1369 //variable length string at the end.
1370 streamHeader = PTR_STORAGESTREAM(PTR_TO_TADDR(streamHeader)
1371 + ALIGN_UP(offsetof(STORAGESTREAM, rcName) + strlen(streamHeader->rcName) + 1, 4));
1374 DisplayEndArray( "Total Pools", ALWAYS ); //Pools
1375 DisplayEndStructure( ALWAYS ); //nativeMetadata
1377 void NativeImageDumper::OpenMetadata()
1381 DACCOP_IGNORE(CastBetweenAddressSpaces,"nidump is in-proc and doesn't maintain a clean separation of address spaces (target and host are the same.");
1382 const void *data = reinterpret_cast<void*>(dac_cast<TADDR>(m_decoder.GetMetadata(&size)));
1384 ReleaseHolder<IMetaDataDispenserEx> pDispenser;
1385 IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
1386 IID_IMetaDataDispenserEx, (void **) &pDispenser));
1389 IfFailThrow(pDispenser->GetOption(MetaDataCheckDuplicatesFor, &opt));
1390 V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile;
1391 IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &opt));
1393 data = PTR_READ(TO_TADDR(data), size);
1394 IfFailThrow(pDispenser->OpenScopeOnMemory(data, size, ofRead,
1395 IID_IMetaDataImport2, (IUnknown **) &m_import));
1397 IfFailThrow(m_import->QueryInterface(IID_IMetaDataAssemblyImport,
1398 (void **)&m_assemblyImport));
1400 m_MetadataStartTarget = TO_TADDR(data);
1401 m_MetadataSize = size;
1402 data = PTR_READ(TO_TADDR(data), size);
1403 m_MetadataStartHost = TO_TADDR(data);
1405 if (m_decoder.HasNativeHeader())
1407 DACCOP_IGNORE(CastBetweenAddressSpaces,"nidump is in-proc and doesn't maintain a clean separation of address spaces (target and host are the same.");
1408 data = reinterpret_cast<void*>(dac_cast<TADDR>(m_decoder.GetNativeManifestMetadata(&size)));
1410 IfFailThrow(pDispenser->OpenScopeOnMemory(data, size, ofRead,
1411 IID_IMetaDataImport2, (IUnknown **) &m_manifestImport));
1413 IfFailThrow(m_manifestImport->QueryInterface(IID_IMetaDataAssemblyImport,
1414 (void **)&m_manifestAssemblyImport));
1418 m_manifestImport = m_import;
1419 m_manifestImport->AddRef();
1421 m_manifestAssemblyImport = m_assemblyImport;
1422 m_manifestAssemblyImport->AddRef();
1426 NativeImageDumper::AppendTokenName(mdToken token, SString& buf)
1428 AppendTokenName(token, buf, NULL);
1431 NativeImageDumper::AppendTokenName(mdToken token, SString& buf,
1432 IMetaDataImport2 *pImport,
1438 PCCOR_SIGNATURE pSig;
1439 PTR_CCOR_SIGNATURE dacSig;
1445 if( CHECK_OPT(DISABLE_NAMES) && !force )
1447 buf.Append( W("Disabled") );
1451 if (pImport == NULL)
1453 if( RidFromToken(token) == mdTokenNil )
1455 AppendNilToken( token, buf );
1459 switch (TypeFromToken(token))
1462 IfFailThrow(pImport->GetTypeDefProps(token, bigBuffer, bigBufferSize, &size, &flags, &parent));
1463 buf.Append(bigBuffer);
1467 // TritonTODO: consolidate with desktop
1468 // IfFailThrow(pImport->GetTypeRefProps(token, &parent, bigBuffer, bigBufferSize, &size));
1469 if (FAILED(pImport->GetTypeRefProps(token, &parent, bigBuffer, bigBufferSize, &size)))
1470 buf.Append(W("ADDED TYPEREF (?)"));
1472 buf.Append(bigBuffer);
1476 IfFailThrow(pImport->GetTypeSpecFromToken(token, &pSig, &cSig));
1477 dacSig = metadataToHostDAC(pSig, pImport);
1478 TypeToString(dacSig, buf, pImport);
1482 IfFailThrow(pImport->GetFieldProps(token, &parent, bigBuffer, bigBufferSize, &size, &attr,
1483 &pSig, &cSig, &flags, NULL, NULL));
1484 AppendTokenName(parent, buf, pImport);
1485 IfFailThrow(pImport->GetFieldProps(token, &parent, bigBuffer, bigBufferSize, &size, &attr,
1486 &pSig, &cSig, &flags, NULL, NULL));
1487 buf.AppendPrintf( W("::%s"), bigBuffer );
1491 IfFailThrow(pImport->GetMethodProps(token, &parent, bigBuffer, bigBufferSize, &size, &attr,
1492 &pSig, &cSig, &rva, &flags));
1493 AppendTokenName(parent, buf, pImport);
1494 IfFailThrow(pImport->GetMethodProps(token, &parent, bigBuffer, bigBufferSize, &size, &attr,
1495 &pSig, &cSig, &rva, &flags));
1496 buf.AppendPrintf( W("::%s"), bigBuffer );
1500 IfFailThrow(pImport->GetMemberRefProps(token, &parent, bigBuffer, bigBufferSize, &size,
1502 AppendTokenName(parent, buf, pImport);
1503 IfFailThrow(pImport->GetMemberRefProps(token, &parent, bigBuffer, bigBufferSize, &size,
1505 buf.AppendPrintf( W("::%s"), bigBuffer );
1509 IfFailThrow(pImport->GetSigFromToken(token, &pSig, &cSig));
1511 PrettyPrintSig(pSig, cSig, W(""), &bytes, pImport);
1512 m_display->ErrorPrintF("%S", bytes.Ptr());
1514 _ASSERTE(!"Unimplemented");
1515 m_display->ErrorPrintF( "unimplemented" );
1520 IfFailThrow(pImport->GetUserString(token, bigBuffer, bigBufferSize, &size));
1521 bigBuffer[min(size, bigBufferSize-1)] = 0;
1522 buf.Append( bigBuffer );
1526 case mdtAssemblyRef:
1528 case mdtExportedType:
1530 ReleaseHolder<IMetaDataAssemblyImport> pAssemblyImport;
1531 IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
1532 (void **)&pAssemblyImport));
1533 PrintManifestTokenName(token, buf, pAssemblyImport, force);
1537 case mdtGenericParam:
1540 IfFailThrow(pImport->GetGenericParamProps(token, NULL, NULL, NULL, NULL, bigBuffer,
1541 _countof(bigBuffer), &nameLen));
1542 bigBuffer[min(nameLen, _countof(bigBuffer) - 1)] = 0;
1543 buf.Append( bigBuffer );
1548 _ASSERTE( !"Unknown token type in AppendToken" );
1549 buf.AppendPrintf( W("token 0x%x"), token );
1553 void NativeImageDumper::PrintManifestTokenName(mdToken token, SString& str)
1555 PrintManifestTokenName(token, str, NULL);
1558 NativeImageDumper::PrintManifestTokenName(mdToken token,
1560 IMetaDataAssemblyImport *pAssemblyImport,
1570 if( CHECK_OPT(DISABLE_NAMES) && !force )
1572 buf.Append( W("Disabled") );
1576 if (pAssemblyImport == NULL)
1577 pAssemblyImport = m_manifestAssemblyImport;
1579 if( RidFromToken(token) == mdTokenNil )
1581 AppendNilToken( token, buf );
1585 switch (TypeFromToken(token))
1588 IfFailThrow(pAssemblyImport->GetAssemblyProps(token, &pSig, &cSig,
1590 bigBufferSize, &size,
1593 buf.Append(bigBuffer);
1596 case mdtAssemblyRef:
1597 IfFailThrow(pAssemblyImport->GetAssemblyRefProps(token, &pSig,
1602 buf.Append(bigBuffer);
1606 IfFailThrow(pAssemblyImport->GetFileProps(token, bigBuffer,
1607 bigBufferSize, &size,
1608 NULL, NULL, &flags));
1610 buf.Append(bigBuffer);
1613 case mdtExportedType:
1614 IfFailThrow(pAssemblyImport->GetExportedTypeProps(token, bigBuffer,
1615 bigBufferSize, &size,
1616 NULL, NULL, &flags));
1618 buf.Append(bigBuffer);
1622 buf.AppendPrintf(W("token %x"), token);
1627 BOOL NativeImageDumper::HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection,
1631 COUNT_T nImportSections;
1632 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1635 TADDR tableBase = m_decoder.GetDirectoryData(&pSection->Section, &tableSize);
1637 COUNT_T table = (COUNT_T)(pSection - pImportSections);
1638 _ASSERTE(table < nImportSections);
1640 SIZE_T offset = dac_cast<TADDR>(fixupCell) - tableBase;
1641 _ASSERTE( offset < tableSize );
1643 COUNT_T entry = (COUNT_T)(offset / sizeof(TADDR));
1644 m_fixupHistogram[table][entry]++;
1649 void NativeImageDumper::ComputeMethodFixupHistogram( PTR_Module module )
1651 COUNT_T nImportSections;
1652 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1654 m_fixupHistogram = new COUNT_T * [nImportSections];
1656 for (COUNT_T i=0; i < nImportSections; i++)
1658 PTR_CORCOMPILE_IMPORT_SECTION pSection = m_decoder.GetNativeImportSectionFromIndex(i);
1660 COUNT_T count = pSection->Section.Size / sizeof(TADDR);
1662 m_fixupHistogram[i] = new COUNT_T [count];
1663 ZeroMemory(m_fixupHistogram[i], count * sizeof(COUNT_T));
1666 ZeroMemory(&m_fixupCountHistogram, sizeof(m_fixupCountHistogram));
1667 // profiled hot code
1669 MethodIterator mi(module, &m_decoder, MethodIterator::Hot);
1674 TADDR pFixupList = mi.GetMethodDesc()->GetFixupList();
1676 if (pFixupList != NULL)
1678 COUNT_T nImportSections;
1679 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1681 module->FixupDelayListAux(pFixupList, this,
1682 &NativeImageDumper::HandleFixupForHistogram,
1683 pImportSections, nImportSections,
1687 if (m_fixupCount < COUNT_HISTOGRAM_SIZE)
1688 m_fixupCountHistogram[m_fixupCount]++;
1690 m_fixupCountHistogram[COUNT_HISTOGRAM_SIZE-1]++;
1694 MethodIterator miUnprofiled(module, &m_decoder, MethodIterator::Unprofiled);
1696 while(miUnprofiled.Next())
1700 TADDR pFixupList = miUnprofiled.GetMethodDesc()->GetFixupList();
1702 if (pFixupList != NULL)
1704 COUNT_T nImportSections;
1705 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1707 module->FixupDelayListAux(pFixupList, this,
1708 &NativeImageDumper::HandleFixupForHistogram,
1709 pImportSections, nImportSections,
1713 if (m_fixupCount < COUNT_HISTOGRAM_SIZE)
1714 m_fixupCountHistogram[m_fixupCount]++;
1716 m_fixupCountHistogram[COUNT_HISTOGRAM_SIZE-1]++;
1720 void NativeImageDumper::DumpFixupTables( PTR_Module module )
1722 IF_OPT(FIXUP_HISTOGRAM)
1723 ComputeMethodFixupHistogram( module );
1725 DisplayStartCategory( "Imports", FIXUP_TABLES );
1727 COUNT_T nImportSections;
1728 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1730 for (COUNT_T iImportSections = 0; iImportSections < nImportSections; iImportSections++)
1732 PTR_CORCOMPILE_IMPORT_SECTION pImportSection = pImportSections + iImportSections;
1735 TADDR pTable(m_decoder.GetDirectoryData(&pImportSection->Section, &size));
1736 TADDR pTableEnd = pTable + size;
1738 TADDR pDataTable(NULL);
1740 if (pImportSection->Signatures != 0)
1741 pDataTable = m_decoder.GetRvaData(pImportSection->Signatures);
1743 switch (pImportSection->Type)
1745 case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
1747 COUNT_T entrySize = pImportSection->EntrySize;
1748 COUNT_T count = size / entrySize;
1749 _ASSERTE(entrySize == sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK));
1751 for (TADDR pEntry = pTable; pEntry < pTableEnd; pEntry += entrySize)
1753 PTR_CORCOMPILE_VIRTUAL_IMPORT_THUNK pThunk = pEntry;
1755 DisplayStartStructure("VirtualImportThunk", DPtrToPreferredAddr(pThunk),
1756 entrySize, FIXUP_THUNKS );
1758 DisplayWriteElementInt( "Slot", pThunk->slotNum, FIXUP_THUNKS);
1760 DisplayEndStructure( FIXUP_THUNKS );
1765 case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
1767 COUNT_T entrySize = pImportSection->EntrySize;
1768 COUNT_T count = size / entrySize;
1769 _ASSERTE(entrySize == sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK));
1771 for (TADDR pEntry = pTable; pEntry < pTableEnd; pEntry += entrySize)
1773 PTR_CORCOMPILE_EXTERNAL_METHOD_THUNK pThunk = pEntry;
1775 DisplayStartStructure("ExternalImportThunk", DPtrToPreferredAddr(pThunk),
1776 entrySize, FIXUP_THUNKS );
1778 TADDR pDataAddr = pDataTable + ((pEntry - pTable) / entrySize) * sizeof(DWORD);
1779 PTR_DWORD pData = pDataAddr;
1781 DisplayWriteElementPointer( "DataAddress ", pDataAddr, FIXUP_THUNKS );
1783 TADDR blobSigAddr = RvaToDisplay(*pData);
1784 DisplayWriteElementPointer( "TargetSigAddress", blobSigAddr, FIXUP_THUNKS );
1786 FixupBlobToString(*pData, buf);
1787 DisplayWriteElementStringW( "TargetName", (const WCHAR*)buf, FIXUP_THUNKS );
1789 DisplayEndStructure( FIXUP_THUNKS );
1796 COUNT_T count = size / sizeof(TADDR);
1798 for (COUNT_T j = 0; j < count; j++)
1800 if (dac_cast<PTR_TADDR>(pTable)[j] == 0)
1803 SIZE_T nNextEntry = j + 1;
1804 while (nNextEntry < count && dac_cast<PTR_TADDR>(pTable)[nNextEntry] == 0)
1807 DisplayStartStructure("ImportEntry", DPtrToPreferredAddr(dac_cast<PTR_TADDR>(pTable) + j),
1808 (nNextEntry - j) * sizeof(TADDR), FIXUP_TABLES );
1810 if (pDataTable != NULL)
1812 DWORD rva = dac_cast<PTR_DWORD>(pDataTable)[j];
1813 WriteElementsFixupTargetAndName(rva);
1817 SIZE_T token = dac_cast<PTR_TADDR>(pTable)[j];
1818 DisplayWriteElementPointer( "TaggedValue", token, FIXUP_TABLES );
1819 WriteElementsFixupBlob(pImportSection, token);
1822 DisplayWriteElementInt( "index", j, FIXUP_HISTOGRAM);
1823 DisplayWriteElementInt( "ReferenceCount", m_fixupHistogram[iImportSections][j], FIXUP_HISTOGRAM );
1825 DisplayEndStructure( FIXUP_TABLES );
1830 DisplayEndCategory( FIXUP_TABLES );
1833 void NativeImageDumper::FixupThunkToString(PTR_CORCOMPILE_IMPORT_SECTION pImportSection, TADDR addr, SString& buf)
1835 switch (pImportSection->Type)
1837 case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
1839 PTR_CORCOMPILE_VIRTUAL_IMPORT_THUNK pThunk = addr;
1840 buf.AppendPrintf( W("slot %d"), pThunk->slotNum );
1844 case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
1845 case CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH:
1847 TADDR pTable(m_decoder.GetDirectoryData(&pImportSection->Section));
1848 COUNT_T index = (COUNT_T)(addr - pTable) / pImportSection->EntrySize;
1849 TADDR pDataTable(m_decoder.GetRvaData(pImportSection->Signatures));
1850 TADDR pDataAddr = pDataTable + (index * sizeof(DWORD));
1851 PTR_DWORD pData = pDataAddr;
1852 FixupBlobToString(*pData, buf);
1857 _ASSERTE(!"Unknown import type");
1861 void NativeImageDumper::WriteElementsFixupBlob(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixup)
1863 if (pSection != NULL && !CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
1866 if (pSection->Type == CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE)
1868 TypeHandleToString(TypeHandle::FromTAddr((TADDR)fixup), buf);
1871 if (pSection->Type == CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE)
1873 MethodDescToString(PTR_MethodDesc((TADDR)fixup), buf);
1877 _ASSERTE(!"Unknown Type");
1878 IfFailThrow(E_FAIL);
1880 m_display->WriteElementStringW( "FixupTargetName", (const WCHAR*)buf );
1884 RVA rva = CORCOMPILE_UNTAG_TOKEN(fixup);
1886 WriteElementsFixupTargetAndName(rva);
1889 const NativeImageDumper::EnumMnemonics s_EncodeMethodSigFlags[] =
1891 #define EMS_ENTRY(f) NativeImageDumper::EnumMnemonics(ENCODE_METHOD_SIG_ ## f, W(#f))
1892 EMS_ENTRY(UnboxingStub),
1893 EMS_ENTRY(InstantiatingStub),
1894 EMS_ENTRY(MethodInstantiation),
1895 EMS_ENTRY(SlotInsteadOfToken),
1896 EMS_ENTRY(MemberRefToken),
1897 EMS_ENTRY(Constrained),
1898 EMS_ENTRY(OwnerType),
1902 void NativeImageDumper::FixupBlobToString(RVA rva, SString& buf)
1904 PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
1907 CorTokenType tkType = (CorTokenType)0;
1909 IMetaDataImport2 * pImport = m_import;
1911 if (kind & ENCODE_MODULE_OVERRIDE)
1913 Import *import = OpenImport(DacSigUncompressData(sig));
1914 kind &= ~ENCODE_MODULE_OVERRIDE;
1916 Dependency *pDep = import->dependency;
1922 pImport = pDep->pImport;
1924 _ASSERTE(pImport != NULL);
1926 // print assembly/module info
1929 MapAssemblyRefToManifest(TokenFromRid(import->index,
1932 AppendToken(realRef, buf, m_manifestImport);
1933 buf.Append( W(" ") );
1936 // print further info
1942 case ENCODE_MODULE_HANDLE:
1946 case ENCODE_TYPE_HANDLE:
1948 if (pImport != NULL)
1949 TypeToString(sig, buf, pImport);
1951 buf.Append( W("<unresolved type> ") );
1955 case ENCODE_METHOD_HANDLE:
1959 DWORD methodFlags = DacSigUncompressData(sig);
1961 // If the type portion for this generic method signature
1962 // is from a different module then both the generic type and the
1963 // generic method tokens are interpreted in the context of that module,
1964 // and not the current import. This is returned by TypeToString.
1966 IMetaDataImport2 * pMethodImport = pImport;
1967 if (pImport != NULL)
1969 if (methodFlags & ENCODE_METHOD_SIG_OwnerType)
1971 pMethodImport = TypeToString(sig, buf, pImport);
1976 buf.Append( W("<unresolved method signature>") );
1980 //If we have SlotInsteadOfToken set then this is a slot number (i.e. for an array)
1981 if( methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken )
1983 buf.AppendPrintf( W(" method slot %d"), DacSigUncompressData(sig) );
1987 // decode the methodToken (a rid is encoded)
1988 RID rid = DacSigUncompressData(sig);
1990 mdMethodDef methodToken = ((methodFlags & ENCODE_METHOD_SIG_MemberRefToken) ? mdtMemberRef : mdtMethodDef) | rid;
1992 buf.Append( W(" ") );
1994 // Get the full signature of method from external module
1995 // Need temporary buffer because method name will be inserted
1996 // in between the signature
1998 TempBuffer tempName;
2000 AppendTokenName( methodToken, tempName, pMethodImport );
2002 if( methodFlags & ENCODE_METHOD_SIG_MethodInstantiation )
2004 //for each generic arg, there is a type handle.
2005 ULONG numParams = DacSigUncompressData(sig);
2007 tempName.Append( W("<") );
2008 for( unsigned i = 0;i < numParams; ++i )
2011 tempName.Append( W(", ") );
2013 // switch back to using pImport to resolve tokens
2014 TypeToString(sig, tempName, pImport);
2016 tempName.Append( W(">") );
2019 PCCOR_SIGNATURE pvSigBlob;
2022 if (methodFlags & ENCODE_METHOD_SIG_MemberRefToken)
2024 IfFailThrow(pMethodImport->GetMemberRefProps(methodToken,
2034 IfFailThrow(pMethodImport->GetMethodProps(methodToken,
2046 CQuickBytes prettySig;
2047 ReleaseHolder<IMDInternalImport> pInternal;
2048 IfFailThrow(GetMDInternalInterfaceFromPublic(pMethodImport, IID_IMDInternalImport,
2049 (void**)&pInternal));
2050 StackScratchBuffer buffer;
2051 const ANSI * ansi = tempName.GetANSI(buffer);
2052 ansi = PrettyPrintSig(pvSigBlob, cbSigBlob, ansi, &prettySig, pInternal, NULL);
2053 tempName.SetANSI( ansi );
2054 buf.Append(tempName);
2057 buf.Append( W(" flags=(") );
2058 EnumFlagsToString( methodFlags, s_EncodeMethodSigFlags, _countof(s_EncodeMethodSigFlags),
2060 buf.Append( W(")") );
2064 case ENCODE_FIELD_HANDLE:
2068 DWORD fieldFlags = DacSigUncompressData(sig);
2070 IMetaDataImport2 * pFieldImport = pImport;
2071 if (pImport != NULL)
2073 if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
2075 pFieldImport = TypeToString(sig, buf, pImport);
2079 buf.Append( W("<unresolved type>") );
2081 if (fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken)
2083 buf.AppendPrintf( W(" field index %d"), DacSigUncompressData(sig) );
2087 // decode the methodToken (a rid is encoded)
2088 RID rid = DacSigUncompressData(sig);
2090 mdMethodDef fieldToken = ((fieldFlags & ENCODE_FIELD_SIG_MemberRefToken) ? mdtMemberRef : mdtFieldDef) | rid;
2092 buf.Append( W(" ") );
2094 AppendTokenName( fieldToken, buf, pFieldImport );
2099 case ENCODE_STRING_HANDLE:
2100 token = TokenFromRid(DacSigUncompressData(sig), mdtString);
2101 if (pImport != NULL)
2102 AppendToken(token, buf, pImport);
2104 buf.AppendPrintf( W("<unresolved token %d>"), token );
2107 case ENCODE_VARARGS_SIG:
2108 tkType = mdtFieldDef;
2109 goto DataToTokenCore;
2110 case ENCODE_VARARGS_METHODREF:
2111 tkType = mdtMemberRef;
2112 goto DataToTokenCore;
2113 case ENCODE_VARARGS_METHODDEF:
2114 tkType = mdtMemberRef;
2115 goto DataToTokenCore;
2117 token = TokenFromRid(DacSigUncompressData(sig), tkType);
2118 if (pImport != NULL)
2119 AppendToken(token, buf, pImport);
2121 buf.AppendPrintf( "<unresolved token %d>", token );
2124 case ENCODE_METHOD_ENTRY:
2125 buf.Append( W("Entrypoint for ") );
2128 case ENCODE_METHOD_ENTRY_DEF_TOKEN:
2130 buf.Append( W("Entrypoint for ") );
2131 token = TokenFromRid(DacSigUncompressData(sig), mdtMethodDef);
2132 AppendTokenName(token, buf, pImport);
2136 case ENCODE_METHOD_ENTRY_REF_TOKEN:
2138 buf.Append( W("Entrypoint for ref ") );
2139 token = TokenFromRid(DacSigUncompressData(sig), mdtMemberRef);
2140 AppendTokenName(token, buf, pImport);
2144 case ENCODE_VIRTUAL_ENTRY:
2145 buf.Append( W("Entrypoint for ") );
2148 case ENCODE_VIRTUAL_ENTRY_DEF_TOKEN:
2150 buf.Append( W("Virtual call for ") );
2151 token = TokenFromRid(DacSigUncompressData(sig), mdtMethodDef);
2152 AppendTokenName(token, buf, pImport);
2156 case ENCODE_VIRTUAL_ENTRY_REF_TOKEN:
2158 buf.Append( W("Virtual call for ref ") );
2159 token = TokenFromRid(DacSigUncompressData(sig), mdtMemberRef);
2160 AppendTokenName(token, buf, pImport);
2164 case ENCODE_VIRTUAL_ENTRY_SLOT:
2166 buf.Append( W("Virtual call for ") );
2167 int slot = DacSigUncompressData(sig);
2168 buf.AppendPrintf( W("slot %d "), slot );
2172 case ENCODE_MODULE_ID_FOR_STATICS:
2173 buf.Append( W("Module For Statics") );
2177 case ENCODE_MODULE_ID_FOR_GENERIC_STATICS:
2178 buf.Append( W("Module For Statics for ") );
2181 case ENCODE_CLASS_ID_FOR_STATICS:
2182 buf.Append( W("Statics ID for ") );
2185 case ENCODE_STATIC_FIELD_ADDRESS:
2186 buf.Append( W("Static field address for ") );
2189 case ENCODE_SYNC_LOCK:
2190 buf.Append( W("Synchronization handle for ") );
2193 case ENCODE_INDIRECT_PINVOKE_TARGET:
2194 buf.Append( W("Indirect P/Invoke target for ") );
2197 case ENCODE_PROFILING_HANDLE:
2198 buf.Append( W("Profiling handle for ") );
2201 case ENCODE_ACTIVE_DEPENDENCY:
2203 buf.Append( W("Active dependency for ") );
2205 int targetModuleIndex = DacSigUncompressData(sig);
2206 Import *targetImport = OpenImport(targetModuleIndex);
2209 MapAssemblyRefToManifest(TokenFromRid(targetImport->index,
2212 AppendToken(realRef, buf, m_manifestImport);
2213 buf.Append( W(" ") );
2218 buf.Append( W("Unknown fixup kind") );
2219 _ASSERTE(!"Unknown fixup kind");
2223 void NativeImageDumper::WriteElementsFixupTargetAndName(RVA rva)
2227 /* XXX Tue 04/11/2006
2228 * This should only happen for static fields. If the field is
2229 * unaligned, we need an extra cell for an indirection.
2231 m_display->WriteElementPointer( "FixupTargetValue", NULL );
2232 m_display->WriteElementStringW( "FixupTargetName", W("NULL") );
2236 m_display->WriteElementPointer( "FixupTargetValue", RvaToDisplay(rva) );
2239 FixupBlobToString(rva, buf);
2241 m_display->WriteElementStringW( "FixupTargetName", (const WCHAR*)buf );
2244 NativeImageDumper::Dependency * NativeImageDumper::GetDependency(mdAssemblyRef token, IMetaDataAssemblyImport *pImport)
2246 if (RidFromToken(token) == 0)
2247 return OpenDependency(0);
2249 if (pImport == NULL)
2250 pImport = m_assemblyImport;
2252 // Need to map from IL token to manifest token
2253 mdAssemblyRef manifestToken = MapAssemblyRefToManifest(token, pImport);
2255 if( manifestToken == mdAssemblyNil )
2258 return OpenDependency(0);
2262 PTR_CORCOMPILE_DEPENDENCY deps(TO_TADDR(m_decoder.GetNativeDependencies(&count)));
2264 for (COUNT_T i = 0; i < count; i++)
2266 if (deps[i].dwAssemblyRef == manifestToken)
2267 return OpenDependency(i+1);
2271 AppendTokenName(manifestToken, buf, m_manifestImport);
2272 m_display->ErrorPrintF("Error: unlisted assembly dependency %S\n", (const WCHAR*)buf);
2277 mdAssemblyRef NativeImageDumper::MapAssemblyRefToManifest(mdAssemblyRef token, IMetaDataAssemblyImport *pAssemblyImport)
2279 // Reference may be to self
2280 if (TypeFromToken(token) == mdtAssembly)
2283 // Additional tokens not originally present overflow to manifest automatically during emit
2284 /* REVISIT_TODO Tue 01/31/2006
2285 * Factor this code out so that it is shared with the module index code in the CLR that looks
2288 //count the assembly refs.
2291 HCORENUM iter = NULL;
2296 IfFailThrow(pAssemblyImport->EnumAssemblyRefs(&iter, &tmp, 1,
2302 pAssemblyImport->CloseEnum(iter);
2304 if( RidFromToken(token) > count )
2306 //out of range import. This means that it has spilled over. Subtract
2307 //off the max number of assembly refs and return it as a manifest
2309 return token - (count + 1);
2313 ASSEMBLYMETADATA metadata;
2315 ZeroMemory(&metadata, sizeof(metadata));
2317 IfFailThrow(pAssemblyImport->GetAssemblyRefProps(token, NULL, NULL,
2319 &metadata, NULL, NULL,
2322 LPWSTR szAssemblyName = NULL;
2325 szAssemblyName = (LPWSTR) _alloca(cchName * sizeof(WCHAR));
2327 if (metadata.cbLocale > 0)
2328 metadata.szLocale = (LPWSTR) _alloca(metadata.cbLocale * sizeof(WCHAR));
2329 if (metadata.ulProcessor > 0)
2330 metadata.rProcessor = (DWORD*) _alloca(metadata.ulProcessor * sizeof(DWORD));
2331 if (metadata.ulOS > 0)
2332 metadata.rOS = (OSINFO*) _alloca(metadata.ulOS * sizeof(OSINFO));
2334 const void *pbPublicKey;
2337 const void *pbHashValue;
2341 IfFailThrow(pAssemblyImport->GetAssemblyRefProps(token, &pbPublicKey, &cbPublicKey,
2342 szAssemblyName, cchName, NULL,
2343 &metadata, &pbHashValue, &cbHashValue,
2346 //Notice that we're searching for the provided metadata for the dependency info and then looking in the
2347 //image we're dumping for the dependency.
2349 //Also, sometimes we find "self" in these searches. If so, return mdAssemblyDefNil as a canary value.
2351 if( !wcscmp(szAssemblyName, m_name) )
2354 return mdAssemblyNil;
2357 mdAssemblyRef ret = mdAssemblyRefNil;
2358 /*HCORENUM*/ iter = NULL;
2361 //Walk through all the assemblyRefs and search for a match. I would use DefineAssemblyRef here, but
2362 //if I do it will create an assemblyRef is one is not found. Then I fail in a bad place. This
2363 //way I can fail in a less bad place.
2364 mdAssemblyRef currentRef;
2366 IfFailThrow(m_manifestAssemblyImport->EnumAssemblyRefs(&iter, ¤tRef, 1, &count));
2370 //get the information about the assembly ref and compare.
2371 const void * publicKeyToken;
2374 /*ULONG*/ cchName = _countof(name);
2375 ASSEMBLYMETADATA curMD = {0};
2377 IfFailThrow(m_manifestAssemblyImport->GetAssemblyRefProps(currentRef, &publicKeyToken, &pktSize, name,
2378 cchName, &cchName, &curMD,
2379 NULL /*ppbHashValue*/, NULL/*pcbHashValue*/,
2380 NULL/*pdwAssemblyRefFlags*/));
2381 if( !wcscmp(name, szAssemblyName) )
2383 if( cbPublicKey == pktSize && !memcmp(pbPublicKey, publicKeyToken, pktSize)
2384 && curMD.usMajorVersion == metadata.usMajorVersion
2385 && curMD.usMinorVersion == metadata.usMinorVersion)
2390 else if (wcscmp(szAssemblyName, CoreLibName_W) == 0)
2392 // Mscorlib is special - version number and public key token are ignored.
2396 else if (metadata.usMajorVersion == 255 &&
2397 metadata.usMinorVersion == 255 &&
2398 metadata.usBuildNumber == 255 &&
2399 metadata.usRevisionNumber == 255)
2401 // WinMDs encode all assemblyrefs with version 255.255.255.255 including CLR assembly dependencies (mscorlib, System).
2406 //there was an assembly with the correct name, but with the wrong version number. Let the
2408 m_display->ErrorPrintF("MapAssemblyRefToManifest: found %S with version %d.%d in manifest. Wanted version %d.%d.\n", szAssemblyName, curMD.usMajorVersion, curMD.usMinorVersion, metadata.usMajorVersion, metadata.usMinorVersion);
2416 pAssemblyImport->CloseEnum(iter);
2417 if( ret == mdAssemblyRefNil )
2420 appendByteArray(pkt, (const BYTE*)pbPublicKey, cbPublicKey);
2421 m_display->ErrorPrintF("MapAssemblyRefToManifest could not find token for %S, Version=%d.%d, PublicKeyToken=%S\n", szAssemblyName, metadata.usMajorVersion, metadata.usMinorVersion, (const WCHAR *)pkt);
2422 _ASSERTE(!"MapAssemblyRefToManifest failed to find a match");
2428 NativeImageDumper::Import * NativeImageDumper::OpenImport(int i)
2430 if (m_imports == NULL)
2433 m_decoder.GetNativeDependencies(&count);
2434 m_numImports = count;
2435 m_imports = new Import [count];
2436 ZeroMemory(m_imports, count * sizeof(m_imports[0]));
2439 if (m_imports[i].index == 0)
2441 //GetNativeImportFromIndex returns a host pointer.
2442 m_imports[i].index = i;
2445 mdToken tok = TokenFromRid(entry->index, mdtAssemblyRef);
2446 Dependency * dependency = GetDependency( MapAssemblyRefToManifest(tok,
2448 Dependency *dependency = GetDependency(TokenFromRid(i, mdtAssemblyRef));
2449 m_imports[i].dependency = dependency;
2450 _ASSERTE(dependency); //Why can this be null?
2454 return &m_imports[i];
2458 const NativeImageDumper::Dependency *NativeImageDumper::GetDependencyForFixup(RVA rva)
2460 PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
2461 if (*sig++ & ENCODE_MODULE_OVERRIDE)
2463 unsigned idx = DacSigUncompressData(sig);
2465 _ASSERTE(idx >= 0 && idx < m_numImports);
2466 return OpenImport(idx)->dependency;
2469 return &m_dependencies[0];
2473 void NativeImageDumper::AppendToken(mdToken token, SString& buf)
2475 return NativeImageDumper::AppendToken(token, buf, NULL);
2477 void NativeImageDumper::AppendToken(mdToken token, SString& buf,
2478 IMetaDataImport2 *pImport)
2480 IF_OPT(DISABLE_NAMES)
2482 buf.Append( W("Disabled") );
2485 switch (TypeFromToken(token))
2488 buf.Append( W("TypeDef ") );
2492 buf.Append( W("TypeRef ") );
2496 buf.Append( W("TypeRef ") );
2500 buf.Append( W("FieldDef "));
2504 buf.Append( W("MethodDef ") );
2508 buf.Append( W("MemberRef ") );
2511 case mdtAssemblyRef:
2512 buf.Append( W("AssemblyRef ") );
2516 buf.Append( W("File ") );
2520 buf.Append( W("String ") );
2524 buf.Append( W("Signature ") );
2528 if( RidFromToken(token) == mdTokenNil )
2529 buf.Append( W("Nil") );
2531 AppendTokenName(token, buf, pImport);
2534 NativeImageDumper::Dependency *NativeImageDumper::OpenDependency(int index)
2536 CORCOMPILE_VERSION_INFO *info = m_decoder.GetNativeVersionInfo();
2538 if (m_dependencies == NULL)
2541 m_decoder.GetNativeDependencies(&count);
2546 m_numDependencies = count;
2547 m_dependencies = new Dependency [count];
2548 ZeroMemory(m_dependencies, count * sizeof (Dependency));
2551 if (m_dependencies[index].entry == NULL)
2553 CORCOMPILE_DEPENDENCY *entry;
2557 // Make dummy entry for self
2559 m_self.dwAssemblyRef = TokenFromRid(1, mdtAssembly);
2560 m_self.dwAssemblyDef = TokenFromRid(1, mdtAssembly);
2561 m_self.signAssemblyDef = info->sourceAssembly;
2562 m_manifestImport->GetScopeProps(NULL, NULL, 0, &m_self.signNativeImage);
2563 m_dependencies[index].pLoadedAddress = dac_cast<TADDR>(m_baseAddress);
2564 m_dependencies[index].pPreferredBase =
2565 TO_TADDR(m_decoder.GetNativePreferredBase());
2566 m_dependencies[index].size = m_imageSize;
2567 m_dependencies[index].pImport = m_import;
2568 m_dependencies[index].pMetadataStartTarget =
2569 m_MetadataStartTarget;
2570 m_dependencies[index].pMetadataStartHost =
2571 m_MetadataStartHost;
2572 m_dependencies[index].MetadataSize = m_MetadataSize;
2573 m_dependencies[index].pModule =
2574 (TADDR)m_decoder.GetPersistedModuleImage();
2575 m_dependencies[index].fIsHardbound = TRUE;
2576 _ASSERTE( (m_dependencies[index].pModule
2577 > m_dependencies[index].pLoadedAddress)
2578 && (m_dependencies[index].pModule
2579 < m_dependencies[index].pLoadedAddress
2580 + m_dependencies[index].size) );
2581 // patch the Module vtable so that the DAC is able to instantiate it
2582 TADDR vtbl = DacGetTargetVtForHostVt(Module::VPtrHostVTable(), true);
2583 DacWriteAll( m_dependencies[index].pModule.GetAddr(), &vtbl, sizeof(vtbl), false );
2588 PTR_CORCOMPILE_DEPENDENCY deps(TO_TADDR(m_decoder.GetNativeDependencies(&numDeps)));
2590 entry = deps + (index-1);
2592 //load the dependency, get the pointer, and use the PEDecoder
2593 //to open the metadata.
2597 /* REVISIT_TODO Tue 11/22/2005
2598 * Is this the right name?
2600 Dependency& dependency = m_dependencies[index];
2601 AppendTokenName(entry->dwAssemblyRef, buf, m_manifestImport, true);
2602 bool isHardBound = !!(entry->signNativeImage != INVALID_NGEN_SIGNATURE);
2603 SString mscorlibStr(SString::Literal, CoreLibName_W);
2604 bool isMscorlib = (0 == buf.Compare( mscorlibStr ));
2605 dependency.fIsHardbound = isHardBound;
2606 wcscpy_s(dependency.name, _countof(dependency.name),
2610 IfFailThrow(m_librarySupport->LoadHardboundDependency((const WCHAR*)buf,
2611 entry->signNativeImage, &loadedBase));
2613 dependency.pLoadedAddress = loadedBase;
2617 ASSEMBLYMETADATA asmData = {0};
2618 const void * hashValue;
2619 ULONG hashLength, size, flags;
2620 IfFailThrow(m_manifestAssemblyImport->GetAssemblyRefProps(entry->dwAssemblyRef, &hashValue, &hashLength, bigBuffer, bigBufferSize, &size, &asmData, NULL, NULL, &flags));
2624 m_librarySupport->LoadSoftboundDependency((const WCHAR*)buf,
2625 (const BYTE*)&asmData, (const BYTE*)hashValue, hashLength,
2630 if( hashLength > 0 )
2632 appendByteArray(pkt, (BYTE*)hashValue, hashLength);
2636 pkt.Set( W("<No Hash>") );
2638 //try to continue without loading this softbound
2640 m_display->ErrorPrintF( "WARNING Failed to load softbound dependency:\n\t%S,Version=%d.%d.0.0,PublicKeyToken=%S.\n\tAttempting to continue. May crash later in due to missing metadata\n",
2641 (const WCHAR *)buf, asmData.usMajorVersion,
2642 asmData.usMinorVersion, (const WCHAR *)pkt );
2643 m_dependencies[index].entry = entry;
2644 return &m_dependencies[index];
2647 //save this off to the side so OpenImport can find the metadata.
2648 m_dependencies[index].pLoadedAddress = loadedBase;
2650 /* REVISIT_TODO Wed 11/23/2005
2651 * Refactor this with OpenMetadata from above.
2653 //now load the metadata from the new image.
2654 PEDecoder decoder(dac_cast<PTR_VOID>(loadedBase));
2657 dependency.pPreferredBase =
2658 TO_TADDR(decoder.GetNativePreferredBase());
2659 dependency.size = decoder.Has32BitNTHeaders() ?
2660 decoder.GetNTHeaders32()->OptionalHeader.SizeOfImage :
2661 decoder.GetNTHeaders64()->OptionalHeader.SizeOfImage;
2663 ReleaseHolder<IMetaDataDispenserEx> pDispenser;
2664 IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
2665 IID_IMetaDataDispenserEx,
2666 (void **) &pDispenser));
2669 IfFailThrow(pDispenser->GetOption(MetaDataCheckDuplicatesFor,
2671 V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile;
2672 IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor,
2674 if( decoder.HasNativeHeader() )
2676 dependency.pModule =
2677 TO_TADDR(decoder.GetPersistedModuleImage());
2678 _ASSERTE( (PTR_TO_TADDR(dependency.pModule) > loadedBase)
2679 && (PTR_TO_TADDR(dependency.pModule) < loadedBase +
2680 decoder.GetSize()) );
2681 // patch the Module vtable so that the DAC is able to instantiate it
2682 TADDR vtbl = DacGetTargetVtForHostVt(Module::VPtrHostVTable(), true);
2683 DacWriteAll( m_dependencies[index].pModule.GetAddr(), &vtbl, sizeof(vtbl), false );
2687 dependency.pModule = NULL;
2693 DACCOP_IGNORE(CastBetweenAddressSpaces,"nidump is in-proc and doesn't maintain a clean separation of address spaces (target and host are the same.");
2694 data = reinterpret_cast<void*>(dac_cast<TADDR>(decoder.GetMetadata(&size)));
2696 dependency.pMetadataStartTarget = TO_TADDR(data);
2697 dependency.MetadataSize = size;
2698 data = PTR_READ(TO_TADDR(data), size);
2699 dependency.pMetadataStartHost = TO_TADDR(data);
2700 IfFailThrow(pDispenser->OpenScopeOnMemory(data, size,
2702 IID_IMetaDataImport2,
2703 (IUnknown **) &dependency.pImport));
2704 dependency.fIsMscorlib = isMscorlib;
2707 m_dependencies[index].entry = entry;
2711 return &m_dependencies[index];
2714 IMetaDataImport2* NativeImageDumper::TypeToString(PTR_CCOR_SIGNATURE &sig, SString& buf)
2716 return TypeToString(sig, buf, NULL);
2719 void NativeImageDumper::TypeToString(PTR_CCOR_SIGNATURE &sig,
2720 IMetaDataImport2 *pImport)
2724 if (pImport == NULL)
2727 LPCWSTR type = PrettyPrintSig( sig, INT_MAX, W(""), &tmp, pImport );
2729 m_display->ErrorPrintF( "%S", type );
2733 IMetaDataImport2 * NativeImageDumper::TypeToString(PTR_CCOR_SIGNATURE &sig,
2735 IMetaDataImport2 *pImport,
2736 IMetaDataImport2 *pOrigImport /* =NULL */)
2739 IF_OPT(DISABLE_NAMES)
2741 buf.Append( W("Disabled") );
2745 if (pImport == NULL)
2747 if (pOrigImport == NULL)
2748 pOrigImport = pImport;
2750 IMetaDataImport2 * pRet = pImport;
2751 #define TYPEINFO(enumName, classSpace, className, size, gcType, isArray, isPrim, isFloat, isModifier, isGenVar) \
2753 static const char *elementNames[] = {
2754 #include "cortypeinfo.h"
2758 CorElementType type = DacSigUncompressElementType(sig);
2760 if (type == (CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG)
2762 unsigned idx = DacSigUncompressData(sig);
2763 buf.AppendPrintf( W("module %d "), idx );
2765 const Import * import = OpenImport(idx);
2766 pImport = import->dependency->pImport;
2768 //if there was a module switch, return the import for the new module.
2769 //This is useful for singatures, where the module index applies to
2770 //subsequent tokens.
2773 type = DacSigUncompressElementType(sig);
2775 if (type >= 0 && (size_t)type < _countof(elementNames)
2776 && elementNames[type] != NULL)
2778 buf.AppendPrintf( "%s", elementNames[type] );
2780 else switch ((DWORD)type)
2782 case ELEMENT_TYPE_CANON_ZAPSIG:
2783 buf.Append( W("System.__Canon") );
2786 case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
2787 case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
2789 buf.Append( W("native ") );
2790 TypeToString(sig, buf, pImport);
2794 case ELEMENT_TYPE_VALUETYPE:
2795 case ELEMENT_TYPE_CLASS:
2797 if (type == ELEMENT_TYPE_VALUETYPE)
2798 buf.Append( W("struct ") );
2800 mdToken token = DacSigUncompressToken(sig);
2801 AppendTokenName(token, buf, pImport);
2805 case ELEMENT_TYPE_SZARRAY:
2806 TypeToString(sig, buf, pImport);
2807 buf.Append( W("[]") );
2810 case ELEMENT_TYPE_ARRAY:
2812 TypeToString(sig, buf, pImport, pOrigImport);
2813 unsigned rank = DacSigUncompressData(sig);
2815 buf.Append( W("[??]") );
2818 size_t cbLowerBounds;
2819 if (!ClrSafeInt<size_t>::multiply(rank, 2*sizeof(int), cbLowerBounds/* passed by ref */))
2820 ThrowHR(COR_E_OVERFLOW);
2821 int* lowerBounds = (int*) _alloca(cbLowerBounds);
2822 int* sizes = &lowerBounds[rank];
2823 memset(lowerBounds, 0, sizeof(int)*2*rank);
2825 unsigned numSizes = DacSigUncompressData(sig);
2826 _ASSERTE(numSizes <= rank);
2828 for(i =0; i < numSizes; i++)
2829 sizes[i] = DacSigUncompressData(sig);
2831 unsigned numLowBounds = DacSigUncompressData(sig);
2832 _ASSERTE(numLowBounds <= rank);
2833 for(i = 0; i < numLowBounds; i++)
2834 lowerBounds[i] = DacSigUncompressData(sig);
2837 for(i = 0; i < rank; i++)
2839 if (sizes[i] != 0 && lowerBounds[i] != 0)
2841 if (lowerBounds[i] == 0)
2842 buf.AppendPrintf( W("%s"), sizes[i] );
2845 buf.AppendPrintf( W("%d ..."), lowerBounds[i] );
2847 buf.AppendPrintf( W("%d"),
2848 lowerBounds[i] + sizes[i]
2853 buf.Append( W(",") );
2855 buf.Append( W("]") );
2860 case ELEMENT_TYPE_MVAR:
2861 buf.Append( W("!") );
2863 case ELEMENT_TYPE_VAR:
2864 buf.AppendPrintf( W("!%d"), DacSigUncompressData(sig));
2867 case ELEMENT_TYPE_VAR_ZAPSIG:
2869 buf.Append( W("var ") );
2871 mdToken token = TokenFromRid(DacSigUncompressData(sig), mdtGenericParam);
2872 AppendTokenName(token, buf, pImport);
2876 case ELEMENT_TYPE_GENERICINST:
2878 TypeToString(sig, buf, pImport, pOrigImport);
2879 unsigned ntypars = DacSigUncompressData(sig);
2880 buf.Append( W("<") );
2881 for (unsigned i = 0; i < ntypars; i++)
2884 buf.Append( W(",") );
2885 // switch pImport back to our original Metadata importer
2886 TypeToString(sig, buf, pOrigImport, pOrigImport);
2888 buf.Append( W(">") );
2892 case ELEMENT_TYPE_FNPTR:
2893 buf.Append( W("(fnptr)") );
2896 // Modifiers or depedant types
2897 case ELEMENT_TYPE_PINNED:
2898 TypeToString(sig, buf, pImport, pOrigImport);
2899 buf.Append( W(" pinned") );
2902 case ELEMENT_TYPE_PTR:
2903 TypeToString(sig, buf, pImport, pOrigImport);
2904 buf.Append( W("*") );
2907 case ELEMENT_TYPE_BYREF:
2908 TypeToString(sig, buf, pImport, pOrigImport);
2909 buf.Append( W("&") );
2912 case ELEMENT_TYPE_SENTINEL:
2913 case ELEMENT_TYPE_END:
2915 _ASSERTE(!"Unknown Type");
2916 IfFailThrow(E_FAIL);
2922 void NativeImageDumper::DumpMethods(PTR_Module module)
2924 COUNT_T hotCodeSize;
2925 PCODE hotCode = m_decoder.GetNativeHotCode(&hotCodeSize);
2929 PCODE code = m_decoder.GetNativeCode(&codeSize);
2931 COUNT_T coldCodeSize;
2932 PCODE coldCode = m_decoder.GetNativeColdCode(&coldCodeSize);
2934 DisplayStartCategory( "Code", METHODS );
2935 DisplayWriteElementAddress( "HotCode", DataPtrToDisplay(hotCode),
2936 hotCodeSize, METHODS );
2938 DisplayWriteElementAddress( "UnprofiledCode",
2939 DataPtrToDisplay(code),
2940 codeSize, METHODS );
2941 DisplayWriteElementAddress( "ColdCode",
2942 DataPtrToDisplay(coldCode),
2943 coldCodeSize, METHODS );
2945 PTR_CORCOMPILE_CODE_MANAGER_ENTRY codeEntry(m_decoder.GetNativeCodeManagerTable());
2947 DisplayWriteElementAddress( "ROData",
2948 RvaToDisplay(codeEntry->ROData.VirtualAddress),
2949 codeEntry->ROData.Size, METHODS );
2951 DisplayWriteElementAddress( "HotCommonCode",
2952 DataPtrToDisplay(hotCode),
2953 codeEntry->HotIBCMethodOffset, METHODS );
2955 DisplayWriteElementAddress( "HotIBCMethodCode",
2956 DataPtrToDisplay(hotCode
2957 + codeEntry->HotIBCMethodOffset),
2958 codeEntry->HotGenericsMethodOffset
2959 - codeEntry->HotIBCMethodOffset,
2962 DisplayWriteElementAddress( "HotGenericsMethodCode",
2963 DataPtrToDisplay(hotCode
2964 + codeEntry->HotGenericsMethodOffset),
2965 hotCodeSize - codeEntry->HotGenericsMethodOffset,
2968 DisplayWriteElementAddress( "ColdIBCMethodCode",
2969 DataPtrToDisplay(coldCode),
2970 codeEntry->ColdUntrainedMethodOffset,
2973 MethodIterator mi(module, &m_decoder);
2975 DisplayStartArray( "Methods", NULL, METHODS );
2979 DumpCompleteMethod( module, mi );
2982 DisplayEndArray( "Total Methods", METHODS ); //Methods
2984 /* REVISIT_TODO Wed 12/14/2005
2985 * I have this coverage read in here because there is some other data between the
2986 * methods in debug builds. For now just whack the whole text section. Go
2987 * back later and check out that I really got everything.
2989 CoverageRead( hotCode, hotCodeSize );
2990 CoverageRead( coldCode, coldCodeSize );
2991 #ifdef USE_CORCOMPILE_HEADER
2992 CoverageRead( hotCodeTable, hotCodeTableSize );
2993 CoverageRead( coldCodeTable, coldCodeTableSize );
2996 DisplayEndCategory( METHODS ); //Code
2998 //m_display->StartCategory( "Methods" );
3001 static SString g_holdStringOutData;
3003 static void stringOut( const char* fmt, ... )
3006 va_start(args, fmt);
3007 g_holdStringOutData.AppendVPrintf(fmt, args);
3011 static void nullStringOut( const char * fmt, ... ) { }
3013 const NativeImageDumper::EnumMnemonics s_CorExceptionFlags[] =
3015 #define CEF_ENTRY(f,v) NativeImageDumper::EnumMnemonics(f, v)
3016 CEF_ENTRY(COR_ILEXCEPTION_CLAUSE_NONE, W("none")),
3017 CEF_ENTRY(COR_ILEXCEPTION_CLAUSE_FILTER, W("filter")),
3018 CEF_ENTRY(COR_ILEXCEPTION_CLAUSE_FINALLY, W("finally")),
3019 CEF_ENTRY(COR_ILEXCEPTION_CLAUSE_FAULT, W("fault")),
3020 CEF_ENTRY(COR_ILEXCEPTION_CLAUSE_DUPLICATED, W("duplicated")),
3024 void NativeImageDumper::DumpCompleteMethod(PTR_Module module, MethodIterator& mi)
3026 PTR_MethodDesc md = mi.GetMethodDesc();
3028 #ifdef WIN64EXCEPTIONS
3029 PTR_RUNTIME_FUNCTION pRuntimeFunction = mi.GetRuntimeFunction();
3032 //Read the GCInfo to get the total method size.
3033 unsigned methodSize = 0;
3034 unsigned gcInfoSize = UINT_MAX;
3036 //parse GCInfo for size information.
3037 GCInfoToken gcInfoToken = mi.GetGCInfoToken();
3038 PTR_CBYTE gcInfo = dac_cast<PTR_CBYTE>(gcInfoToken.Info);
3040 void (* stringOutFn)(const char *, ...);
3043 stringOutFn = stringOut;
3047 stringOutFn = nullStringOut;
3051 PTR_CBYTE curGCInfoPtr = gcInfo;
3052 g_holdStringOutData.Clear();
3053 GCDump gcDump(gcInfoToken.Version);
3054 gcDump.gcPrintf = stringOutFn;
3055 #if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
3056 GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
3057 methodSize = gcInfoDecoder.GetCodeLength();
3060 //dump the data to a string first so we can get the gcinfo size.
3063 stringOutFn( "method info Block:\n" );
3064 curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0);
3065 stringOutFn( "\n" );
3071 stringOutFn( "PointerTable:\n" );
3072 curGCInfoPtr += gcDump.DumpGCTable( curGCInfoPtr,
3075 gcInfoSize = curGCInfoPtr - gcInfo;
3076 #elif defined(USE_GC_INFO_DECODER)
3077 stringOutFn( "PointerTable:\n" );
3078 curGCInfoPtr += gcDump.DumpGCTable( curGCInfoPtr,
3080 gcInfoSize = (unsigned)(curGCInfoPtr - gcInfo);
3084 //data is output below.
3087 TADDR hotCodePtr = mi.GetMethodStartAddress();
3088 TADDR coldCodePtr = mi.GetMethodColdStartAddress();
3090 size_t hotCodeSize = methodSize;
3091 size_t coldCodeSize = 0;
3093 if (coldCodePtr != NULL)
3095 hotCodeSize = mi.GetHotCodeSize();
3096 coldCodeSize = methodSize - hotCodeSize;
3099 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(md)));
3100 const Dependency* mdDep = GetDependencyFromMD(md);
3102 _ASSERTE(mdDep->pImport);
3103 MethodDescToString(md, buffer);
3105 DisplayStartElement( "Method", METHODS );
3106 DisplayWriteElementStringW( "Name", (const WCHAR *)buffer, METHODS );
3108 /* REVISIT_TODO Mon 10/24/2005
3109 * Do I have to annotate this?
3111 DisplayWriteElementPointer("m_methodDesc",
3112 DPtrToPreferredAddr(md),
3115 DisplayStartStructure( "m_gcInfo",
3116 DPtrToPreferredAddr(gcInfo),
3120 DisplayStartTextElement( "Contents", GC_INFO );
3121 DisplayWriteXmlTextBlock( ("%S", (const WCHAR *)g_holdStringOutData), GC_INFO );
3122 DisplayEndTextElement( GC_INFO ); //Contents
3124 DisplayEndStructure( METHODS ); //GCInfo
3126 PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE pExceptionInfoTable (PTR_TO_TADDR(module->GetNGenLayoutInfo()->m_ExceptionInfoLookupTable.StartAddress()));
3127 if (pExceptionInfoTable)
3129 COUNT_T numLookupEntries = (COUNT_T) (module->GetNGenLayoutInfo()->m_ExceptionInfoLookupTable.Size() / sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY));
3130 DWORD methodStartRVA = m_decoder.GetDataRva(TO_TADDR(hotCodePtr));
3132 COUNT_T ehInfoSize = 0;
3133 DWORD exceptionInfoRVA = NativeExceptionInfoLookupTable::LookupExceptionInfoRVAForMethod(pExceptionInfoTable,
3138 if( exceptionInfoRVA != 0 )
3140 PTR_CORCOMPILE_EXCEPTION_CLAUSE pExceptionInfoArray = dac_cast<PTR_CORCOMPILE_EXCEPTION_CLAUSE>(PTR_TO_TADDR(m_decoder.GetBase()) + exceptionInfoRVA);
3141 COUNT_T ehCount = ehInfoSize / sizeof(CORCOMPILE_EXCEPTION_CLAUSE);
3142 _ASSERTE(ehCount > 0);
3143 DisplayStartArray("EHClauses", NULL, METHODS );
3144 for( unsigned i = 0; i < ehCount; ++i )
3146 PTR_CORCOMPILE_EXCEPTION_CLAUSE host = pExceptionInfoArray + i;
3148 DisplayStartStructure( "Clause", DPtrToPreferredAddr(host), sizeof(PTR_CORCOMPILE_EXCEPTION_CLAUSE), METHODS);
3149 DisplayWriteFieldEnumerated( Flags, host->Flags,
3150 EE_ILEXCEPTION_CLAUSE,
3151 s_CorExceptionFlags, W(", "),
3153 DisplayWriteFieldUInt( TryStartPC, host->TryStartPC,
3154 EE_ILEXCEPTION_CLAUSE, METHODS );
3155 DisplayWriteFieldUInt( TryEndPC, host->TryEndPC,
3156 EE_ILEXCEPTION_CLAUSE, METHODS );
3157 DisplayWriteFieldUInt( HandlerStartPC,
3158 host->HandlerStartPC,
3159 EE_ILEXCEPTION_CLAUSE, METHODS );
3160 DisplayWriteFieldUInt( HandlerEndPC,
3162 EE_ILEXCEPTION_CLAUSE, METHODS );
3163 if( host->Flags & COR_ILEXCEPTION_CLAUSE_FILTER )
3165 DisplayWriteFieldUInt( FilterOffset, host->FilterOffset,
3166 EE_ILEXCEPTION_CLAUSE, METHODS );
3168 else if( !(host->Flags & (COR_ILEXCEPTION_CLAUSE_FAULT | COR_ILEXCEPTION_CLAUSE_FINALLY)) )
3170 WriteFieldMDTokenImport( ClassToken, host->ClassToken,
3171 EE_ILEXCEPTION_CLAUSE, METHODS,
3174 DisplayEndStructure( METHODS ); //Clause
3176 DisplayEndArray("Total EHClauses", METHODS ); // Clauses
3180 TADDR fixupList = md->GetFixupList();
3181 if (fixupList != NULL)
3183 DisplayStartArray( "Fixups", NULL, METHODS );
3184 DumpMethodFixups(module, fixupList);
3185 DisplayEndArray(NULL, METHODS); //Fixups
3188 DisplayStartStructure( "Code", DataPtrToDisplay(hotCodePtr), hotCodeSize,
3191 IF_OPT(DISASSEMBLE_CODE)
3193 // Disassemble hot code. Read the code into the host process.
3194 /* REVISIT_TODO Mon 10/24/2005
3195 * Is this align up right?
3197 BYTE * codeStartHost =
3198 reinterpret_cast<BYTE*>(PTR_READ(hotCodePtr,
3199 (ULONG32)ALIGN_UP(hotCodeSize,
3201 DisassembleMethod( codeStartHost, hotCodeSize );
3205 CoverageRead(hotCodePtr,
3206 (ULONG32)ALIGN_UP(hotCodeSize, CODE_SIZE_ALIGN));
3209 DisplayEndStructure(METHODS); //HotCode
3211 if( coldCodePtr != NULL )
3213 DisplayStartStructure( "ColdCode", DataPtrToDisplay(coldCodePtr),
3214 coldCodeSize, METHODS );
3215 IF_OPT(DISASSEMBLE_CODE)
3217 // Disassemble cold code. Read the code into the host process.
3218 BYTE * codeStartHost =
3219 reinterpret_cast<BYTE*>(PTR_READ(coldCodePtr,
3220 (ULONG32)ALIGN_UP(coldCodeSize,
3222 DisassembleMethod( codeStartHost, coldCodeSize );
3226 CoverageRead(coldCodePtr,
3227 (ULONG32)ALIGN_UP(coldCodeSize, CODE_SIZE_ALIGN));
3230 DisplayEndStructure( METHODS ); //ColdCode
3232 DisplayEndElement( METHODS ); //Method
3238 void NativeImageDumper::DisassembleMethod(BYTE *code, SIZE_T size)
3240 _ASSERTE(CHECK_OPT(DISASSEMBLE_CODE));
3242 m_display->StartTextElement( "NativeCode" );
3244 #ifdef FEATURE_MSDIS
3246 BYTE *codeStart = code;
3248 /* XXX Wed 8/22/2007
3249 * The way I compute code size includes the switch tables at the end of the hot and/or cold section.
3250 * When the disassembler gets there, it has a tendency to crash as it runs off the end of mapped
3251 * memory. In order to properly compute this I need to look at the UnwindData (which is a
3252 * kernel32!RUNTIME_FUNCTION structure that gives the address range for the code. However, I also need
3253 * to chase through the list of funclets to make sure I disassemble everything. Instead of doing that,
3254 * I'll just trap the AV.
3258 while (code < (codeStart + size))
3260 const size_t count = m_dis->CbDisassemble(0, code, size);
3264 m_display->WriteXmlText( "%04x\tUnknown instruction (%02x)\n", code-codeStart, *code);
3269 /* XXX Fri 09/16/2005
3270 * PTR_HOST_TO_TADDR doesn't work on interior pointers.
3272 m_currentAddress = m_decoder.GetDataRva(PTR_HOST_TO_TADDR(codeStart)
3273 + (code - codeStart))
3274 + PTR_TO_TADDR(m_decoder.GetBase());
3276 const size_t cinstr = m_dis->Cinstruction();
3280 WCHAR szOpcode[4096];
3281 size_t len = m_dis->CchFormatInstr(szOpcode, _countof(szOpcode));
3282 _ASSERTE(szOpcode[len-1] == 0);
3283 m_display->WriteXmlText( "%04x\t%S\n", (code-codeStart) + (inum * 4), szOpcode );
3286 if (++inum >= cinstr)
3289 _ASSERTE((inum * 4) < count); // IA64 has 3 instructions per bundle commonly
3290 // referenced as offset 0, 4, and 8
3291 if (!m_dis->FSelectInstruction(inum))
3293 m_display->WriteXmlText( "%04x\tUnknown instruction within bundle\n", (code-codeStart) + (inum * 4));
3305 EX_END_CATCH(SwallowAllExceptions);
3307 #else // FEATURE_MSDIS
3309 m_display->WriteXmlText( "Disassembly not supported\n" );
3311 #endif // FEATURE_MSDIS
3313 m_display->EndTextElement(); //NativeCode
3316 SIZE_T NativeImageDumper::TranslateAddressCallback(IXCLRDisassemblySupport *dis,
3317 CLRDATA_ADDRESS addr,
3318 __out_ecount(nameSize) WCHAR *name, SIZE_T nameSize,
3321 NativeImageDumper *pThis = (NativeImageDumper *) dis->PvClient();
3323 SIZE_T ret = pThis->TranslateSymbol(dis,
3324 addr+(SIZE_T)pThis->m_currentAddress,
3325 name, nameSize, offset);
3329 _snwprintf_s(name, nameSize, _TRUNCATE, W("@TRANSLATED ADDRESS@ %p"),
3330 (TADDR)(addr + (SIZE_T)pThis->m_currentAddress) );
3337 SIZE_T NativeImageDumper::TranslateFixupCallback(IXCLRDisassemblySupport *dis,
3338 CLRDATA_ADDRESS addr,
3339 SIZE_T size, __out_ecount(nameSize) WCHAR *name,
3343 NativeImageDumper *pThis = (NativeImageDumper *) dis->PvClient();
3344 if( !dis->TargetIsAddress() )
3347 TADDR taddr = TO_TADDR(pThis->m_currentAddress) + (TADDR)addr;
3348 SSIZE_T targetOffset;
3352 targetOffset = *PTR_SIZE_T(taddr);
3356 targetOffset = *PTR_INT32(taddr);
3360 targetOffset = *(short*)(WORD*)PTR_WORD(taddr);
3362 case sizeof(signed char):
3363 targetOffset = *PTR_SBYTE(taddr);
3369 CLRDATA_ADDRESS address = targetOffset + TO_TADDR(pThis->m_currentAddress) + addr + size;
3371 SIZE_T ret = pThis->TranslateSymbol(dis, address, name, nameSize, offset);
3374 _snwprintf_s(name, nameSize, _TRUNCATE, W("@TRANSLATED FIXUP@ %p"), (TADDR)address);
3381 size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis,
3382 CLRDATA_ADDRESS addr, __out_ecount(nameSize) WCHAR *name,
3383 SIZE_T nameSize, DWORDLONG *offset)
3385 #ifdef FEATURE_READYTORUN
3386 if (m_pReadyToRunHeader != NULL)
3390 if (isInRange((TADDR)addr))
3392 COUNT_T rva = (COUNT_T)(addr - PTR_TO_TADDR(m_decoder.GetBase()));
3394 COUNT_T helperTableSize;
3395 void *helperTable = m_decoder.GetNativeHelperTable(&helperTableSize);
3397 if (rva >= m_decoder.GetDataRva(TO_TADDR(helperTable))
3398 && rva < (m_decoder.GetDataRva(TO_TADDR(helperTable))
3401 int helperIndex = (USHORT)*PTR_DWORD(TO_TADDR(addr));
3402 // _ASSERTE(helperIndex < CORINFO_HELP_COUNT);
3403 // because of literal blocks we might have bogus values
3404 if (helperIndex < CORINFO_HELP_COUNT)
3405 _snwprintf_s(name, nameSize, _TRUNCATE, W("<%S>"), g_helperNames[helperIndex]);
3407 _snwprintf_s(name, nameSize, _TRUNCATE, W("Illegal HelperIndex<%04X>"), helperIndex);
3409 return wcslen(name);
3412 PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
3413 PTR_NGenLayoutInfo pNgenLayout = module->GetNGenLayoutInfo();
3415 for (int iRange = 0; iRange < 2; iRange++)
3417 if (pNgenLayout->m_CodeSections[iRange].IsInRange((TADDR)addr))
3419 int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1);
3420 if (MethodIndex >= 0)
3422 #ifdef WIN64EXCEPTIONS
3423 while (pNgenLayout->m_MethodDescs[iRange][MethodIndex] == 0)
3427 PTR_RUNTIME_FUNCTION pRuntimeFunction = pNgenLayout->m_pRuntimeFunctions[iRange] + MethodIndex;
3429 PTR_MethodDesc pMD = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase()));
3431 MethodDescToString( pMD, buf );
3432 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s "), (const WCHAR *)buf );
3433 *offset = rva - RUNTIME_FUNCTION__BeginAddress(pRuntimeFunction);
3434 return wcslen(name);
3439 if (pNgenLayout->m_CodeSections[2].IsInRange((TADDR)addr))
3441 int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[2], 0, pNgenLayout->m_nRuntimeFunctions[2] - 1);
3442 if (ColdMethodIndex >= 0)
3444 PTR_RUNTIME_FUNCTION pRuntimeFunction;
3446 PTR_CORCOMPILE_COLD_METHOD_ENTRY pColdCodeMap = pNgenLayout->m_ColdCodeMap;
3448 #ifdef WIN64EXCEPTIONS
3449 while (pColdCodeMap[ColdMethodIndex].mainFunctionEntryRVA == 0)
3452 pRuntimeFunction = dac_cast<PTR_RUNTIME_FUNCTION>(PTR_TO_TADDR(m_decoder.GetBase()) + pColdCodeMap[ColdMethodIndex].mainFunctionEntryRVA);
3454 DWORD ColdUnwindData = pNgenLayout->m_pRuntimeFunctions[2][ColdMethodIndex].UnwindData;
3455 _ASSERTE((ColdUnwindData & RUNTIME_FUNCTION_INDIRECT) != 0);
3456 pRuntimeFunction = dac_cast<PTR_RUNTIME_FUNCTION>(PTR_TO_TADDR(m_decoder.GetBase()) + (ColdUnwindData & ~RUNTIME_FUNCTION_INDIRECT));
3459 PTR_MethodDesc pMD = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase()));
3461 MethodDescToString( pMD, buf );
3462 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s (cold region)"), (const WCHAR *)buf );
3463 *offset = rva - RUNTIME_FUNCTION__BeginAddress(&pNgenLayout->m_pRuntimeFunctions[2][ColdMethodIndex]);
3464 return wcslen(name);
3468 //Dumping precodes by name requires some information from the module (the precode ranges).
3469 IF_OPT_OR(PRECODES, MODULE)
3471 TempBuffer precodeBuf;
3472 //maybe it is a precode
3473 PTR_Precode maybePrecode((TADDR)addr);
3474 const char * precodeName = NULL;
3475 if (isPrecode((TADDR)addr))
3477 switch(maybePrecode->GetType())
3479 case PRECODE_INVALID:
3480 precodeName = "InvalidPrecode"; break;
3482 precodeName = "StubPrecode"; break;
3483 #ifdef HAS_NDIRECT_IMPORT_PRECODE
3484 case PRECODE_NDIRECT_IMPORT:
3485 precodeName = "NDirectImportPrecode"; break;
3486 #endif // HAS_NDIRECT_IMPORT_PRECODE
3487 #ifdef HAS_FIXUP_PRECODE
3489 #ifdef HAS_RELATIVE_FIXUP_PRECODE
3490 _ASSERTE(!"unreachable"); break;
3491 #else // HAS_RELATIVE_FIXUP_PRECODE
3492 precodeName = "FixupPrecode"; break;
3493 #endif // HAS_RELATIVE_FIXUP_PRECODE
3494 #endif // HAS_FIXUP_PRECODE
3495 #ifdef HAS_RELATIVE_FIXUP_PRECODE
3496 case PRECODE_RELATIVE_FIXUP:
3497 precodeName = "RelativeFixupPrecode"; break;
3498 #endif // HAS_RELATIVE_FIXUP_PRECODE
3499 #ifdef HAS_THISPTR_RETBUF_PRECODE
3500 case PRECODE_THISPTR_RETBUF:
3501 precodeName = "ThisPtrRetBufPrecode"; break;
3502 #endif // HAS_THISPTR_RETBUF_PRECODE
3508 precodeBuf.AppendPrintf( W("%S (0x%p)"), precodeName, addr );
3510 //get MethodDesc from precode and dump the target
3511 PTR_MethodDesc precodeMD(maybePrecode->GetMethodDesc());
3512 precodeBuf.Append( W(" for ") );
3513 MethodDescToString(precodeMD, precodeBuf);
3515 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)precodeBuf);
3518 return wcslen(name);
3522 PTR_CORCOMPILE_IMPORT_SECTION pImportSection = m_decoder.GetNativeImportSectionForRVA(rva);
3523 if (pImportSection != NULL)
3525 const char * wbRangeName = NULL;
3526 switch (pImportSection->Type)
3528 case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
3529 wbRangeName = "ExternalMethod";
3533 case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
3534 wbRangeName = "VirtualMethod";
3537 case CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH:
3538 wbRangeName = "StubDispatch";
3542 // This method is only ever called for targets of direct calls right now and so the only
3543 // import that can meaninfully show up here is external method thunk.
3548 TempBuffer fixupThunkBuf;
3549 fixupThunkBuf.AppendPrintf( W("%S (0x%p) for "), wbRangeName, addr );
3550 FixupThunkToString(pImportSection, (TADDR)addr, fixupThunkBuf);
3552 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)fixupThunkBuf);
3555 return wcslen(name);
3558 else if( g_dacImpl->GetJitHelperFunctionName(addr,
3559 _countof(bigByteBuffer),
3560 (char*)bigByteBuffer,
3564 _snwprintf_s( name, nameSize, _TRUNCATE, W("%S"), bigByteBuffer );
3565 return wcslen(name);
3570 if( m_mscorwksBase <= addr &&
3571 addr < (m_mscorwksBase + m_mscorwksSize) )
3573 *offset = addr - m_mscorwksBase;
3574 _snwprintf_s( name, nameSize, _TRUNCATE, W("clr") );
3575 return wcslen(name);
3577 for( COUNT_T i = 0; i < m_numDependencies; ++i )
3579 const Dependency& dep = m_dependencies[i];
3580 if( dep.pLoadedAddress <= addr &&
3581 addr < (dep.pLoadedAddress + dep.size) )
3583 *offset = addr - dep.pLoadedAddress;
3584 _snwprintf_s( name, nameSize, _TRUNCATE, W("%s.ni"), dep.name );
3585 return wcslen(name);
3593 BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
3595 PTR_SIZE_T fixupPtr(TO_TADDR(fixupCell));
3596 m_display->StartElement( "Fixup" );
3597 m_display->WriteElementPointer( "Address",
3598 DataPtrToDisplay( TO_TADDR(fixupCell) ) );
3599 m_display->WriteElementUInt( "TaggedValue", (DWORD)*fixupPtr );
3600 WriteElementsFixupBlob(pSection, *fixupPtr);
3601 m_display->EndElement();
3606 void NativeImageDumper::DumpMethodFixups(PTR_Module module,
3609 _ASSERTE( CHECK_OPT(METHODS) );
3611 COUNT_T nImportSections;
3612 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
3614 //create the first element outside of the callback. The callback creates
3615 //subsequent elements.
3616 module->FixupDelayListAux( fixupList, this,
3617 &NativeImageDumper::HandleFixupForMethodDump,
3618 pImportSections, nImportSections,
3622 IMAGE_SECTION_HEADER * NativeImageDumper::FindSection( char const * name )
3624 COUNT_T numberOfSections = m_decoder.GetNumberOfSections();
3625 PTR_IMAGE_SECTION_HEADER curSection( m_decoder.FindFirstSection() );
3627 for ( ; numberOfSections > 0; --numberOfSections, ++curSection )
3629 if ( ! strncmp( reinterpret_cast< char * >( curSection->Name ), name, 8 ) )
3633 if ( ! numberOfSections )
3639 NativeImageDumper::EnumMnemonics NativeImageDumper::s_ModulePersistedFlags[] =
3641 #define MPF_ENTRY(f) NativeImageDumper::EnumMnemonics(Module::f, W(#f))
3642 MPF_ENTRY(COMPUTED_GLOBAL_CLASS),
3644 MPF_ENTRY(COMPUTED_STRING_INTERNING),
3645 MPF_ENTRY(NO_STRING_INTERNING),
3647 MPF_ENTRY(COMPUTED_WRAP_EXCEPTIONS),
3648 MPF_ENTRY(WRAP_EXCEPTIONS),
3650 MPF_ENTRY(COMPUTED_RELIABILITY_CONTRACT),
3652 MPF_ENTRY(COLLECTIBLE_MODULE),
3653 MPF_ENTRY(COMPUTED_IS_PRE_V4_ASSEMBLY),
3654 MPF_ENTRY(IS_PRE_V4_ASSEMBLY),
3655 MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED),
3656 MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS),
3658 MPF_ENTRY(COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP),
3659 MPF_ENTRY(LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME),
3663 //VirtualSectionTypes.
3664 #define TEXTIFY(x) W(#x)
3665 static const NativeImageDumper::EnumMnemonics s_virtualSectionFlags [] =
3668 #define CORCOMPILE_SECTION_IBCTYPE(ibcType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(ibcType)),
3669 CORCOMPILE_SECTION_IBCTYPES()
3670 #undef CORCOMPILE_SECTION_IBCTYPE
3672 #define CORCOMPILE_SECTION_RANGE_TYPE(rangeType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(rangeType) W("Range")),
3673 CORCOMPILE_SECTION_RANGE_TYPES()
3674 #undef CORCOMPILE_SECTION_RANGE_TYPE
3676 const WCHAR * g_sectionNames[] =
3678 W("SECTION_DUMMY"), // the first section start at 0x1. Make the array 1 based.
3679 #define CORCOMPILE_SECTION_TYPE(section) W("SECTION_") TEXTIFY(section),
3680 CORCOMPILE_SECTION_TYPES()
3681 #undef CORCOMPILE_SECTION
3688 #pragma warning(push)
3689 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3692 void NativeImageDumper::DumpModule( PTR_Module module )
3695 //the module is the fisrt thing in the .data section. We use this fact for
3696 //the sectionBases down below.
3697 // _ASSERTE(m_decoder.GetDataRva(PTR_TO_TADDR(module))
3698 // == FindSection(".data")->VirtualAddress );
3700 DisplayStartStructure( "module", DPtrToPreferredAddr(module),
3701 sizeof(*module), MODULE );
3702 PTR_PEFile file = module->m_file;
3703 _ASSERTE(file == NULL);
3704 DisplayWriteFieldPointer( m_file, DPtrToPreferredAddr(file), Module,
3707 PTR_MethodDesc dllMain( TO_TADDR(module->m_pDllMain) );
3708 WriteFieldMethodDesc( m_pDllMain, dllMain, Module,
3711 _ASSERTE(module->m_dwTransientFlags == 0U);
3712 DisplayWriteFieldUInt(m_dwTransientFlags, module->m_dwTransientFlags,
3717 DisplayWriteFieldEnumerated( m_dwPersistedFlags, module->m_dwPersistedFlags,
3718 Module, s_ModulePersistedFlags, W("|"), MODULE );
3720 DisplayWriteFieldPointer( m_pAssembly,
3721 DPtrToPreferredAddr(module->m_pAssembly),
3723 _ASSERTE(module->m_pAssembly == NULL); //never appears in the image
3725 DisplayWriteFieldUInt( m_moduleRef, module->m_moduleRef, Module, MODULE );
3726 DisplayWriteFieldInt( m_dwDebuggerJMCProbeCount,
3727 module->m_dwDebuggerJMCProbeCount, Module, MODULE );
3728 /* REVISIT_TODO Fri 10/14/2005
3731 PTR_MscorlibBinder binder = module->m_pBinder;
3732 if( NULL != binder )
3734 DisplayStartStructureWithOffset( m_pBinder, DPtrToPreferredAddr(binder),
3735 sizeof(*binder), Module,
3738 //these four fields don't have anything useful in ngen images.
3739 DisplayWriteFieldPointer( m_classDescriptions,
3740 DPtrToPreferredAddr(binder->m_classDescriptions),
3741 MscorlibBinder, MODULE );
3742 DisplayWriteFieldPointer( m_methodDescriptions,
3743 DPtrToPreferredAddr(binder->m_methodDescriptions),
3744 MscorlibBinder, MODULE );
3745 DisplayWriteFieldPointer( m_fieldDescriptions,
3746 DPtrToPreferredAddr(binder->m_fieldDescriptions),
3747 MscorlibBinder, MODULE );
3748 DisplayWriteFieldPointer( m_pModule,
3749 DPtrToPreferredAddr(binder->m_pModule),
3750 MscorlibBinder, MODULE );
3752 DisplayWriteFieldInt( m_cClasses, binder->m_cClasses, MscorlibBinder,
3754 DisplayWriteFieldAddress( m_pClasses,
3755 DPtrToPreferredAddr(binder->m_pClasses),
3756 sizeof(*binder->m_pClasses)
3757 * binder->m_cClasses,
3758 MscorlibBinder, MODULE );
3759 DisplayWriteFieldInt( m_cFields, binder->m_cFields, MscorlibBinder,
3761 DisplayWriteFieldAddress( m_pFields,
3762 DPtrToPreferredAddr(binder->m_pFields),
3763 sizeof(*binder->m_pFields)
3764 * binder->m_cFields,
3765 MscorlibBinder, MODULE );
3766 DisplayWriteFieldInt( m_cMethods, binder->m_cMethods, MscorlibBinder,
3768 DisplayWriteFieldAddress( m_pMethods,
3769 DPtrToPreferredAddr(binder->m_pMethods),
3770 sizeof(*binder->m_pMethods)
3771 * binder->m_cMethods,
3772 MscorlibBinder, MODULE );
3774 DisplayEndStructure( MODULE ); //m_pBinder
3778 DisplayWriteFieldPointer( m_pBinder, NULL, Module, MODULE );
3782 /* REVISIT_TODO Tue 10/25/2005
3783 * unconditional dependencies, activations, class dependencies, thunktable
3787 //round trip the LookupMap back through the DAC so that we don't have an
3788 //interior host pointer.
3789 PTR_LookupMapBase lookupMap( PTR_TO_TADDR(module)
3790 + offsetof(Module, m_TypeDefToMethodTableMap) );
3791 TraverseMap( lookupMap, "m_TypeDefToMethodTableMap",
3792 offsetof(Module, m_TypeDefToMethodTableMap),
3793 fieldsize(Module, m_TypeDefToMethodTableMap),
3794 &NativeImageDumper::IterateTypeDefToMTCallback );
3796 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3797 + offsetof(Module, m_TypeRefToMethodTableMap) );
3799 TraverseMap( lookupMap, "m_TypeRefToMethodTableMap",
3800 offsetof(Module, m_TypeRefToMethodTableMap),
3801 fieldsize(Module, m_TypeRefToMethodTableMap),
3802 &NativeImageDumper::IterateTypeRefToMTCallback );
3804 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3805 + offsetof(Module, m_MethodDefToDescMap) );
3806 TraverseMap( lookupMap, "m_MethodDefToDescMap",
3807 offsetof(Module, m_MethodDefToDescMap),
3808 fieldsize(Module, m_MethodDefToDescMap),
3809 &NativeImageDumper::IterateMethodDefToMDCallback);
3811 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3812 + offsetof(Module, m_FieldDefToDescMap) );
3813 TraverseMap( lookupMap, "m_FieldDefToDescMap",
3814 offsetof(Module, m_FieldDefToDescMap),
3815 fieldsize(Module, m_FieldDefToDescMap),
3816 &NativeImageDumper::IterateFieldDefToFDCallback);
3818 TraverseMemberRefToDescHash(module->m_pMemberRefToDescHashTable, "m_pMemberRefToDescHashTable",
3819 offsetof(Module, m_pMemberRefToDescHashTable),
3820 fieldsize(Module, m_pMemberRefToDescHashTable),
3823 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3824 + offsetof(Module, m_GenericParamToDescMap) );
3826 TraverseMap( lookupMap, "m_GenericParamToDescMap",
3827 offsetof(Module, m_GenericParamToDescMap),
3828 fieldsize(Module, m_GenericParamToDescMap),
3829 &NativeImageDumper::IterateGenericParamToDescCallback);
3831 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3832 + offsetof(Module, m_GenericTypeDefToCanonMethodTableMap) );
3834 TraverseMap( lookupMap, "m_GenericTypeDefToCanonMethodTableMap",
3835 offsetof(Module, m_GenericTypeDefToCanonMethodTableMap),
3836 fieldsize(Module, m_GenericTypeDefToCanonMethodTableMap),
3837 &NativeImageDumper::IterateTypeDefToMTCallback );
3839 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3840 + offsetof(Module, m_FileReferencesMap) );
3841 TraverseMap( lookupMap, "m_FileReferencesMap",
3842 offsetof(Module, m_FileReferencesMap),
3843 fieldsize(Module, m_FileReferencesMap),
3844 &NativeImageDumper::IterateMemberRefToDescCallback);
3846 lookupMap = PTR_LookupMapBase(PTR_TO_TADDR(module)
3847 + offsetof(Module,m_ManifestModuleReferencesMap));
3849 TraverseMap( lookupMap, "m_ManifestModuleReferencesMap",
3850 offsetof(Module, m_ManifestModuleReferencesMap),
3851 fieldsize(Module, m_ManifestModuleReferencesMap),
3852 &NativeImageDumper::IterateManifestModules);
3854 TraverseClassHash( module->m_pAvailableClasses, "m_pAvailableClasses",
3855 offsetof(Module, m_pAvailableClasses),
3856 fieldsize(Module, m_pAvailableClasses), true );
3858 TraverseTypeHash( module->m_pAvailableParamTypes, "m_pAvailableParamTypes",
3859 offsetof(Module, m_pAvailableParamTypes),
3860 fieldsize(Module, m_pAvailableParamTypes) );
3861 TraverseInstMethodHash( module->m_pInstMethodHashTable,
3862 "m_pInstMethodHashTable",
3863 offsetof(Module, m_pInstMethodHashTable),
3864 fieldsize(Module, m_pInstMethodHashTable),
3866 TraverseStubMethodHash( module->m_pStubMethodHashTable,
3867 "m_pStubMethodHashTable",
3868 offsetof(Module, m_pStubMethodHashTable),
3869 fieldsize(Module, m_pStubMethodHashTable),
3874 TraverseClassHash( module->m_pAvailableClassesCaseIns,
3875 "m_pAvailableClassesCaseIns",
3876 offsetof(Module, m_pAvailableClassesCaseIns),
3877 fieldsize(Module, m_pAvailableClassesCaseIns),
3881 #ifdef FEATURE_COMINTEROP
3882 TraverseGuidToMethodTableHash( module->m_pGuidToTypeHash,
3883 "m_pGuidToTypeHash",
3884 offsetof(Module, m_pGuidToTypeHash),
3885 fieldsize(Module, m_pGuidToTypeHash),
3888 #endif // FEATURE_COMINTEROP
3890 _ASSERTE(module->m_pProfilingBlobTable == NULL);
3892 DisplayWriteFieldFlag( m_nativeImageProfiling,
3893 module->m_nativeImageProfiling, Module, MODULE );
3895 DisplayWriteFieldPointer( m_methodProfileList,
3896 DataPtrToDisplay((TADDR)module->m_methodProfileList),
3898 _ASSERTE(module->m_methodProfileList == NULL);
3900 /* REVISIT_TODO Tue 10/04/2005
3901 * Dump module->m_moduleCtorInfo
3903 PTR_ModuleCtorInfo ctorInfo( PTR_HOST_MEMBER_TADDR(Module, module,
3904 m_ModuleCtorInfo) );
3906 DisplayStartStructureWithOffset( m_ModuleCtorInfo,
3907 DPtrToPreferredAddr(ctorInfo),
3909 Module, SLIM_MODULE_TBLS );
3910 DisplayWriteFieldInt( numElements, ctorInfo->numElements, ModuleCtorInfo,
3912 DisplayWriteFieldInt( numLastAllocated, ctorInfo->numLastAllocated,
3913 ModuleCtorInfo, SLIM_MODULE_TBLS );
3914 DisplayWriteFieldInt( numElementsHot, ctorInfo->numElementsHot,
3915 ModuleCtorInfo, SLIM_MODULE_TBLS );
3916 DisplayWriteFieldAddress( ppMT, DPtrToPreferredAddr(ctorInfo->ppMT),
3917 ctorInfo->numElements * sizeof(RelativePointer<MethodTable*>),
3918 ModuleCtorInfo, SLIM_MODULE_TBLS );
3919 /* REVISIT_TODO Tue 03/21/2006
3920 * is cctorInfoHot and cctorInfoCold actually have anything interesting
3923 DisplayWriteFieldAddress( cctorInfoHot,
3924 DPtrToPreferredAddr(ctorInfo->cctorInfoHot),
3925 sizeof(*ctorInfo->cctorInfoHot)
3926 * ctorInfo->numElementsHot,
3927 ModuleCtorInfo, SLIM_MODULE_TBLS );
3928 DisplayWriteFieldAddress( cctorInfoCold,
3929 DPtrToPreferredAddr(ctorInfo->cctorInfoCold),
3930 sizeof(*ctorInfo->cctorInfoCold)
3931 * (ctorInfo->numElements
3932 - ctorInfo->numElementsHot),
3933 ModuleCtorInfo, SLIM_MODULE_TBLS );
3934 /* XXX Thu 03/23/2006
3935 * See ModuleCtorInfo::Save for why these are +1.
3937 DisplayWriteFieldAddress( hotHashOffsets,
3938 DPtrToPreferredAddr(ctorInfo->hotHashOffsets),
3939 (ctorInfo->numHotHashes + 1)
3940 * sizeof(*ctorInfo->hotHashOffsets),
3941 ModuleCtorInfo, SLIM_MODULE_TBLS );
3942 DisplayWriteFieldAddress( coldHashOffsets,
3943 DPtrToPreferredAddr(ctorInfo->coldHashOffsets),
3944 (ctorInfo->numColdHashes + 1)
3945 * sizeof(*ctorInfo->coldHashOffsets),
3946 ModuleCtorInfo, SLIM_MODULE_TBLS );
3948 DisplayWriteFieldInt( numHotHashes, ctorInfo->numHotHashes, ModuleCtorInfo,
3950 DisplayWriteFieldInt( numColdHashes, ctorInfo->numColdHashes,
3951 ModuleCtorInfo, SLIM_MODULE_TBLS );
3953 DisplayWriteFieldAddress( ppHotGCStaticsMTs,
3954 DPtrToPreferredAddr(ctorInfo->ppHotGCStaticsMTs),
3955 ctorInfo->numHotGCStaticsMTs
3956 * sizeof(*ctorInfo->ppHotGCStaticsMTs),
3957 ModuleCtorInfo, SLIM_MODULE_TBLS );
3958 DisplayWriteFieldAddress( ppColdGCStaticsMTs,
3959 DPtrToPreferredAddr(ctorInfo->ppColdGCStaticsMTs),
3960 ctorInfo->numColdGCStaticsMTs
3961 * sizeof(*ctorInfo->ppColdGCStaticsMTs),
3962 ModuleCtorInfo, SLIM_MODULE_TBLS );
3963 DisplayWriteFieldInt( numHotGCStaticsMTs, ctorInfo->numHotGCStaticsMTs,
3964 ModuleCtorInfo, SLIM_MODULE_TBLS );
3965 DisplayWriteFieldInt( numColdGCStaticsMTs, ctorInfo->numColdGCStaticsMTs,
3966 ModuleCtorInfo, SLIM_MODULE_TBLS );
3968 DisplayEndStructure( SLIM_MODULE_TBLS ); //m_ModuleCtorInfo
3970 _ASSERTE(module->m_pNgenStats == NULL);
3972 DisplayWriteFieldPointer( m_pNgenStats,
3973 DataPtrToDisplay((TADDR)module->m_pNgenStats),
3976 DisplayWriteFieldAddress(m_propertyNameSet,
3977 DPtrToPreferredAddr(module->m_propertyNameSet),
3978 sizeof(module->m_propertyNameSet[0]) *
3979 module->m_nPropertyNameSet,
3982 DisplayWriteFieldPointer( m_ModuleID,
3983 DataPtrToDisplay(dac_cast<TADDR>(module->m_ModuleID)),
3985 _ASSERTE(module->m_ModuleID == NULL);
3987 /* XXX Tue 04/11/2006
3988 * Value is either -1 or 0, so no need to rebase.
3990 DisplayWriteFieldPointer( m_pRegularStaticOffsets,
3991 PTR_TO_TADDR(module->m_pRegularStaticOffsets),
3993 _ASSERTE(module->m_pRegularStaticOffsets == (void*)-1
3994 || module->m_pRegularStaticOffsets == 0 );
3996 DisplayWriteFieldInt( m_dwMaxGCRegularStaticHandles,
3997 module->m_dwMaxGCRegularStaticHandles, Module, MODULE );
3998 DisplayWriteFieldInt( m_dwRegularStaticsBlockSize, module->m_dwRegularStaticsBlockSize,
4000 DisplayWriteFieldAddress( m_pDynamicStaticsInfo,
4001 DataPtrToDisplay((TADDR)module->m_pDynamicStaticsInfo),
4002 module->m_maxDynamicEntries
4003 * sizeof(*(module->m_pDynamicStaticsInfo)),
4006 DisplayWriteFieldInt( m_cDynamicEntries,
4007 (int)module->m_cDynamicEntries, Module, MODULE );
4009 CoverageRead(TO_TADDR(module->m_pDynamicStaticsInfo),
4010 (int)(module->m_maxDynamicEntries
4011 * sizeof(*(module->m_pDynamicStaticsInfo))));
4015 _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL);
4016 DisplayWriteFieldPointer( m_debuggerSpecificData.m_pDynamicILCrst,
4017 DataPtrToDisplay(dac_cast<TADDR>(module->m_debuggerSpecificData.m_pDynamicILCrst)),
4021 /* REVISIT_TODO Wed 09/21/2005
4022 * Get me in the debugger and look at the activations and module/class
4024 * As well as the thunks.
4027 /* REVISIT_TODO Wed 09/21/2005
4028 * Dump the following
4033 DisplayWriteFieldInt( m_DefaultDllImportSearchPathsAttributeValue,
4034 module->m_DefaultDllImportSearchPathsAttributeValue, Module, MODULE );
4037 DisplayEndStructure(MODULE); //Module
4040 #pragma warning(pop)
4043 bool NativeImageDumper::isPrecode(TADDR maybePrecode)
4045 PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
4047 return !!module->IsZappedPrecode(maybePrecode);
4051 void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget,
4053 PTR_LookupMapBase map,
4056 DisplayStartElement( "Entry", MODULE_TABLES );
4058 PTR_MethodTable mt(mtTarget);
4060 DisplayWriteElementUInt( "Token", rid | mdtTypeDef, MODULE_TABLES );
4061 /* REVISIT_TODO Fri 10/21/2005
4062 * Can I use WriteElementMethodTable here?
4064 DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4066 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4067 /* REVISIT_TODO Fri 09/30/2005
4068 * This handles the extra entries in the type table that shouldn't be there.
4070 if( rid == 0 || ((rid != 1) && (mtTarget == NULL)) )
4072 DisplayWriteElementString( "Name", "mdTypeDefNil", MODULE_TABLES );
4077 MethodTableToString( mt, buf );
4078 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4080 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4082 DisplayEndElement( MODULE_TABLES );
4084 if( isInRange(PTR_TO_TADDR(mt)) )
4086 m_discoveredMTs.AppendEx(mt);
4087 PTR_EEClass clazz = GetClassFromMT(mt);
4088 if( isInRange(PTR_TO_TADDR(clazz)) )
4089 m_discoveredClasses.AppendEx(mt);
4093 void NativeImageDumper::IterateTypeRefToMTCallback( TADDR mtTarget,
4095 PTR_LookupMapBase map,
4098 DisplayStartElement( "Entry", MODULE_TABLES );
4100 mtTarget = ((FixupPointer<TADDR>&)mtTarget).GetValue();
4102 PTR_MethodTable mt(mtTarget);
4105 RecordTypeRef(rid | mdtTypeRef, mt);
4108 DisplayWriteElementUInt( "Token", rid | mdtTypeRef, MODULE_TABLES );
4110 DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4115 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4116 DisplayWriteElementString( "Name", "mdtTypeRefNil", MODULE_TABLES );
4118 else if( mt == NULL )
4120 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4121 IF_OPT(MODULE_TABLES)
4122 WriteElementMDToken( "Name", mdtTypeRef | rid );
4124 else if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
4126 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
4128 // This guy writes two things FixupTargetValue and FixupTargetName
4130 WriteElementsFixupBlob( NULL,PTR_TO_TADDR(mt));
4135 MethodTableToString( mt, buf );
4136 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4137 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4139 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4141 DisplayEndElement( MODULE_TABLES );
4142 if( isInRange(mtTarget) )
4144 m_discoveredMTs.AppendEx(mt);
4145 PTR_EEClass clazz = GetClassFromMT(mt);
4146 if( isInRange(PTR_TO_TADDR(clazz)) )
4147 m_discoveredClasses.AppendEx(mt);
4151 void NativeImageDumper::IterateMethodDefToMDCallback( TADDR mdTarget,
4153 PTR_LookupMapBase map,
4156 DisplayStartElement( "Entry", MODULE_TABLES );
4158 PTR_MethodDesc md(mdTarget);
4160 DisplayWriteElementUInt( "Token", rid | mdtMethodDef, MODULE_TABLES );
4162 DisplayWriteElementPointer( "MethodDesc", DPtrToPreferredAddr(md),
4165 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4168 DisplayWriteElementString( "Name", "mdtMethodDefNil", MODULE_TABLES );
4173 MethodDescToString( md, buf );
4174 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4176 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4178 DisplayEndElement( MODULE_TABLES );
4179 //m_discoveredMDs.AppendEx(md);
4182 void NativeImageDumper::IterateFieldDefToFDCallback( TADDR fdTarget,
4184 PTR_LookupMapBase map,
4187 PTR_FieldDesc fd(fdTarget);
4188 DisplayStartElement( "Entry", MODULE_TABLES );
4191 DisplayWriteElementUInt( "Token", rid | mdtFieldDef, MODULE_TABLES );
4193 DisplayWriteElementPointer( "FieldDef", DPtrToPreferredAddr(fd),
4196 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4199 DisplayWriteElementString( "Name", "mdtFieldDefNil", MODULE_TABLES );
4204 FieldDescToString( fd, mdtFieldDef | rid, buf );
4205 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4207 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4209 DisplayEndElement( MODULE_TABLES );
4210 /* XXX Mon 10/17/2005
4211 * All FieldDescs are reachable from the EEClasses
4213 //m_discoveredFDs.AppendEx(PTR_FieldDesc(fdTarget));
4216 void NativeImageDumper::IterateMemberRefToDescCallback( TADDR mrTarget,
4218 PTR_LookupMapBase map,
4221 DisplayStartElement( "Entry", MODULE_TABLES );
4224 bool isFieldRef = (flags & IS_FIELD_MEMBER_REF) != 0;
4225 mdToken targetToken = mdtMemberRef | rid;
4226 mrTarget = ((FixupPointer<TADDR>&)mrTarget).GetValue();
4227 DisplayWriteElementUInt( "Token", targetToken, MODULE_TABLES );
4228 DisplayWriteElementPointer( isFieldRef ? "FieldDesc" : "MethodDesc",
4229 DataPtrToDisplay(mrTarget), MODULE_TABLES );
4234 buf.Append( W("mdtMemberDefNil") );
4236 else if( CORCOMPILE_IS_POINTER_TAGGED(mrTarget) )
4238 WriteElementsFixupBlob( NULL, mrTarget );
4240 else if( isFieldRef )
4242 FieldDescToString( PTR_FieldDesc(mrTarget), buf );
4246 MethodDescToString( PTR_MethodDesc(mrTarget), buf );
4248 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4249 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4251 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4253 DisplayEndElement(MODULE_TABLES);
4254 //m_discoveredMTs.AppendEx(mt);
4257 void NativeImageDumper::IterateGenericParamToDescCallback( TADDR tdTarget,
4259 PTR_LookupMapBase map,
4262 PTR_TypeDesc td(tdTarget);
4263 DisplayStartElement( "Entry", MODULE_TABLES );
4266 DisplayWriteElementUInt( "Token", rid | mdtGenericParam, MODULE_TABLES );
4268 DisplayWriteElementPointer( "GenericParam", DPtrToPreferredAddr(td),
4271 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4272 if( rid == 0 || td == NULL )
4274 DisplayWriteElementString( "Name", "mdtGenericParamNil", MODULE_TABLES );
4279 TypeDescToString( td, buf );
4280 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4282 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4284 DisplayEndElement( MODULE_TABLES );
4288 void NativeImageDumper::IterateFileReferencesCallback(TADDR moduleTarget,
4290 PTR_LookupMapBase map,
4293 DisplayStartElement( "Entry", MODULE_TABLES );
4295 PTR_Module module(moduleTarget);
4297 DisplayWriteElementUInt( "Token", rid | mdtFile, MODULE_TABLES );
4299 DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4302 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4303 if( rid == 0 || (module == NULL) )
4305 DisplayWriteElementString( "Name", "mdtFileNil", MODULE_TABLES );
4310 AppendTokenName(mdtFile | rid, buf);
4311 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4313 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4315 DisplayEndElement( MODULE_TABLES );
4316 //m_discoveredFDs.AppendEx(mt);
4320 void NativeImageDumper::IterateManifestModules( TADDR moduleTarget,
4322 PTR_LookupMapBase map,
4325 DisplayStartElement( "Entry", MODULE_TABLES );
4327 moduleTarget = ((FixupPointer<TADDR>&)moduleTarget).GetValue();
4329 PTR_Module module(moduleTarget);
4331 DisplayWriteElementUInt( "Token", rid | mdtAssemblyRef, MODULE_TABLES );
4333 DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4335 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4336 if( rid == 0 || (module == NULL) )
4338 DisplayWriteElementString( "Name", "mdtAssemblyRefNil", MODULE_TABLES );
4343 AppendTokenName(mdtAssemblyRef | rid, buf, m_import);
4344 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4346 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4348 DisplayEndElement( MODULE_TABLES );
4349 //m_discoveredFDs.AppendEx(mt);
4352 void NativeImageDumper::TraverseMap(PTR_LookupMapBase map, const char * name,
4353 unsigned offset, unsigned fieldSize,
4354 void(NativeImageDumper::*cb)(TADDR,
4362 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
4365 DisplayStartVStructure(name, MODULE);
4367 DisplayStartArray( "Tables", W("%s"), MODULE );
4368 PTR_LookupMapBase current = map;
4371 DWORD cbTable = map->MapIsCompressed() ? map->cbTable : map->dwCount * sizeof(*map->pTable);
4375 DisplayWriteElementAddress( "Table",
4376 DPtrToPreferredAddr(map->pTable),
4381 CoverageRead( PTR_TO_TADDR(map->pTable), cbTable );
4382 _ASSERTE(current == map || current->hotItemList == NULL);
4383 current = current->pNext;
4384 }while( current != NULL );
4386 DisplayEndArray( "Total Tables", MODULE ); //Tables
4388 DisplayWriteFieldAddress( hotItemList,
4389 DPtrToPreferredAddr(map->hotItemList),
4390 map->dwNumHotItems * sizeof(*map->hotItemList),
4391 LookupMapBase, MODULE );
4393 DisplayStartArray( "Map", W("[%s]: %s %s%s %s %s %s"), MODULE_TABLES );
4395 IF_OPT_OR3(MODULE_TABLES, EECLASSES, METHODTABLES)
4397 LookupMap<TADDR>::Iterator iter(dac_cast<DPTR(LookupMap<TADDR>)>(map));
4402 TADDR element = iter.GetElementAndFlags(&flags);
4403 (this->*cb)( element, flags, map, rid );
4408 CoverageRead( PTR_TO_TADDR(map->hotItemList),
4409 map->dwNumHotItems * sizeof(*map->hotItemList) );
4410 DisplayEndArray( "Total" , MODULE_TABLES );//Map
4412 DisplayEndVStructure(MODULE); //name
4415 // Templated method containing the core code necessary to traverse hash tables based on NgenHash (see
4417 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4418 void NativeImageDumper::TraverseNgenHash(DPTR(HASH_CLASS) pTable,
4423 void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4429 m_display->WriteFieldPointer(name, offset, fieldSize, NULL);
4434 m_display->StartStructureWithOffset(name, offset, fieldSize,
4435 DPtrToPreferredAddr(pTable),
4436 sizeof(HASH_CLASS));
4439 DisplayWriteFieldPointer(m_pModule,
4440 DPtrToPreferredAddr(pTable->GetModule()),
4441 HASH_CLASS, MODULE);
4443 // Dump warm (volatile) entries.
4444 DisplayWriteFieldUInt(m_cWarmEntries, pTable->m_cWarmEntries, HASH_CLASS, MODULE);
4445 DisplayWriteFieldUInt(m_cWarmBuckets, pTable->m_cWarmBuckets, HASH_CLASS, MODULE);
4446 DisplayWriteFieldAddress(m_pWarmBuckets,
4447 DPtrToPreferredAddr(pTable->GetWarmBuckets()),
4448 sizeof(HASH_ENTRY_CLASS*) * pTable->m_cWarmBuckets,
4449 HASH_CLASS, MODULE);
4451 // Dump hot (persisted) entries.
4452 DPTR(typename HASH_CLASS::PersistedEntries) pHotEntries(PTR_HOST_MEMBER_TADDR(HASH_CLASS, pTable, m_sHotEntries));
4453 DisplayStartStructureWithOffset(m_sHotEntries, DPtrToPreferredAddr(pHotEntries),
4454 sizeof(typename HASH_CLASS::PersistedEntries),
4455 HASH_CLASS, MODULE);
4456 TraverseNgenPersistedEntries<HASH_CLASS, HASH_ENTRY_CLASS>(pTable, pHotEntries, saveClasses, DisplayEntryFunction, pContext);
4457 DisplayEndStructure(MODULE); // Hot entries
4459 // Dump cold (persisted) entries.
4460 DPTR(typename HASH_CLASS::PersistedEntries) pColdEntries(PTR_HOST_MEMBER_TADDR(HASH_CLASS, pTable, m_sColdEntries));
4461 DisplayStartStructureWithOffset(m_sColdEntries, DPtrToPreferredAddr(pColdEntries),
4462 sizeof(typename HASH_CLASS::PersistedEntries),
4463 HASH_CLASS, MODULE);
4464 TraverseNgenPersistedEntries<HASH_CLASS, HASH_ENTRY_CLASS>(pTable, pColdEntries, saveClasses, DisplayEntryFunction, pContext);
4465 DisplayEndStructure(MODULE); // Cold entries
4467 DisplayEndStructure(MODULE); // pTable
4470 // Helper used by TraverseNgenHash above to traverse an ngen persisted section of a table (separated out here
4471 // because NgenHash-based tables can have two such sections, one for hot and one for cold entries).
4472 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4473 void NativeImageDumper::TraverseNgenPersistedEntries(DPTR(HASH_CLASS) pTable,
4474 DPTR(typename HASH_CLASS::PersistedEntries) pEntries,
4476 void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4479 // Display top-level fields.
4480 DisplayWriteFieldUInt(m_cEntries, pEntries->m_cEntries, typename HASH_CLASS::PersistedEntries, MODULE);
4481 DisplayWriteFieldUInt(m_cBuckets, pEntries->m_cBuckets, typename HASH_CLASS::PersistedEntries, MODULE);
4482 DisplayWriteFieldAddress(m_pBuckets,
4483 DPtrToPreferredAddr(pTable->GetPersistedBuckets(pEntries)),
4484 pEntries->m_cBuckets ? pTable->GetPersistedBuckets(pEntries)->GetSize(pEntries->m_cBuckets) : 0,
4485 typename HASH_CLASS::PersistedEntries, MODULE);
4486 DisplayWriteFieldAddress(m_pEntries,
4487 DPtrToPreferredAddr(pTable->GetPersistedEntries(pEntries)),
4488 sizeof(typename HASH_CLASS::PersistedEntry) * pEntries->m_cEntries,
4489 typename HASH_CLASS::PersistedEntries, MODULE);
4491 // Display entries (or maybe just the classes referenced by those entries).
4492 DisplayStartArray("Entries", NULL, SLIM_MODULE_TBLS);
4494 // Enumerate bucket list.
4495 for (DWORD i = 0; i < pEntries->m_cBuckets; ++i)
4497 // Get index of the first entry and the count of entries in the bucket.
4498 DWORD dwEntryId, cEntries;
4499 pTable->GetPersistedBuckets(pEntries)->GetBucket(i, &dwEntryId, &cEntries);
4501 // Loop over entries.
4502 while (cEntries && (CHECK_OPT(SLIM_MODULE_TBLS)
4503 || CHECK_OPT(EECLASSES)
4504 || CHECK_OPT(METHODTABLES)))
4506 // Lookup entry in the array via the index we have.
4507 typename HASH_CLASS::PTR_PersistedEntry pEntry(PTR_TO_TADDR(pTable->GetPersistedEntries(pEntries)) +
4508 (dwEntryId * sizeof(typename HASH_CLASS::PersistedEntry)));
4510 IF_OPT(SLIM_MODULE_TBLS)
4512 DisplayStartStructure("PersistedEntry",
4513 DPtrToPreferredAddr(pEntry),
4514 sizeof(typename HASH_CLASS::PersistedEntry), SLIM_MODULE_TBLS);
4517 // Display entry via a member function specific to the type of hash table we're traversing. Each
4518 // sub-class of NgenHash hash its own entry structure that is embedded NgenHash's entry. The
4519 // helper function expects a pointer to this inner entry.
4520 DPTR(HASH_ENTRY_CLASS) pInnerEntry(PTR_TO_MEMBER_TADDR(typename HASH_CLASS::PersistedEntry, pEntry, m_sValue));
4521 (this->*DisplayEntryFunction)(pContext, pInnerEntry, saveClasses);
4523 IF_OPT(SLIM_MODULE_TBLS)
4525 DisplayWriteFieldUInt(m_iHashValue, pEntry->m_iHashValue,
4526 typename HASH_CLASS::PersistedEntry, SLIM_MODULE_TBLS);
4528 DisplayEndStructure(SLIM_MODULE_TBLS); // Entry
4536 DisplayEndArray("Total Entries", SLIM_MODULE_TBLS); // Entry array
4539 void NativeImageDumper::TraverseClassHashEntry(void *pContext, PTR_EEClassHashEntry pEntry, bool saveClasses)
4541 IF_OPT(SLIM_MODULE_TBLS)
4543 DisplayStartStructure("EEClassHashEntry",
4544 DPtrToPreferredAddr(pEntry),
4545 sizeof(EEClassHashEntry), SLIM_MODULE_TBLS);
4548 size_t datum = size_t(PTR_TO_TADDR(pEntry->GetData()));
4550 if (datum & EECLASSHASH_TYPEHANDLE_DISCR)
4552 IF_OPT(SLIM_MODULE_TBLS)
4554 /* REVISIT_TODO Tue 10/25/2005
4555 * Raw data with annotation?
4558 tk = EEClassHashTable::UncompressModuleAndClassDef(pEntry->GetData());
4559 DoWriteFieldMDToken("Token",
4560 offsetof(EEClassHashEntry, m_Data),
4561 fieldsize(EEClassHashEntry, m_Data),
4567 PTR_MethodTable pMT(TO_TADDR(datum));
4568 IF_OPT(SLIM_MODULE_TBLS)
4570 DoWriteFieldMethodTable("MethodTable",
4571 offsetof(EEClassHashEntry, m_Data),
4572 fieldsize(EEClassHashEntry, m_Data),
4578 // These are MethodTables. Get back to the EEClass from there.
4579 if (isInRange(PTR_TO_TADDR(pMT)))
4580 m_discoveredMTs.AppendEx(pMT);
4583 PTR_EEClass pClass = GetClassFromMT(pMT);
4584 if (isInRange(PTR_TO_TADDR(pClass)))
4585 m_discoveredClasses.AppendEx(pMT);
4590 IF_OPT(SLIM_MODULE_TBLS)
4592 DisplayWriteFieldPointer(m_pEncloser,
4593 DPtrToPreferredAddr(pEntry->GetEncloser()),
4594 EEClassHashEntry, SLIM_MODULE_TBLS);
4595 DisplayEndStructure(SLIM_MODULE_TBLS);
4599 void NativeImageDumper::TraverseClassHash(PTR_EEClassHashTable pTable,
4605 TraverseNgenHash<EEClassHashTable, EEClassHashEntry>(pTable,
4610 &NativeImageDumper::TraverseClassHashEntry,
4614 #ifdef FEATURE_COMINTEROP
4616 void NativeImageDumper::TraverseGuidToMethodTableEntry(void *pContext, PTR_GuidToMethodTableEntry pEntry, bool saveClasses)
4618 IF_OPT(SLIM_MODULE_TBLS)
4620 DisplayStartStructure("GuidToMethodTableEntry",
4621 DPtrToPreferredAddr(pEntry),
4622 sizeof(GuidToMethodTableEntry), SLIM_MODULE_TBLS);
4625 WriteFieldMethodTable(m_pMT, pEntry->m_pMT, GuidToMethodTableEntry, ALWAYS);
4628 GuidToString( *(pEntry->m_Guid), buf );
4629 DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidToMethodTableEntry, ALWAYS );
4631 DisplayEndStructure( SLIM_MODULE_TBLS );
4634 void NativeImageDumper::TraverseGuidToMethodTableHash(PTR_GuidToMethodTableHashTable pTable,
4640 TraverseNgenHash<GuidToMethodTableHashTable, GuidToMethodTableEntry>(pTable,
4645 &NativeImageDumper::TraverseGuidToMethodTableEntry,
4649 #endif // FEATURE_COMINTEROP
4651 void NativeImageDumper::TraverseMemberRefToDescHashEntry(void *pContext, PTR_MemberRefToDescHashEntry pEntry, bool saveClasses)
4653 IF_OPT(SLIM_MODULE_TBLS)
4655 DisplayStartStructure("MemberRefToDescHashEntry",
4656 DPtrToPreferredAddr(pEntry),
4657 sizeof(MemberRefToDescHashEntry), SLIM_MODULE_TBLS);
4660 if(pEntry->m_value & IS_FIELD_MEMBER_REF)
4661 WriteFieldFieldDesc(m_value, dac_cast<PTR_FieldDesc>(pEntry->m_value & (~MEMBER_REF_MAP_ALL_FLAGS)), MemberRefToDescHashEntry, MODULE_TABLES);
4663 WriteFieldMethodDesc(m_value, dac_cast<PTR_MethodDesc>(pEntry->m_value), MemberRefToDescHashEntry, MODULE_TABLES);
4665 DisplayEndStructure( SLIM_MODULE_TBLS );
4668 void NativeImageDumper::TraverseMemberRefToDescHash(PTR_MemberRefToDescHashTable pTable,
4674 TraverseNgenHash<MemberRefToDescHashTable, MemberRefToDescHashEntry>(pTable,
4679 &NativeImageDumper::TraverseMemberRefToDescHashEntry,
4684 void NativeImageDumper::TraverseTypeHashEntry(void *pContext, PTR_EETypeHashEntry pEntry, bool saveClasses)
4686 TypeHandle th = pEntry->GetTypeHandle();
4687 IF_OPT(SLIM_MODULE_TBLS)
4689 DisplayStartStructure("EETypeHashEntry",
4690 DPtrToPreferredAddr(pEntry),
4691 sizeof(EETypeHashEntry), SLIM_MODULE_TBLS);
4693 DoWriteFieldTypeHandle("TypeHandle",
4694 offsetof(EETypeHashEntry, m_data),
4695 fieldsize(EETypeHashEntry, m_data),
4699 if (!CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc())
4701 PTR_TypeDesc td(th.AsTypeDesc());
4702 if (isInRange(PTR_TO_TADDR(td)))
4703 m_discoveredTypeDescs.AppendEx(td);
4704 if (td->HasTypeParam())
4706 PTR_ParamTypeDesc ptd(td);
4708 /* REVISIT_TODO Thu 12/15/2005
4709 * Check OwnsTemplateMethodTable. However, this asserts in
4710 * this special completely unrestored and messed up state
4711 * (also, it chases through MT->GetClass()). There isn't
4712 * all that much harm here (bloats m_discoveredMTs though,
4713 * but not by a huge amount.
4715 PTR_MethodTable mt(ptd->GetTemplateMethodTableInternal());
4716 if (isInRange(PTR_TO_TADDR(mt)))
4718 m_discoveredMTs.AppendEx(mt);
4719 if (mt->IsClassPointerValid())
4721 PTR_EEClass pClass = mt->GetClass();
4722 if (isInRange(PTR_TO_TADDR(pClass)))
4723 m_discoveredClasses.AppendEx(mt);
4730 PTR_MethodTable mt(th.AsTAddr());
4732 if (isInRange( PTR_TO_TADDR(mt)))
4733 m_discoveredMTs.AppendEx(mt);
4734 //don't use GetClassFromMT here. mt->m_pEEClass might be a
4735 //fixup. In that case, just skip it.
4736 if (mt->IsClassPointerValid())
4738 PTR_EEClass pClass = mt->GetClass();
4739 if (isInRange(PTR_TO_TADDR(pClass)))
4740 m_discoveredClasses.AppendEx(mt);
4744 IF_OPT(SLIM_MODULE_TBLS)
4746 DisplayEndStructure(SLIM_MODULE_TBLS);
4750 void NativeImageDumper::TraverseTypeHash(PTR_EETypeHashTable pTable,
4755 TraverseNgenHash<EETypeHashTable, EETypeHashEntry>(pTable,
4760 &NativeImageDumper::TraverseTypeHashEntry,
4764 void NativeImageDumper::TraverseInstMethodHashEntry(void *pContext, PTR_InstMethodHashEntry pEntry, bool saveClasses)
4766 PTR_Module pModule((TADDR)pContext);
4768 IF_OPT(SLIM_MODULE_TBLS)
4770 DisplayStartStructure("InstMethodHashEntry",
4771 DPtrToPreferredAddr(pEntry),
4772 sizeof(InstMethodHashEntry), SLIM_MODULE_TBLS);
4775 IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4779 PTR_MethodDesc md = pEntry->GetMethod();
4780 _ASSERTE(md != NULL);
4782 //if we want methoddescs, write the data field as a
4783 //structure with the whole contents of the method desc.
4784 m_display->StartVStructureWithOffset("data", offsetof(InstMethodHashEntry, data),
4785 sizeof(pEntry->data));
4786 DumpMethodDesc(md, pModule);
4787 DisplayEndVStructure(ALWAYS); //data
4791 PTR_MethodDesc md = pEntry->GetMethod();
4792 WriteFieldMethodDesc(data, md,
4793 InstMethodHashEntry, ALWAYS);
4797 CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4799 IF_OPT(SLIM_MODULE_TBLS)
4801 DisplayEndStructure(SLIM_MODULE_TBLS);
4805 void NativeImageDumper::TraverseStubMethodHashEntry(void *pContext, PTR_StubMethodHashEntry pEntry, bool saveClasses)
4807 PTR_Module pModule((TADDR)pContext);
4809 IF_OPT(SLIM_MODULE_TBLS)
4811 DisplayStartStructure("StubMethodHashEntry",
4812 DPtrToPreferredAddr(pEntry),
4813 sizeof(StubMethodHashEntry), SLIM_MODULE_TBLS);
4816 IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4818 PTR_MethodDesc md = pEntry->GetMethod();
4819 _ASSERTE(md != NULL);
4821 PTR_MethodDesc stub = pEntry->GetStubMethod();
4822 _ASSERTE(stub != NULL);
4826 //if we want methoddescs, write the data fields as a
4827 //structure with the whole contents of the method desc.
4828 m_display->StartVStructureWithOffset("pMD", offsetof(StubMethodHashEntry, pMD),
4829 sizeof(pEntry->pMD));
4830 DumpMethodDesc(md, pModule);
4831 DisplayEndVStructure(ALWAYS); //pMD
4833 m_display->StartVStructureWithOffset("pStubMD", offsetof(StubMethodHashEntry, pStubMD),
4834 sizeof(pEntry->pStubMD));
4835 DumpMethodDesc(stub, pModule);
4836 DisplayEndVStructure(ALWAYS); //pStubMD
4840 WriteFieldMethodDesc(pMD, md,
4841 StubMethodHashEntry, ALWAYS);
4842 WriteFieldMethodDesc(pStubMD, stub,
4843 StubMethodHashEntry, ALWAYS);
4847 CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4849 IF_OPT(SLIM_MODULE_TBLS)
4851 DisplayEndStructure(SLIM_MODULE_TBLS);
4855 void NativeImageDumper::TraverseInstMethodHash(PTR_InstMethodHashTable pTable,
4857 unsigned fieldOffset,
4861 TraverseNgenHash<InstMethodHashTable, InstMethodHashEntry>(pTable,
4866 &NativeImageDumper::TraverseInstMethodHashEntry,
4867 (void*)dac_cast<TADDR>(module));
4870 void NativeImageDumper::TraverseStubMethodHash(PTR_StubMethodHashTable pTable,
4872 unsigned fieldOffset,
4876 TraverseNgenHash<StubMethodHashTable, StubMethodHashEntry>(pTable,
4881 &NativeImageDumper::TraverseStubMethodHashEntry,
4882 (void*)dac_cast<TADDR>(module));
4885 const NativeImageDumper::Dependency *
4886 NativeImageDumper::GetDependencyForModule( PTR_Module module )
4888 for( COUNT_T i = 0; i < m_numDependencies; ++i )
4890 if( m_dependencies[i].pModule == module )
4891 return &m_dependencies[i];
4897 const NativeImageDumper::Import *
4898 NativeImageDumper::GetImportForPointer( TADDR ptr )
4900 for( int i = 0; i < m_numImports; ++i )
4902 const Import * import = &m_imports[i];
4903 if( import->dependency->pPreferredBase == NULL )
4905 if( import->dependency->pPreferredBase <= ptr
4906 && ((import->dependency->pPreferredBase
4907 + import->dependency->size) > ptr) )
4909 //found the right target
4916 const NativeImageDumper::Dependency *
4917 NativeImageDumper::GetDependencyForPointer( TADDR ptr )
4919 for( COUNT_T i = 0; i < m_numDependencies; ++i )
4921 const Dependency * dependency = &m_dependencies[i];
4922 if( dependency->pLoadedAddress == NULL )
4924 if( dependency->pLoadedAddress <= ptr
4925 && ((dependency->pLoadedAddress + dependency->size) > ptr) )
4927 //found the right target
4934 void NativeImageDumper::DictionaryToArgString( PTR_Dictionary dictionary, unsigned numArgs, SString& buf )
4936 //this can be called with numArgs == 0 for value type instantiations.
4937 buf.Append( W("<") );
4939 for( unsigned i = 0; i < numArgs; ++i )
4942 buf.Append( W(",") );
4944 TypeHandle th = dictionary->GetInstantiation()[i].GetValue();
4945 if( CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) )
4947 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(dictionary))))
4949 //this is an RVA from another hardbound dependency. We cannot decode it
4950 buf.Append(W("OUT_OF_MODULE_FIXUP"));
4954 RVA rva = CORCOMPILE_UNTAG_TOKEN(th.AsTAddr());
4955 FixupBlobToString(rva, buf);
4960 TypeHandleToString( th, buf );
4963 buf.Append( W(">") );
4966 void NativeImageDumper::MethodTableToString( PTR_MethodTable mt, SString& buf )
4968 bool hasCompleteExtents = true;
4969 IF_OPT(DISABLE_NAMES)
4971 buf.Append( W("Disabled") );
4974 mdToken token = mdTokenNil;
4976 buf.Append( W("mdTypeDefNil") );
4979 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)));
4980 const Dependency * dependency;
4981 if( !mt->IsClassPointerValid() )
4983 if( isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))) )
4986 hasCompleteExtents = false;
4987 RVA rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
4988 PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
4992 if (kind & ENCODE_MODULE_OVERRIDE)
4994 /* int moduleIndex = */ DacSigUncompressData(sig);
4995 kind &= ~ENCODE_MODULE_OVERRIDE;
4998 _ASSERTE(kind == ENCODE_TYPE_HANDLE);
4999 CorElementType et = DacSigUncompressElementType(sig);
5000 if( et == ELEMENT_TYPE_GENERICINST )
5002 //generic instances have another element type
5003 et = DacSigUncompressElementType(sig);
5005 if (et == ELEMENT_TYPE_VALUETYPE || et == ELEMENT_TYPE_CLASS)
5007 token = DacSigUncompressToken(sig);
5014 dependency = GetDependencyForFixup(rva);
5018 //this is an RVA from another hardbound dependency. We cannot decode it
5019 buf.Append(W("OUT_OF_MODULE_FIXUP"));
5025 token = mt->GetCl();
5026 dependency = GetDependencyFromMT(mt);
5029 if( !isSelf(dependency) )
5031 AppendTokenName( dependency->entry->dwAssemblyRef, buf,
5036 _ASSERTE(dependency->pImport);
5037 if( token == mdtTypeDef )
5038 buf.Append( W("No Token") );
5040 AppendTokenName( token, buf, dependency->pImport );
5042 if( mt->HasPerInstInfo() )
5045 if( hasCompleteExtents )
5047 numDicts = mt->GetNumDicts();
5048 _ASSERTE(numDicts == CountDictionariesInClass(token, dependency->pImport));
5052 numDicts = (DWORD)CountDictionariesInClass(token, dependency->pImport);
5055 TADDR base = dac_cast<TADDR>(&(mt->GetPerInstInfo()[numDicts-1]));
5057 PTR_Dictionary dictionary( MethodTable::PerInstInfoElem_t::GetValueAtPtr(base) );
5058 unsigned numArgs = mt->GetNumGenericArgs();
5060 DictionaryToArgString( dictionary, numArgs, buf );
5065 mdToken NativeImageDumper::ConvertToTypeDef( mdToken typeToken, IMetaDataImport2* (&pImport) )
5067 _ASSERTE( (TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5068 || (TypeFromToken(typeToken) == mdtTypeSpec) );
5069 if( mdtTypeDef == TypeFromToken(typeToken) )
5071 if( mdtTypeRef == TypeFromToken(typeToken) )
5073 //convert the ref to a def.
5075 WCHAR trName[MAX_CLASS_NAME];
5077 IfFailThrow(pImport->GetTypeRefProps(typeToken, &scope, trName, _countof(trName), &trNameLen));
5078 _ASSERTE(trName[trNameLen-1] == 0);
5080 //scope is now a moduleRef or assemblyRef. Find the IMetaData import for that Ref
5081 /* REVISIT_TODO Fri 10/6/2006
5082 * How do I handle moduleRefs?
5084 _ASSERTE(TypeFromToken(scope) == mdtAssemblyRef);
5085 ReleaseHolder<IMetaDataAssemblyImport> pAssemblyImport;
5086 IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
5087 (void **)&pAssemblyImport));
5088 NativeImageDumper::Dependency * dep = GetDependency(scope, pAssemblyImport);
5090 pImport = dep->pImport;
5092 /* REVISIT_TODO Fri 10/6/2006
5093 * Does this work for inner types?
5095 //now I have the correct MetaData. Find the typeDef
5096 HRESULT hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5097 while (hr == CLDB_E_RECORD_NOTFOUND)
5099 // No matching TypeDef, try ExportedType
5100 pAssemblyImport = NULL;
5101 IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
5102 (void **)&pAssemblyImport));
5103 mdExportedType tkExportedType = mdExportedTypeNil;
5104 IfFailThrow(pAssemblyImport->FindExportedTypeByName(trName, mdExportedTypeNil, &tkExportedType));
5105 mdToken tkImplementation;
5106 IfFailThrow(pAssemblyImport->GetExportedTypeProps(tkExportedType, NULL, 0, NULL, &tkImplementation, NULL, NULL));
5107 dep = GetDependency(tkImplementation, pAssemblyImport);
5109 pImport = dep->pImport;
5110 hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5116 PCCOR_SIGNATURE pSig;
5118 IfFailThrow(pImport->GetTypeSpecFromToken(typeToken, &pSig, &cbSig));
5119 //GENERICINST (CLASS|VALUETYPE) typeDefOrRef
5120 CorElementType et = CorSigUncompressElementType(pSig);
5121 _ASSERTE(et == ELEMENT_TYPE_GENERICINST);
5122 et = CorSigUncompressElementType(pSig);
5123 _ASSERTE((et == ELEMENT_TYPE_CLASS) || (et == ELEMENT_TYPE_VALUETYPE));
5124 typeToken = CorSigUncompressToken(pSig);
5127 //we just removed one level of indirection. We still might have a ref or spec.
5128 typeToken = ConvertToTypeDef(typeToken, pImport);
5129 _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5133 SIZE_T NativeImageDumper::CountDictionariesInClass( mdToken typeToken, IMetaDataImport2 * pImport )
5135 SIZE_T myDicts; //either 0 or 1
5137 _ASSERTE((TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5138 || (TypeFromToken(typeToken) == mdtTypeSpec));
5141 //for refs and specs, convert to a def. This is a nop for defs.
5142 typeToken = ConvertToTypeDef(typeToken, pImport);
5144 _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5147 //count the number of generic arguments. If there are any, then we have a dictionary.
5148 HCORENUM hEnum = NULL;
5149 mdGenericParam params[2];
5150 ULONG numParams = 0;
5151 IfFailThrow(pImport->EnumGenericParams(&hEnum, typeToken, params, _countof(params), &numParams));
5152 myDicts = (numParams > 0) ? 1 : 0;
5154 pImport->CloseEnum(hEnum);
5156 //get my parent for the recursive call.
5158 IfFailThrow(pImport->GetTypeDefProps(typeToken, NULL, 0, NULL, NULL, &parent));
5159 return myDicts + (IsNilToken(parent) ? 0 : CountDictionariesInClass(parent, pImport));
5162 const NativeImageDumper::EnumMnemonics s_Subsystems[] =
5164 #define S_ENTRY(f,v) NativeImageDumper::EnumMnemonics(f, 0, v)
5165 S_ENTRY(IMAGE_SUBSYSTEM_UNKNOWN, W("Unknown")),
5166 S_ENTRY(IMAGE_SUBSYSTEM_NATIVE, W("Native")),
5167 S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CUI, W("Windows CUI")),
5168 S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_GUI, W("Windows GUI")),
5169 S_ENTRY(IMAGE_SUBSYSTEM_OS2_CUI, W("OS/2 CUI")),
5170 S_ENTRY(IMAGE_SUBSYSTEM_POSIX_CUI, W("POSIX CUI")),
5171 S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, W("WinCE GUI")),
5172 S_ENTRY(IMAGE_SUBSYSTEM_XBOX, W("XBox"))
5176 const NativeImageDumper::EnumMnemonics s_CorCompileHdrFlags[] =
5178 #define CCHF_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5179 CCHF_ENTRY(CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY),
5180 CCHF_ENTRY(CORCOMPILE_HEADER_IS_IBC_OPTIMIZED),
5181 CCHF_ENTRY(CORCOMPILE_HEADER_IS_READY_TO_RUN),
5185 const NativeImageDumper::EnumMnemonics s_CorPEKind[] =
5187 #define CPEK_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5189 CPEK_ENTRY(peILonly),
5190 CPEK_ENTRY(pe32BitRequired),
5191 CPEK_ENTRY(pe32Plus),
5192 CPEK_ENTRY(pe32Unmanaged),
5193 CPEK_ENTRY(pe32BitPreferred)
5196 const NativeImageDumper::EnumMnemonics s_IFH_Machine[] =
5198 #define IFH_ENTRY(f) NativeImageDumper::EnumMnemonics(f, 0, W(#f))
5199 IFH_ENTRY(IMAGE_FILE_MACHINE_UNKNOWN),
5200 IFH_ENTRY(IMAGE_FILE_MACHINE_I386),
5201 IFH_ENTRY(IMAGE_FILE_MACHINE_AMD64),
5202 IFH_ENTRY(IMAGE_FILE_MACHINE_ARMNT),
5206 const NativeImageDumper::EnumMnemonics s_IFH_Characteristics[] =
5208 #define IFH_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5209 IFH_ENTRY(IMAGE_FILE_RELOCS_STRIPPED),
5210 IFH_ENTRY(IMAGE_FILE_EXECUTABLE_IMAGE),
5211 IFH_ENTRY(IMAGE_FILE_LINE_NUMS_STRIPPED),
5212 IFH_ENTRY(IMAGE_FILE_LOCAL_SYMS_STRIPPED),
5213 IFH_ENTRY(IMAGE_FILE_AGGRESIVE_WS_TRIM),
5214 IFH_ENTRY(IMAGE_FILE_LARGE_ADDRESS_AWARE),
5215 IFH_ENTRY(IMAGE_FILE_BYTES_REVERSED_LO),
5216 IFH_ENTRY(IMAGE_FILE_32BIT_MACHINE),
5217 IFH_ENTRY(IMAGE_FILE_DEBUG_STRIPPED),
5218 IFH_ENTRY(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
5219 IFH_ENTRY(IMAGE_FILE_NET_RUN_FROM_SWAP),
5220 IFH_ENTRY(IMAGE_FILE_SYSTEM),
5221 IFH_ENTRY(IMAGE_FILE_DLL),
5222 IFH_ENTRY(IMAGE_FILE_UP_SYSTEM_ONLY),
5223 IFH_ENTRY(IMAGE_FILE_BYTES_REVERSED_HI),
5227 const NativeImageDumper::EnumMnemonics s_ImportSectionType[] =
5229 #define IST_ENTRY(f) NativeImageDumper::EnumMnemonics(f, 0, W(#f))
5230 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_UNKNOWN),
5231 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD),
5232 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH),
5233 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_STRING_HANDLE),
5234 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE),
5235 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE),
5236 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD),
5240 const NativeImageDumper::EnumMnemonics s_ImportSectionFlags[] =
5242 #define IST_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5243 IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_EAGER),
5244 IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_CODE),
5245 IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_PCODE),
5249 void NativeImageDumper::DumpNativeHeader()
5251 PTR_CORCOMPILE_HEADER nativeHeader(m_decoder.GetNativeHeader());
5256 #define WRITE_NATIVE_FIELD( name ) m_display->WriteFieldAddress(\
5257 # name, offsetof(CORCOMPILE_HEADER, name), \
5258 fieldsize(CORCOMPILE_HEADER, name), \
5259 RvaToDisplay( nativeHeader-> name . VirtualAddress ), \
5260 nativeHeader-> name . Size )
5262 m_display->StartStructure( "CORCOMPILE_HEADER",
5263 DPtrToPreferredAddr(nativeHeader),
5264 sizeof(*nativeHeader) );
5266 DisplayWriteFieldUInt( Signature, nativeHeader->Signature, CORCOMPILE_HEADER, ALWAYS );
5267 DisplayWriteFieldUInt( MajorVersion, nativeHeader->MajorVersion, CORCOMPILE_HEADER, ALWAYS );
5268 DisplayWriteFieldUInt( MinorVersion, nativeHeader->MinorVersion, CORCOMPILE_HEADER, ALWAYS );
5270 WRITE_NATIVE_FIELD(HelperTable);
5272 WRITE_NATIVE_FIELD(ImportSections);
5273 PTR_CORCOMPILE_IMPORT_SECTION pImportSections =
5274 nativeHeader->ImportSections.VirtualAddress
5275 + PTR_TO_TADDR(m_decoder.GetBase());
5276 DisplayStartArray( "ImportSections", NULL, ALWAYS );
5277 for( COUNT_T i = 0; i < nativeHeader->ImportSections.Size
5278 / sizeof(*pImportSections); ++i )
5280 DisplayStartStructure( "CORCOMPILE_IMPORT_SECTION",
5281 DPtrToPreferredAddr(pImportSections + i),
5282 sizeof(pImportSections[i]), ALWAYS );
5283 DisplayWriteElementAddress( "Section",
5284 RvaToDisplay(pImportSections[i].Section.VirtualAddress),
5285 pImportSections[i].Section.Size, ALWAYS );
5287 DisplayWriteFieldEnumerated( Flags, pImportSections[i].Flags,
5288 CORCOMPILE_IMPORT_SECTION, s_ImportSectionFlags, W(", "), ALWAYS );
5289 DisplayWriteFieldEnumerated( Type, pImportSections[i].Type,
5290 CORCOMPILE_IMPORT_SECTION, s_ImportSectionType, W(""), ALWAYS );
5292 DisplayWriteFieldUInt( EntrySize, pImportSections[i].EntrySize,
5293 CORCOMPILE_IMPORT_SECTION, ALWAYS );
5294 DisplayWriteFieldUInt( Signatures, pImportSections[i].Signatures,
5295 CORCOMPILE_IMPORT_SECTION, ALWAYS );
5296 DisplayWriteFieldUInt( AuxiliaryData, pImportSections[i].AuxiliaryData,
5297 CORCOMPILE_IMPORT_SECTION, ALWAYS );
5298 DisplayEndStructure( ALWAYS ); //PTR_CORCOMPILE_IMPORT_SECTION
5301 DisplayEndArray( NULL, ALWAYS ); //delayLoads
5303 WRITE_NATIVE_FIELD(VersionInfo);
5304 WRITE_NATIVE_FIELD(DebugMap);
5305 WRITE_NATIVE_FIELD(ModuleImage);
5306 WRITE_NATIVE_FIELD(CodeManagerTable);
5307 WRITE_NATIVE_FIELD(ProfileDataList);
5308 WRITE_NATIVE_FIELD(ManifestMetaData);
5310 WRITE_NATIVE_FIELD(VirtualSectionsTable);
5311 DisplayStartArray( "VirtualSections", W("%-48s%s"), SLIM_MODULE_TBLS );
5312 PTR_CORCOMPILE_VIRTUAL_SECTION_INFO sects( nativeHeader->VirtualSectionsTable.VirtualAddress + PTR_TO_TADDR(m_decoder.GetBase()) );
5313 COUNT_T numVirtualSections = nativeHeader->VirtualSectionsTable.Size / sizeof (CORCOMPILE_VIRTUAL_SECTION_INFO);
5315 for( COUNT_T i = 0; i < numVirtualSections; ++i )
5317 TempBuffer sectionNameBuf;
5318 TempBuffer sectionFlags;
5319 StackScratchBuffer scratch;
5321 sectionNameBuf.Append(g_sectionNames[VirtualSectionData::VirtualSectionType(sects[i].SectionType)]);
5323 EnumFlagsToString( sects[i].SectionType, s_virtualSectionFlags, dim(s_virtualSectionFlags),
5324 W(" | "), sectionFlags);
5326 sectionNameBuf.Append(W(" ["));
5327 sectionNameBuf.Append(sectionFlags);
5328 sectionNameBuf.Append(W("]"));
5330 DisplayStartElement( "Section", SLIM_MODULE_TBLS );
5331 DisplayWriteElementString("Name", sectionNameBuf.GetANSI(scratch), SLIM_MODULE_TBLS);
5333 DisplayWriteElementAddress( "Address",
5334 RvaToDisplay(sects[i].VirtualAddress),
5337 DisplayEndElement( SLIM_MODULE_TBLS ); //Section
5339 DisplayEndArray( "Total VirtualSections", SLIM_MODULE_TBLS );
5341 WRITE_NATIVE_FIELD(EEInfoTable);
5343 #undef WRITE_NATIVE_FIELD
5344 DisplayWriteFieldEnumerated( Flags, nativeHeader->Flags,
5345 CORCOMPILE_HEADER, s_CorCompileHdrFlags, W(", "),
5348 DisplayWriteFieldEnumerated( PEKind, nativeHeader->PEKind,
5349 CORCOMPILE_HEADER, s_CorPEKind, W(", "),
5352 DisplayWriteFieldEnumerated( COR20Flags, nativeHeader->COR20Flags,
5353 CORCOMPILE_HEADER, s_CorHdrFlags, W(", "),
5356 DisplayWriteFieldEnumerated( Machine, nativeHeader->Machine,
5357 CORCOMPILE_HEADER, s_IFH_Machine,
5358 W(""), NATIVE_INFO );
5359 DisplayWriteFieldEnumerated( Characteristics,
5360 nativeHeader->Characteristics,
5361 CORCOMPILE_HEADER, s_IFH_Characteristics,
5362 W(", "), NATIVE_INFO );
5364 m_display->EndStructure(); //CORCOMPILE_HEADER
5368 const NativeImageDumper::EnumMnemonics s_RelocType[] =
5370 #define REL_ENTRY(x) NativeImageDumper::EnumMnemonics( x, 0, W(#x))
5371 REL_ENTRY(IMAGE_REL_BASED_ABSOLUTE),
5372 REL_ENTRY(IMAGE_REL_BASED_HIGHLOW),
5373 REL_ENTRY(IMAGE_REL_BASED_DIR64),
5374 REL_ENTRY(IMAGE_REL_BASED_THUMB_MOV32),
5378 void NativeImageDumper::DumpBaseRelocs()
5383 data = m_decoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_BASERELOC, &size);
5387 DisplayStartStructure( "Relocations", DataPtrToDisplay(data), size,
5392 IMAGE_BASE_RELOCATION * pBaseRelocation = dac_cast<DPTR(IMAGE_BASE_RELOCATION)>(data);
5393 _ASSERTE(size >= pBaseRelocation->SizeOfBlock);
5395 SIZE_T rel = sizeof(IMAGE_BASE_RELOCATION);
5396 while (rel < pBaseRelocation->SizeOfBlock)
5398 USHORT typeOffset = *PTR_USHORT(data + rel);
5400 DisplayStartElement( "Entry", ALWAYS );
5402 DisplayWriteElementPointer( "Address", RvaToDisplay(pBaseRelocation->VirtualAddress + (typeOffset & 0xFFF)), ALWAYS );
5404 DisplayWriteElementEnumerated( "Type", (typeOffset >> 12),
5405 s_RelocType, W(", "), ALWAYS );
5407 DisplayEndElement( ALWAYS ); //Entry
5409 rel += sizeof(USHORT);
5412 data += pBaseRelocation->SizeOfBlock;
5413 size -= pBaseRelocation->SizeOfBlock;
5416 DisplayEndStructure( ALWAYS ); //Relocations
5420 void NativeImageDumper::DumpHelperTable()
5425 data = TO_TADDR(m_decoder.GetNativeHelperTable(&size));
5428 DisplayStartStructure( "HelperTable", DataPtrToDisplay(data), size,
5431 TADDR curEntry = data;
5432 TADDR tableEnd = data + size;
5434 while (curEntry < tableEnd)
5436 DWORD dwHelper = *PTR_DWORD(curEntry);
5438 int iHelper = (USHORT)dwHelper;
5439 _ASSERTE(iHelper < CORINFO_HELP_COUNT);
5441 DisplayStartStructure( "Helper",
5442 DataPtrToDisplay(curEntry), (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN,
5445 DisplayWriteElementUInt( "dwHelper", dwHelper, ALWAYS );
5446 DisplayWriteElementString( "Name", g_helperNames[iHelper], ALWAYS );
5448 DisplayEndStructure( ALWAYS ); //Helper
5450 curEntry += (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN;
5453 DisplayEndStructure( ALWAYS ); //HelperTable
5457 // TODO: fix these to work with the updated flags in MethodTable, AND to understand
5458 // the new overloading of component size...
5460 NativeImageDumper::EnumMnemonics s_MTFlagsLow[] =
5462 #define MTFLAG_ENTRY(x) \
5463 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5465 MTFLAG_ENTRY(UNUSED_ComponentSize_1),
5466 MTFLAG_ENTRY(StaticsMask),
5467 MTFLAG_ENTRY(StaticsMask_NonDynamic),
5468 MTFLAG_ENTRY(StaticsMask_Dynamic),
5469 MTFLAG_ENTRY(StaticsMask_Generics),
5470 MTFLAG_ENTRY(StaticsMask_CrossModuleGenerics),
5471 MTFLAG_ENTRY(NotInPZM),
5472 MTFLAG_ENTRY(GenericsMask),
5473 MTFLAG_ENTRY(GenericsMask_NonGeneric),
5474 MTFLAG_ENTRY(GenericsMask_GenericInst),
5475 MTFLAG_ENTRY(GenericsMask_SharedInst),
5476 MTFLAG_ENTRY(GenericsMask_TypicalInst),
5477 MTFLAG_ENTRY(HasVariance),
5478 MTFLAG_ENTRY(HasDefaultCtor),
5479 MTFLAG_ENTRY(HasPreciseInitCctors),
5480 #if defined(FEATURE_HFA)
5481 MTFLAG_ENTRY(IsHFA),
5482 #endif // FEATURE_HFA
5483 #if defined(UNIX_AMD64_ABI)
5484 MTFLAG_ENTRY(IsRegStructPassed),
5485 #endif // UNIX_AMD64_ABI
5486 MTFLAG_ENTRY(IsByRefLike),
5487 MTFLAG_ENTRY(UNUSED_ComponentSize_5),
5488 MTFLAG_ENTRY(UNUSED_ComponentSize_6),
5489 MTFLAG_ENTRY(UNUSED_ComponentSize_7),
5493 NativeImageDumper::EnumMnemonics s_MTFlagsHigh[] =
5495 #define MTFLAG_ENTRY(x) \
5496 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5498 #define MTFLAG_CATEGORY_ENTRY(x) \
5499 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_Mask, W("Category_") W(#x))
5501 #define MTFLAG_CATEGORY_ENTRY_WITH_MASK(x, m) \
5502 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_ ## m, W("Category_") W(#x))
5504 MTFLAG_CATEGORY_ENTRY(Class),
5505 MTFLAG_CATEGORY_ENTRY(Unused_1),
5506 MTFLAG_CATEGORY_ENTRY(Unused_2),
5507 MTFLAG_CATEGORY_ENTRY(Unused_3),
5508 MTFLAG_CATEGORY_ENTRY(ValueType),
5509 MTFLAG_CATEGORY_ENTRY(Nullable),
5510 MTFLAG_CATEGORY_ENTRY(PrimitiveValueType),
5511 MTFLAG_CATEGORY_ENTRY(TruePrimitive),
5513 MTFLAG_CATEGORY_ENTRY(Interface),
5514 MTFLAG_CATEGORY_ENTRY(Unused_4),
5515 MTFLAG_CATEGORY_ENTRY(Unused_5),
5516 MTFLAG_CATEGORY_ENTRY(Unused_6),
5518 MTFLAG_CATEGORY_ENTRY_WITH_MASK(Array, Array_Mask),
5519 MTFLAG_CATEGORY_ENTRY_WITH_MASK(IfArrayThenSzArray, IfArrayThenSzArray),
5521 #undef MTFLAG_CATEGORY_ENTRY_WITH_MASK
5522 #undef MTFLAG_CATEGORY_ENTRY
5524 MTFLAG_ENTRY(HasFinalizer),
5525 MTFLAG_ENTRY(IfNotInterfaceThenMarshalable),
5526 #if defined(FEATURE_COMINTEROP)
5527 MTFLAG_ENTRY(IfInterfaceThenHasGuidInfo),
5529 #if defined(FEATURE_ICASTABLE)
5530 MTFLAG_ENTRY(ICastable),
5532 MTFLAG_ENTRY(HasIndirectParent),
5533 MTFLAG_ENTRY(ContainsPointers),
5534 MTFLAG_ENTRY(HasTypeEquivalence),
5535 #if defined(FEATURE_COMINTEROP)
5536 MTFLAG_ENTRY(HasRCWPerTypeData),
5538 MTFLAG_ENTRY(HasCriticalFinalizer),
5539 MTFLAG_ENTRY(Collectible),
5540 MTFLAG_ENTRY(ContainsGenericVariables),
5541 #if defined(FEATURE_COMINTEROP)
5542 MTFLAG_ENTRY(ComObject),
5544 MTFLAG_ENTRY(HasComponentSize),
5549 NativeImageDumper::EnumMnemonics s_MTFlags2[] =
5551 #define MTFLAG2_ENTRY(x) \
5552 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5553 MTFLAG2_ENTRY(HasPerInstInfo),
5554 MTFLAG2_ENTRY(HasInterfaceMap),
5555 MTFLAG2_ENTRY(HasDispatchMapSlot),
5556 MTFLAG2_ENTRY(HasNonVirtualSlots),
5557 MTFLAG2_ENTRY(HasModuleOverride),
5558 MTFLAG2_ENTRY(IsZapped),
5559 MTFLAG2_ENTRY(IsPreRestored),
5560 MTFLAG2_ENTRY(HasModuleDependencies),
5561 MTFLAG2_ENTRY(IsIntrinsicType),
5562 MTFLAG2_ENTRY(RequiresDispatchTokenFat),
5563 MTFLAG2_ENTRY(HasCctor),
5564 MTFLAG2_ENTRY(HasCCWTemplate),
5565 #ifdef FEATURE_64BIT_ALIGNMENT
5566 MTFLAG2_ENTRY(RequiresAlign8),
5568 MTFLAG2_ENTRY(HasBoxedRegularStatics),
5569 MTFLAG2_ENTRY(HasSingleNonVirtualSlot),
5570 MTFLAG2_ENTRY(DependsOnEquivalentOrForwardedStructs),
5571 #undef MTFLAG2_ENTRY
5574 NativeImageDumper::EnumMnemonics s_WriteableMTFlags[] =
5576 #define WMTFLAG_ENTRY(x) \
5577 NativeImageDumper::EnumMnemonics(MethodTableWriteableData::enum_flag_ ## x,\
5580 WMTFLAG_ENTRY(Unrestored),
5581 WMTFLAG_ENTRY(HasApproxParent),
5582 WMTFLAG_ENTRY(UnrestoredTypeKey),
5583 WMTFLAG_ENTRY(IsNotFullyLoaded),
5584 WMTFLAG_ENTRY(DependenciesLoaded),
5587 WMTFLAG_ENTRY(ParentMethodTablePointerValid),
5590 WMTFLAG_ENTRY(NGEN_IsFixedUp),
5591 WMTFLAG_ENTRY(NGEN_IsNeedsRestoreCached),
5592 WMTFLAG_ENTRY(NGEN_CachedNeedsRestore),
5593 #undef WMTFLAG_ENTRY
5596 static NativeImageDumper::EnumMnemonics s_CorElementType[] =
5598 #define CET_ENTRY(x) NativeImageDumper::EnumMnemonics(ELEMENT_TYPE_ ## x, 0, W("ELEMENT_TYPE_") W(#x))
5616 CET_ENTRY(VALUETYPE),
5620 CET_ENTRY(GENERICINST),
5621 CET_ENTRY(TYPEDBYREF),
5622 CET_ENTRY(VALUEARRAY_UNSUPPORTED),
5625 CET_ENTRY(R_UNSUPPORTED),
5630 CET_ENTRY(CMOD_REQD),
5631 CET_ENTRY(CMOD_OPT),
5632 CET_ENTRY(INTERNAL),
5634 CET_ENTRY(SENTINEL),
5639 void NativeImageDumper::DoWriteFieldCorElementType( const char * name,
5642 CorElementType type )
5645 EnumFlagsToString( (int)type, s_CorElementType, dim(s_CorElementType),
5647 m_display->WriteFieldEnumerated( name, offset, fieldSize, (unsigned)type,
5648 (const WCHAR *) buf );
5652 static NativeImageDumper::EnumMnemonics s_CorTypeAttr[] =
5654 #define CTA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5656 #define CTA_VISIBILITY_ENTRY(x) NativeImageDumper::EnumMnemonics( x, tdVisibilityMask, W(#x) )
5657 CTA_VISIBILITY_ENTRY(tdNotPublic),
5658 CTA_VISIBILITY_ENTRY(tdPublic),
5659 CTA_VISIBILITY_ENTRY(tdNestedPublic),
5660 CTA_VISIBILITY_ENTRY(tdNestedPrivate),
5661 CTA_VISIBILITY_ENTRY(tdNestedFamily),
5662 CTA_VISIBILITY_ENTRY(tdNestedAssembly),
5663 CTA_VISIBILITY_ENTRY(tdNestedFamANDAssem),
5664 CTA_VISIBILITY_ENTRY(tdNestedFamORAssem),
5665 #undef CTA_VISIBILITY_ENTRY
5667 CTA_ENTRY(tdSequentialLayout),
5668 CTA_ENTRY(tdExplicitLayout),
5670 CTA_ENTRY(tdInterface),
5672 CTA_ENTRY(tdAbstract),
5673 CTA_ENTRY(tdSealed),
5674 CTA_ENTRY(tdSpecialName),
5676 CTA_ENTRY(tdImport),
5677 CTA_ENTRY(tdSerializable),
5679 CTA_ENTRY(tdUnicodeClass),
5680 CTA_ENTRY(tdAutoClass),
5681 CTA_ENTRY(tdCustomFormatClass),
5682 CTA_ENTRY(tdCustomFormatMask),
5684 CTA_ENTRY(tdBeforeFieldInit),
5685 CTA_ENTRY(tdForwarder),
5687 CTA_ENTRY(tdRTSpecialName),
5688 CTA_ENTRY(tdHasSecurity)
5691 static NativeImageDumper::EnumMnemonics s_VMFlags[] =
5693 #define VMF_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClass::VMFLAG_ ## x, W(#x) )
5695 #ifdef FEATURE_READYTORUN
5696 VMF_ENTRY(LAYOUT_DEPENDS_ON_OTHER_MODULES),
5698 VMF_ENTRY(DELEGATE),
5699 VMF_ENTRY(FIXED_ADDRESS_VT_STATICS),
5700 VMF_ENTRY(HASLAYOUT),
5701 VMF_ENTRY(ISNESTED),
5702 VMF_ENTRY(IS_EQUIVALENT_TYPE),
5704 VMF_ENTRY(HASOVERLAYEDFIELDS),
5705 VMF_ENTRY(HAS_FIELDS_WHICH_MUST_BE_INITED),
5706 VMF_ENTRY(UNSAFEVALUETYPE),
5708 VMF_ENTRY(BESTFITMAPPING_INITED),
5709 VMF_ENTRY(BESTFITMAPPING),
5710 VMF_ENTRY(THROWONUNMAPPABLECHAR),
5713 VMF_ENTRY(HASNONPUBLICFIELDS),
5714 VMF_ENTRY(PREFER_ALIGN8),
5716 #ifdef FEATURE_COMINTEROP
5717 VMF_ENTRY(SPARSE_FOR_COMINTEROP),
5718 VMF_ENTRY(HASCOCLASSATTRIB),
5719 VMF_ENTRY(COMEVENTITFMASK),
5720 VMF_ENTRY(PROJECTED_FROM_WINRT),
5721 VMF_ENTRY(EXPORTED_TO_WINRT),
5722 #endif // FEATURE_COMINTEROP
5724 VMF_ENTRY(NOT_TIGHTLY_PACKED),
5725 VMF_ENTRY(CONTAINS_METHODIMPLS),
5726 #ifdef FEATURE_COMINTEROP
5727 VMF_ENTRY(MARSHALINGTYPE_MASK),
5728 VMF_ENTRY(MARSHALINGTYPE_INHIBIT),
5729 VMF_ENTRY(MARSHALINGTYPE_FREETHREADED),
5730 VMF_ENTRY(MARSHALINGTYPE_STANDARD),
5734 static NativeImageDumper::EnumMnemonics s_CorFieldAttr[] =
5736 #define CFA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5738 #define CFA_ACCESS_ENTRY(x) NativeImageDumper::EnumMnemonics( x, fdFieldAccessMask, W(#x) )
5739 CFA_ENTRY(fdPrivateScope),
5740 CFA_ENTRY(fdPrivate),
5741 CFA_ENTRY(fdFamANDAssem),
5742 CFA_ENTRY(fdAssembly),
5743 CFA_ENTRY(fdFamily),
5744 CFA_ENTRY(fdFamORAssem),
5745 CFA_ENTRY(fdPublic),
5746 #undef CFA_ACCESS_ENTRY
5748 CFA_ENTRY(fdStatic),
5749 CFA_ENTRY(fdInitOnly),
5750 CFA_ENTRY(fdLiteral),
5751 CFA_ENTRY(fdNotSerialized),
5753 CFA_ENTRY(fdSpecialName),
5755 CFA_ENTRY(fdPinvokeImpl),
5757 CFA_ENTRY(fdRTSpecialName),
5758 CFA_ENTRY(fdHasFieldMarshal),
5759 CFA_ENTRY(fdHasDefault),
5760 CFA_ENTRY(fdHasFieldRVA),
5764 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDFlag2[] =
5766 #define MDF2_ENTRY(x) NativeImageDumper::EnumMnemonics( MethodDesc::enum_flag2_ ## x, W("enum_flag2_") W(#x) )
5767 MDF2_ENTRY(HasStableEntryPoint),
5768 MDF2_ENTRY(HasPrecode),
5769 MDF2_ENTRY(IsUnboxingStub),
5770 MDF2_ENTRY(HasNativeCodeSlot),
5774 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDC[] =
5776 #define MDC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5778 #define MDC_ENTRY_CLASSIFICATION(x) NativeImageDumper::EnumMnemonics( x, mdcClassification, W(#x) )
5779 MDC_ENTRY_CLASSIFICATION(mcIL),
5780 MDC_ENTRY_CLASSIFICATION(mcFCall),
5781 MDC_ENTRY_CLASSIFICATION(mcNDirect),
5782 MDC_ENTRY_CLASSIFICATION(mcEEImpl),
5783 MDC_ENTRY_CLASSIFICATION(mcArray),
5784 MDC_ENTRY_CLASSIFICATION(mcInstantiated),
5785 #ifdef FEATURE_COMINTEROP
5786 MDC_ENTRY_CLASSIFICATION(mcComInterop),
5787 #endif // FEATURE_COMINTEROP
5788 MDC_ENTRY_CLASSIFICATION(mcDynamic),
5789 #undef MDC_ENTRY_CLASSIFICATION
5791 MDC_ENTRY(mdcHasNonVtableSlot),
5792 MDC_ENTRY(mdcMethodImpl),
5795 MDC_ENTRY(mdcStatic),
5797 MDC_ENTRY(mdcDuplicate),
5798 MDC_ENTRY(mdcVerifiedState),
5799 MDC_ENTRY(mdcVerifiable),
5800 MDC_ENTRY(mdcNotInline),
5801 MDC_ENTRY(mdcSynchronized),
5802 MDC_ENTRY(mdcRequiresFullSlotNumber),
5808 void NativeImageDumper::DumpTypes(PTR_Module module)
5810 _ASSERTE(CHECK_OPT(EECLASSES) || CHECK_OPT(METHODTABLES)
5811 || CHECK_OPT(TYPEDESCS));
5813 IF_OPT_OR3(METHODTABLES, EECLASSES, TYPEDESCS)
5814 m_display->StartCategory( "Types" );
5815 IF_OPT(METHODTABLES)
5817 //there may be duplicates in the list. Remove them before moving on.
5818 COUNT_T mtCount = m_discoveredMTs.GetCount();
5820 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5821 std::sort(&*m_discoveredMTs.Begin(),
5822 (&*m_discoveredMTs.Begin())
5823 + (m_discoveredMTs.End() - m_discoveredMTs.Begin()));
5824 PTR_MethodTable* newEnd = std::unique(&*m_discoveredMTs.Begin(),
5825 (&*m_discoveredMTs.Begin())
5826 + (m_discoveredMTs.End()
5827 - m_discoveredMTs.Begin()));
5828 mtCount = (COUNT_T)(newEnd - &*m_discoveredMTs.Begin());
5831 DisplayStartArray( "MethodTables", NULL, METHODTABLES );
5832 for(COUNT_T i = 0; i < mtCount; ++i )
5834 PTR_MethodTable mt = m_discoveredMTs[i];
5837 DumpMethodTable( mt, "MethodTable", module );
5840 DisplayEndArray( "Total MethodTables", METHODTABLES );
5842 DisplayStartArray( "MethodTableSlotChunks", NULL, METHODTABLES );
5844 COUNT_T slotChunkCount = m_discoveredSlotChunks.GetCount();
5845 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5846 std::sort(&*m_discoveredSlotChunks.Begin(),
5847 (&*m_discoveredSlotChunks.Begin())
5848 + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin()));
5849 SlotChunk *newEndChunks = std::unique(&*m_discoveredSlotChunks.Begin(),
5850 (&*m_discoveredSlotChunks.Begin())
5851 + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin()));
5852 slotChunkCount = (COUNT_T)(newEndChunks - &*m_discoveredSlotChunks.Begin());
5855 for (COUNT_T i = 0; i < slotChunkCount; ++i)
5857 DumpMethodTableSlotChunk(m_discoveredSlotChunks[i].addr,
5858 m_discoveredSlotChunks[i].nSlots,
5859 m_discoveredSlotChunks[i].isRelative);
5862 DisplayEndArray( "Total MethodTableSlotChunks", METHODTABLES );
5866 DisplayStartArray( "EEClasses", NULL, EECLASSES );
5868 //there may be duplicates in the list. Remove them before moving on.
5869 COUNT_T clazzCount = m_discoveredClasses.GetCount();
5870 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5871 std::sort(&*m_discoveredClasses.Begin(),
5872 (&*m_discoveredClasses.Begin())
5873 + (m_discoveredClasses.End() - m_discoveredClasses.Begin()));
5874 PTR_MethodTable * newEndClazz = std::unique(&*m_discoveredClasses.Begin(),
5875 (&*m_discoveredClasses.Begin())
5876 +(m_discoveredClasses.End()
5877 -m_discoveredClasses.Begin()));
5878 clazzCount = (COUNT_T)(newEndClazz - &*m_discoveredClasses.Begin());
5881 for(COUNT_T i = 0; i < clazzCount; ++i )
5883 PTR_MethodTable mt = m_discoveredClasses[i];
5886 DumpEEClassForMethodTable( mt );
5889 DisplayEndArray( "Total EEClasses", EECLASSES ); //EEClasses
5894 DisplayStartArray( "TypeDescs", NULL, TYPEDESCS );
5896 //there may be duplicates in the list. Remove them before moving on.
5897 COUNT_T tdCount = m_discoveredTypeDescs.GetCount();
5898 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5899 std::sort(&*m_discoveredTypeDescs.Begin(),
5900 (&*m_discoveredTypeDescs.Begin())
5901 + (m_discoveredTypeDescs.End()
5902 - m_discoveredTypeDescs.Begin()));
5903 PTR_TypeDesc* newEndTD = std::unique(&*m_discoveredTypeDescs.Begin(),
5904 (&*m_discoveredTypeDescs.Begin())
5905 +(m_discoveredTypeDescs.End()
5906 -m_discoveredTypeDescs.Begin()));
5907 tdCount = (COUNT_T)(newEndTD - &*m_discoveredTypeDescs.Begin());
5910 for(COUNT_T i = 0; i < tdCount; ++i )
5912 PTR_TypeDesc td = m_discoveredTypeDescs[i];
5918 DisplayEndArray( "Total TypeDescs", TYPEDESCS ); //EEClasses
5921 IF_OPT_OR3(EECLASSES, METHODTABLES, TYPEDESCS)
5922 m_display->EndCategory(); //Types
5925 PTR_EEClass NativeImageDumper::GetClassFromMT( PTR_MethodTable mt )
5927 /* REVISIT_TODO Tue 10/11/2005
5930 _ASSERTE( mt->IsClassPointerValid() );
5931 PTR_EEClass clazz( mt->GetClass() );
5934 PTR_MethodTable NativeImageDumper::GetParent( PTR_MethodTable mt )
5936 /* REVISIT_TODO Thu 12/01/2005
5939 PTR_MethodTable parent( ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent()) );
5940 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(parent)));
5944 //Counts the FieldDescs in a class. This is all of the non-static and static
5945 //non-literal fields.
5946 SIZE_T NativeImageDumper::CountFields( PTR_MethodTable mt )
5948 SIZE_T fieldCount = 0;
5950 HCORENUM hEnum = NULL;
5952 const Dependency * dep = GetDependencyFromMT(mt);
5953 mdToken classToken = mt->GetCl();
5956 _ASSERTE(dep->pImport);
5958 //Arrays have no token.
5959 if( RidFromToken(classToken) == 0 )
5967 IfFailThrow(dep->pImport->EnumFields( &hEnum, classToken, fields,
5974 IfFailThrow(dep->pImport->GetFieldProps( fields[0], NULL, NULL, 0,
5975 NULL, & dwAttr, NULL, NULL,
5976 NULL, NULL, NULL ) );
5977 if( !IsFdStatic(dwAttr) || !IsFdLiteral(dwAttr) )
5980 dep->pImport->CloseEnum(hEnum);
5983 const NativeImageDumper::Dependency*
5984 NativeImageDumper::GetDependencyFromMT( PTR_MethodTable mt )
5986 if( !mt->IsClassPointerValid() )
5988 //This code will not work for out of module dependencies.
5989 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))));
5991 //the EEClass is a fixup. The home for that fixup tells us the
5992 //home for the metadata.
5993 unsigned rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
5994 return GetDependencyForFixup(rva);
5996 PTR_Module module = mt->GetModule();
5997 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
5999 unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
6000 return GetDependencyForFixup(rva);
6002 return GetDependencyForModule(module);
6004 const NativeImageDumper::Dependency*
6005 NativeImageDumper::GetDependencyFromFD( PTR_FieldDesc fd )
6007 PTR_MethodTable mt = fd->GetApproxEnclosingMethodTable();
6008 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6010 //This code will not work for out of module dependencies.
6011 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(fd))));
6013 //the MethodTable has a fixup. The home for that fixup tells us the
6014 //home for the metadata.
6015 unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6016 return GetDependencyForFixup(rva);
6018 return GetDependencyFromMT(mt);
6020 const NativeImageDumper::Dependency*
6021 NativeImageDumper::GetDependencyFromMD( PTR_MethodDesc md )
6023 PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
6024 PTR_MethodTable mt = chunk->GetMethodTable();
6025 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6027 //This code will not work for out of module dependencies.
6028 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6030 //the MethodTable has a fixup. The home for that fixup tells us the
6031 //home for the metadata.
6032 unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6033 return GetDependencyForFixup(rva);
6035 return GetDependencyFromMT(mt);
6038 BOOL NativeImageDumper::DoWriteFieldAsFixup( const char * name,
6040 unsigned fieldSize, TADDR fixup)
6042 if( !CORCOMPILE_IS_POINTER_TAGGED(fixup) )
6044 if( UINT_MAX == offset )
6045 m_display->StartVStructure( name );
6047 m_display->StartVStructureWithOffset( name, offset, fieldSize );
6049 WriteElementsFixupBlob( NULL, fixup );
6050 m_display->EndVStructure(); //name
6054 void AppendTypeQualifier( CorElementType kind, DWORD rank, SString& buf )
6058 case ELEMENT_TYPE_BYREF :
6059 buf.Append( W("&") );
6061 case ELEMENT_TYPE_PTR :
6062 buf.Append( W("*") );
6064 case ELEMENT_TYPE_SZARRAY :
6065 buf.Append( W("[]") );
6067 case ELEMENT_TYPE_ARRAY :
6070 buf.Append( W("[*]") );
6074 buf.Append( W("[") );
6075 for( COUNT_T i = 0; i < rank; ++i )
6076 buf.Append( W(","));
6077 buf.Append( W("]") );
6084 void NativeImageDumper::TypeDescToString( PTR_TypeDesc td, SString& buf )
6086 _ASSERTE(!(PTR_TO_TADDR(td) & 0x2));
6087 if( td->IsGenericVariable() )
6089 PTR_TypeVarTypeDesc tvtd( PTR_TO_TADDR(td) );
6090 //From code:TypeString::AppendType
6091 mdGenericParam token = tvtd->GetToken();
6092 PTR_Module module(tvtd->GetModule());
6093 IMetaDataImport2 * pImport;
6094 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
6096 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(td))))
6098 //this is an RVA from another hardbound dependency. We cannot decode it
6099 buf.Append(W("OUT_OF_MODULE_FIXUP"));
6104 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
6105 pImport = GetDependencyForFixup(rva)->pImport;
6110 pImport = GetDependencyForModule(module)->pImport;
6112 AppendTokenName(token, buf, pImport);
6114 else if( ELEMENT_TYPE_FNPTR == td->GetInternalCorElementType() )
6116 PTR_FnPtrTypeDesc fptd( PTR_TO_TADDR(td) );
6117 buf.Append( W("(fnptr)") );
6119 else if( td->HasTypeParam() || td->IsArray() )
6121 //either a Parameter or an Array.
6122 PTR_ParamTypeDesc ptd(PTR_TO_TADDR(td));
6123 TypeHandle elemType;
6124 /* REVISIT_TODO Thu 10/5/2006
6125 * Do I need to find a rank somewhere in the TypeDesc?
6130 //td->HasTypeParam() may also be true.
6131 PTR_MethodTable mt = ptd->GetTemplateMethodTableInternal();
6132 _ASSERTE( PTR_TO_TADDR(mt) );
6133 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6135 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(ptd))))
6137 //this is an RVA from another hardbound dependency. We cannot decode it
6138 buf.Append(W("OUT_OF_MODULE_FIXUP"));
6142 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6143 FixupBlobToString(rva, buf);
6149 _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) );
6150 MethodTableToString( mt, buf );
6151 rank = PTR_ArrayTypeDesc(PTR_TO_TADDR(ptd))->GetRank();
6156 _ASSERTE(td->HasTypeParam());
6157 TypeHandle th(ptd->GetTypeParam());
6158 _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) );
6159 _ASSERTE( th.AsTAddr() );
6160 TypeHandleToString(th, buf);
6163 AppendTypeQualifier( td->GetInternalCorElementType(), rank, buf );
6168 EnumFlagsToString( (int)td->GetInternalCorElementType(), s_CorElementType, dim(s_CorElementType),
6172 void NativeImageDumper::TypeHandleToString( TypeHandle th, SString& buf )
6174 TADDR arg = th.AsTAddr();
6175 /* REVISIT_TODO Thu 10/5/2006
6176 * Is this constant somewhere?
6178 //0x2 is the subtle hint that this is a typedesc. code:TypeHandle::AsTypeDesc
6181 PTR_TypeDesc argTD( arg & ~0x2 );
6182 TypeDescToString( argTD, buf );
6186 PTR_MethodTable argMT( th.AsTAddr() );
6187 MethodTableToString( argMT, buf );
6191 void NativeImageDumper::DoWriteFieldTypeHandle( const char * name,
6197 TADDR ptr = th.AsTAddr();
6198 if( DoWriteFieldAsFixup(name, offset, fieldSize, th.AsTAddr() ) )
6202 TypeHandleToString(th, buf);
6204 buf.Append( W(" (from TypeHandle)") );
6205 /* REVISIT_TODO Fri 10/14/2005
6206 * Do a better job of this
6208 if( offset == UINT_MAX )
6210 m_display->WriteElementPointerAnnotated( name,
6211 DataPtrToDisplay(ptr),
6212 (const WCHAR*) buf );
6216 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6217 DataPtrToDisplay(ptr),
6218 (const WCHAR*) buf );
6222 void NativeImageDumper::WriteElementTypeHandle( const char * name,
6225 DoWriteFieldTypeHandle( name, UINT_MAX, UINT_MAX, th );
6228 void NativeImageDumper::DoDumpFieldStub( PTR_Stub stub, unsigned offset,
6229 unsigned fieldSize, const char * name )
6231 _ASSERTE(CHECK_OPT(EECLASSES));
6234 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6238 m_display->StartStructureWithOffset( name, offset, fieldSize,
6239 DPtrToPreferredAddr(stub),
6241 /* REVISIT_TODO Fri 10/14/2005
6244 m_display->EndStructure();
6248 #ifdef FEATURE_COMINTEROP
6249 void NativeImageDumper::DoDumpComPlusCallInfo( PTR_ComPlusCallInfo compluscall )
6251 m_display->StartStructure( "ComPlusCallInfo",
6252 DPtrToPreferredAddr(compluscall),
6253 sizeof(*compluscall) );
6255 DisplayWriteFieldPointer( m_pILStub, compluscall->m_pILStub,
6256 ComPlusCallInfo, ALWAYS);
6257 /* REVISIT_TODO Fri 12/16/2005
6258 * Coverage read stub?
6260 WriteFieldMethodTable(m_pInterfaceMT,
6261 compluscall->m_pInterfaceMT,
6262 ComPlusCallInfo, ALWAYS);
6264 PTR_MethodDesc pEventProviderMD = PTR_MethodDesc((TADDR)compluscall->m_pEventProviderMD);
6265 WriteFieldMethodDesc(m_pEventProviderMD,
6267 ComPlusCallInfo, ALWAYS);
6268 DisplayWriteFieldInt( m_cachedComSlot, compluscall->m_cachedComSlot,
6269 ComPlusCallInfo, ALWAYS );
6271 /* REVISIT_TODO Fri 12/16/2005
6272 * Dump these as mnemonics
6274 DisplayWriteFieldInt( m_flags, compluscall->m_flags,
6275 ComPlusCallInfo, ALWAYS );
6276 WriteFieldMethodDesc( m_pStubMD,
6277 compluscall->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(ComPlusCallInfo, compluscall, m_pStubMD)),
6278 ComPlusCallInfo, ALWAYS );
6281 DisplayWriteFieldInt( m_cbStackArgumentSize, compluscall->m_cbStackArgumentSize,
6282 ComPlusCallInfo, ALWAYS );
6284 DisplayWriteFieldPointer( m_pRetThunk,
6285 DataPtrToDisplay((TADDR)compluscall->m_pRetThunk),
6286 ComPlusCallInfo, ALWAYS );
6288 m_display->EndStructure(); //ComPlusCallInfo
6290 #endif // FEATURE_COMINTEROP
6292 void NativeImageDumper::DoWriteFieldStr( PTR_BYTE ptr, const char * name,
6293 unsigned offset, unsigned fieldSize )
6297 if( UINT_MAX == offset )
6298 m_display->WriteElementPointer( name, NULL );
6300 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6304 /* REVISIT_TODO Wed 03/22/2006
6305 * Obviously this does the wrong thing for UTF-8.
6309 TADDR taddr = DPtrToPreferredAddr(ptr);
6310 PTR_BYTE current = ptr;
6311 /* REVISIT_TODO Mon 03/27/2006
6312 * Actually handle UTF-8 properly
6314 while( (b = *current++) != 0 )
6315 buf.Append( (WCHAR)b );
6316 /* REVISIT_TODO Wed 03/22/2006
6317 * This seems way way way more verbose than it needs to be.
6319 if( UINT_MAX == offset )
6321 m_display->StartStructure( name, DataPtrToDisplay(taddr),
6326 m_display->StartStructureWithOffset( name, offset, fieldSize,
6327 DataPtrToDisplay(taddr),
6330 DisplayWriteElementStringW( "Value", (const WCHAR *)buf, ALWAYS );
6331 m_display->EndStructure();
6333 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6334 taddr, (const WCHAR *)buf );
6338 void NativeImageDumper::WriteFieldDictionaryLayout(const char * name,
6341 PTR_DictionaryLayout layout,
6342 IMetaDataImport2 * import)
6344 if( layout == NULL )
6346 m_display->WriteFieldPointer(name, NULL, offset, fieldSize);
6349 m_display->StartVStructureWithOffset( name, offset, fieldSize );
6350 DisplayStartArray( "DictionaryLayouts", NULL, ALWAYS );
6353 DisplayStartStructure( "DictionaryLayout", DPtrToPreferredAddr(layout),
6354 sizeof(DictionaryLayout)
6355 + sizeof(DictionaryEntryLayout)
6356 * (layout->m_numSlots - 1), ALWAYS );
6359 DisplayWriteFieldPointer( m_pNext, DataPtrToDisplay((TADDR)layout->m_pNext),
6360 DictionaryLayout, ALWAYS );
6361 DisplayWriteFieldInt( m_numSlots, layout->m_numSlots,
6362 DictionaryLayout, ALWAYS );
6363 DisplayStartArrayWithOffset( m_slots, NULL, DictionaryLayout, ALWAYS );
6364 for( unsigned i = 0; i < layout->m_numSlots; ++i )
6366 PTR_DictionaryEntryLayout entry( PTR_HOST_MEMBER_TADDR(DictionaryLayout, layout, m_slots) + (i * sizeof(DictionaryEntryLayout)) );
6367 DisplayStartStructure( "DictionaryEntryLayout",
6368 DPtrToPreferredAddr(entry), sizeof(*entry),
6370 const char * kind = NULL;
6371 switch( entry->GetKind() )
6373 #define KIND_ENTRY(x) case x : kind = # x ; break
6374 KIND_ENTRY(EmptySlot);
6375 KIND_ENTRY(TypeHandleSlot);
6376 KIND_ENTRY(MethodDescSlot);
6377 KIND_ENTRY(MethodEntrySlot);
6378 KIND_ENTRY(ConstrainedMethodEntrySlot);
6379 KIND_ENTRY(DispatchStubAddrSlot);
6380 KIND_ENTRY(FieldDescSlot);
6383 _ASSERTE( !"unreachable" );
6385 DisplayWriteElementString( "Kind", kind, ALWAYS );
6386 DisplayWriteElementPointer( "Signature", DPtrToPreferredAddr(entry->m_signature), ALWAYS );
6387 DisplayEndStructure( ALWAYS ); //DictionaryEntryLayout
6389 DisplayEndArray( "Total Dictionary Entries", ALWAYS ); //m_slots
6390 DisplayEndStructure( ALWAYS ); //Layout
6391 layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
6392 }while( layout != NULL );
6393 DisplayEndArray( "Total Dictionary Layouts", ALWAYS ); //DictionaryLayouts
6396 DisplayEndVStructure( ALWAYS ); // name
6398 void NativeImageDumper::DoWriteFieldFieldDesc( const char * name,
6405 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6410 FieldDescToString( fd, buf );
6411 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6412 DPtrToPreferredAddr(fd),
6413 (const WCHAR*) buf );
6417 void NativeImageDumper::DoWriteFieldMethodDesc( const char * name,
6424 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6426 else if( DoWriteFieldAsFixup(name, offset, fieldSize, PTR_TO_TADDR(md)) )
6433 MethodDescToString( md, buf );
6434 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6435 DPtrToPreferredAddr(md),
6436 (const WCHAR*) buf );
6440 void NativeImageDumper::EntryPointToString( TADDR pEntryPoint,
6443 const Dependency * dependency = GetDependencyForPointer(pEntryPoint);
6446 if (dependency->pModule->IsZappedPrecode(pEntryPoint))
6448 md = dac_cast<PTR_MethodDesc>(Precode::GetPrecodeFromEntryPoint(pEntryPoint)->GetMethodDesc());
6452 PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
6453 PTR_NGenLayoutInfo pNgenLayout = module->GetNGenLayoutInfo();
6454 DWORD rva = (DWORD)(pEntryPoint - PTR_TO_TADDR(m_decoder.GetBase()));
6456 for (int iRange = 0; iRange < 2; iRange++)
6458 if (pNgenLayout->m_CodeSections[iRange].IsInRange(pEntryPoint))
6460 int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1);
6461 if (MethodIndex >= 0)
6463 #ifdef WIN64EXCEPTIONS
6464 while (pNgenLayout->m_MethodDescs[iRange][MethodIndex] == 0)
6468 PTR_RUNTIME_FUNCTION pRuntimeFunction = pNgenLayout->m_pRuntimeFunctions[iRange] + MethodIndex;
6470 md = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase()));
6477 MethodDescToString(md, buf);
6480 void NativeImageDumper::MethodDescToString( PTR_MethodDesc md,
6484 buf.Append( W("mdMethodDefNil") );
6485 else if( md->IsILStub() )
6486 buf.AppendUTF8(md->AsDynamicMethodDesc()->GetName());
6489 //write the name to a temporary location, since I'm going to insert it
6490 //into the middle of a signature.
6491 TempBuffer tempName;
6493 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(md)));
6494 //work back to the EEClass. That gives us the context for the token.
6495 PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
6496 //chunk is implicitly remapped because it's calculated from the pointer
6498 PTR_MethodTable mt = chunk->GetMethodTable();
6499 const Dependency * dependency;
6500 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6502 //This code will not work for out of module dependencies.
6503 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6505 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6506 dependency = GetDependencyForFixup(rva);
6507 mt = NULL; //make sure we don't use this for anything.
6510 dependency = GetDependencyFromMT(mt);
6512 _ASSERTE(dependency);
6515 /* REVISIT_TODO Fri 10/13/2006
6516 * Don't I need the array type name here?
6518 _ASSERTE(dependency->pImport);
6519 if( md->GetClassification() == mcArray )
6522 //We don't need to append the dependency all the time.
6523 //MethodTableToString() already appends it to the MethodTable.
6524 //Only do it in cases where we don't call MethodTableToString.
6525 if( !isSelf(dependency) )
6527 AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6529 tempName.Append(W("!"));
6532 _ASSERTE(PTR_TO_TADDR(mt));
6533 MethodTableToString( mt, tempName );
6534 tempName.Append( W("::") );
6536 //there are four hard coded names for array method descs, use these
6537 //instead of the token.
6538 PTR_ArrayMethodDesc amd(PTR_TO_TADDR(md));
6539 tempName.AppendUTF8( amd->GetMethodName() );
6543 //if we have a MethodTable, use that and compose the name
6544 //ourselves. That way we can get generic arguments.
6548 MethodTableToString( mt, tempName );
6549 tempName.Append( W("::") );
6550 IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(), NULL, bigBuffer,
6551 bigBufferSize, &size, NULL, NULL, NULL, NULL,
6553 tempName.Append(bigBuffer);
6557 //We don't need to append the dependency all the time.
6558 //MethodTableToString() already appends it to the MethodTable.
6559 //Only do it in cases where we don't call MethodTableToString.
6560 if( !isSelf(dependency) )
6562 AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6564 tempName.Append(W("!"));
6566 AppendTokenName( md->GetMemberDef(), tempName, dependency->pImport );
6569 if( mcInstantiated == md->GetClassification() )
6571 PTR_InstantiatedMethodDesc imd(PTR_TO_TADDR(md));
6572 unsigned numArgs = imd->m_wNumGenericArgs;
6573 PTR_Dictionary dict(imd->IMD_GetMethodDictionary());
6576 DictionaryToArgString( dict, numArgs, tempName );
6580 PCCOR_SIGNATURE pvSigBlob;
6582 IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(),
6594 CQuickBytes prettySig;
6595 ReleaseHolder<IMDInternalImport> pInternal;
6596 IfFailThrow(GetMDInternalInterfaceFromPublic(dependency->pImport, IID_IMDInternalImport,
6597 (void**)&pInternal));
6598 StackScratchBuffer buffer;
6599 const ANSI * ansi = tempName.GetANSI(buffer);
6600 ansi = PrettyPrintSig(pvSigBlob, cbSigBlob, ansi, &prettySig, pInternal, NULL);
6601 tempName.SetANSI( ansi );
6603 buf.Append(tempName);
6606 void NativeImageDumper::WriteElementMethodDesc( const char * name,
6611 m_display->WriteElementPointer( name, NULL );
6616 MethodDescToString( md, buf );
6617 m_display->WriteElementPointerAnnotated( name, DPtrToPreferredAddr(md),
6618 (const WCHAR*) buf );
6621 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, SString& buf )
6623 FieldDescToString( fd, mdFieldDefNil, buf );
6625 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, mdFieldDef tok,
6628 IF_OPT(DISABLE_NAMES)
6630 buf.Append( W("Disabled") );
6635 if( tok == mdFieldDefNil )
6636 buf.Append( W("mdFieldDefNil") );
6638 AppendTokenName( tok, buf );
6642 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(fd)));
6643 IMetaDataImport2 * importMD = NULL;
6644 if( !isInRange(PTR_TO_TADDR(fd)) )
6646 const Dependency * dependency = GetDependencyFromFD(fd);
6647 _ASSERTE(dependency);
6648 AppendTokenName( dependency->entry->dwAssemblyRef, buf,
6651 importMD = dependency->pImport;
6657 importMD = m_import;
6659 AppendTokenName( fd->GetMemberDef(), buf, importMD );
6663 void NativeImageDumper::DoWriteFieldAsHex( const char * name, unsigned offset,
6664 unsigned fieldSize, PTR_BYTE ptr,
6668 for( unsigned i = 0; i < dataLen; ++i )
6670 unsigned char b = ptr[i];
6671 buffer.AppendPrintf( W("%02x%02x"), (b & 0xf0) >> 4, b & 0xf );
6673 if( offset == UINT_MAX )
6675 m_display->WriteElementStringW( name, (const WCHAR *)buffer );
6679 m_display->WriteFieldStringW( name, offset, fieldSize,
6680 (const WCHAR *)buffer );
6683 void NativeImageDumper::WriteElementMDToken( const char * name, mdToken token )
6685 DoWriteFieldMDToken( name, UINT_MAX, UINT_MAX, token );
6687 void NativeImageDumper::DoWriteFieldMDToken( const char * name, unsigned offset,
6688 unsigned fieldSize, mdToken token,
6689 IMetaDataImport2 * import )
6692 if( RidFromToken(token) == mdTokenNil )
6694 AppendNilToken( token, buf );
6698 AppendToken( token, buf, import );
6700 if( UINT_MAX == offset )
6701 m_display->WriteElementEnumerated( name, token, (const WCHAR *)buf );
6704 m_display->WriteFieldEnumerated(name, offset, fieldSize, token,
6709 void NativeImageDumper::WriteElementMethodTable( const char * name,
6710 PTR_MethodTable mt )
6712 DoWriteFieldMethodTable( name, UINT_MAX, UINT_MAX, mt );
6714 void NativeImageDumper::DoWriteFieldMethodTable( const char * name,
6717 PTR_MethodTable mt )
6721 if( UINT_MAX == offset )
6722 m_display->WriteElementPointer( name, NULL );
6724 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6726 else if( DoWriteFieldAsFixup( name, offset, fieldSize, PTR_TO_TADDR(mt) ) )
6733 MethodTableToString( mt, buf );
6734 if( UINT_MAX == offset )
6737 m_display->WriteElementPointerAnnotated( name,
6738 DPtrToPreferredAddr(mt),
6739 (const WCHAR*) buf );
6743 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6744 DPtrToPreferredAddr(mt),
6745 (const WCHAR*) buf );
6750 const char * s_VTSCallbackNames[] =
6752 #define VTSCB_ENTRY(x) # x
6753 VTSCB_ENTRY(VTS_CALLBACK_ON_SERIALIZING),
6754 VTSCB_ENTRY(VTS_CALLBACK_ON_SERIALIZED),
6755 VTSCB_ENTRY(VTS_CALLBACK_ON_DESERIALIZING),
6756 VTSCB_ENTRY(VTS_CALLBACK_ON_DESERIALIZED),
6759 void NativeImageDumper::DumpFieldDesc( PTR_FieldDesc fd, const char * name )
6761 DisplayStartStructure( name, DPtrToPreferredAddr(fd), sizeof(*fd),
6763 WriteFieldMethodTable( m_pMTOfEnclosingClass,
6764 fd->GetApproxEnclosingMethodTable(), FieldDesc, ALWAYS );
6765 m_display->WriteFieldUInt( "m_mb", offsetof(FieldDesc, m_dword1),
6766 fieldsize(FieldDesc, m_dword1),
6767 fd->GetMemberDef() );
6768 m_display->WriteFieldFlag( "m_isStatic",
6769 offsetof(FieldDesc, m_dword1),
6770 fieldsize(FieldDesc, m_dword1),
6772 m_display->WriteFieldFlag( "m_isThreadLocal",
6773 offsetof(FieldDesc, m_dword1),
6774 fieldsize(FieldDesc, m_dword1),
6775 fd->m_isThreadLocal );
6776 m_display->WriteFieldFlag( "m_isRVA", offsetof(FieldDesc, m_dword1),
6777 fieldsize(FieldDesc, m_dword1),
6782 EnumFlagsToString( fd->m_prot, s_CorFieldAttr,
6783 _countof(s_CorFieldAttr), W(" "), buf );
6784 m_display->WriteFieldEnumerated( "m_prot",
6785 offsetof(FieldDesc, m_dword1),
6786 fieldsize(FieldDesc, m_dword1),
6787 fd->m_prot, (const WCHAR *)buf );
6789 m_display->WriteFieldFlag( "m_requiresFullMbValue",
6790 offsetof(FieldDesc, m_dword1),
6791 fieldsize(FieldDesc, m_dword1),
6792 fd->m_requiresFullMbValue );
6793 m_display->WriteFieldInt( "m_dwOffset",
6794 offsetof(FieldDesc, m_dword2),
6795 fieldsize(FieldDesc, m_dword2),
6797 DoWriteFieldCorElementType( "m_type",
6798 offsetof(FieldDesc, m_dword2),
6799 fieldsize(FieldDesc, m_dword2),
6800 (CorElementType)fd->m_type );
6802 WriteFieldStr( m_debugName, PTR_BYTE(TO_TADDR(fd->m_debugName)),
6803 FieldDesc, ALWAYS );
6805 DisplayEndStructure( ALWAYS ); //name
6809 #pragma warning(push)
6810 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
6813 NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name,
6816 _ASSERTE(NULL != mt);
6818 bool haveCompleteExtents = true;
6819 PTR_EEClass clazz = NULL;
6820 if( !mt->IsCanonicalMethodTable() && CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt->GetCanonicalMethodTable())) )
6822 /* REVISIT_TODO Wed 02/01/2006
6823 * GetExtent requires the class in order to compute GetInstAndDictSize.
6824 * If the EEClass isn't present, I cannot compute the size. If we are
6825 * in this case, skip all of the generic dictionaries.
6827 haveCompleteExtents = false;
6829 MethodTableToString( mt, buf );
6830 m_display->ErrorPrintF( "WARNING! MethodTable %S is generic but is not hard bound to its EEClass. Cannot compute generic dictionary sizes.\n", (const WCHAR *)buf );
6832 else if( !m_isMscorlibHardBound )
6834 /* REVISIT_TODO Mon 8/20/2007
6835 * If we're not hard bound to mscorlib, most things don't work. They depend on knowing what
6836 * g_pObjectClass is. Without the hard binding to mscorlib, I can't figure that out.
6838 haveCompleteExtents = false;
6840 if( haveCompleteExtents )
6842 mt->GetSavedExtent(&start, &end);
6843 clazz = mt->GetClass();
6847 start = PTR_TO_TADDR(mt);
6848 end = start + sizeof(*mt);
6850 IF_OPT(METHODTABLES)
6852 m_display->StartStructureWithNegSpace( name, DPtrToPreferredAddr(mt),
6853 DataPtrToDisplay(start), end - start );
6856 IF_OPT(METHODTABLES)
6860 MethodTableToString( mt, buf );
6861 DisplayWriteElementStringW( "Name", (const WCHAR *)buf, ALWAYS );
6863 if( mt->ContainsPointers() )
6865 PTR_CGCDesc cgc = CGCDesc::GetCGCDescFromMT(mt);
6866 unsigned size = (unsigned)cgc->GetSize();
6867 /* REVISIT_TODO Tue 12/13/2005
6868 * Does anyone actually care about what's inside here?
6870 m_display->WriteFieldEmpty( "CGCDesc", ~size + 1, size );
6874 /* XXX Mon 10/24/2005
6875 * The MT might have a component size as the low WORD of the m_dwFlags
6876 * field, if it doesn't then that field instead represents a number of
6877 * flags, which we know as the "low flags"
6879 if (mt->HasComponentSize())
6881 DisplayWriteElementInt( "ComponentSize", mt->RawGetComponentSize(),
6886 DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & 0xFFFF, MethodTable,
6887 s_MTFlagsLow, W(", "), METHODTABLES );
6890 /* XXX Fri 10/07/2005
6891 * The low WORD of the flags is used for either a component size or flags
6892 * (see above), the high WORD is always flags. If this changes then this
6895 DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & ~0xFFFF, MethodTable,
6896 s_MTFlagsHigh, W(", "), METHODTABLES );
6898 DisplayWriteFieldInt( m_BaseSize, mt->m_BaseSize, MethodTable,
6901 DisplayWriteFieldEnumerated( m_wFlags2, mt->m_wFlags2, MethodTable,
6902 s_MTFlags2, W(", "), METHODTABLES );
6904 DisplayWriteFieldInt( m_wToken, mt->m_wToken, MethodTable,
6906 DisplayWriteFieldInt( m_wNumVirtuals, mt->m_wNumVirtuals, MethodTable,
6908 DisplayWriteFieldInt( m_wNumInterfaces, mt->m_wNumInterfaces, MethodTable,
6913 PTR_MethodTable parent = ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent());
6914 if( parent == NULL )
6916 DisplayWriteFieldPointer( m_pParentMethodTable, NULL, MethodTable,
6921 IF_OPT(METHODTABLES)
6923 DoWriteFieldMethodTable( "m_pParentMethodTable",
6924 offsetof(MethodTable, m_pParentMethodTable),
6925 fieldsize(MethodTable, m_pParentMethodTable),
6926 mt->GetParentMethodTable() );
6929 DisplayWriteFieldPointer( m_pLoaderModule,
6930 DPtrToPreferredAddr(mt->GetLoaderModule()),
6931 MethodTable, METHODTABLES );
6933 PTR_MethodTableWriteableData wd = ReadPointer((MethodTable *)mt, &MethodTable::m_pWriteableData);
6934 _ASSERTE(wd != NULL);
6935 DisplayStartStructureWithOffset( m_pWriteableData, DPtrToPreferredAddr(wd),
6936 sizeof(*wd), MethodTable, METHODTABLES );
6937 DisplayWriteFieldEnumerated( m_dwFlags, wd->m_dwFlags,
6938 MethodTableWriteableData, s_WriteableMTFlags,
6939 W(", "), METHODTABLES );
6940 DisplayWriteFieldPointer( m_hExposedClassObject,
6941 DataPtrToDisplay(wd->m_hExposedClassObject),
6942 MethodTableWriteableData, METHODTABLES );
6943 _ASSERTE(wd->m_hExposedClassObject == 0);
6944 DisplayEndStructure( METHODTABLES ); //m_pWriteableData
6946 if( !mt->IsCanonicalMethodTable() )
6948 WriteFieldMethodTable( m_pCanonMT, mt->GetCanonicalMethodTable(),
6949 MethodTable, METHODTABLES );
6953 DisplayWriteFieldPointer( m_pEEClass, DPtrToPreferredAddr(mt->GetClass()),
6954 MethodTable, METHODTABLES );
6959 WriteFieldTypeHandle( m_ElementTypeHnd,
6960 mt->GetApproxArrayElementTypeHandle(),
6961 MethodTable, METHODTABLES );
6964 if( mt->HasPerInstInfo() && haveCompleteExtents )
6966 //print out the generics dictionary info, and then print out
6967 //the contents of those dictionaries.
6968 PTR_GenericsDictInfo di = mt->GetGenericsDictInfo();
6969 _ASSERTE(NULL != di);
6971 DisplayStartStructure("GenericsDictInfo", DPtrToPreferredAddr(di), sizeof(*di), METHODTABLES);
6973 DisplayWriteFieldInt( m_wNumDicts, di->m_wNumDicts, GenericsDictInfo,
6975 DisplayWriteFieldInt( m_wNumTyPars, di->m_wNumTyPars,
6976 GenericsDictInfo, METHODTABLES);
6977 DisplayEndStructure( METHODTABLES ); //GenericsDictInfo
6979 DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo();
6981 DisplayStartStructure( "PerInstInfo",
6982 DPtrToPreferredAddr(perInstInfo),
6983 mt->GetPerInstInfoSize(),
6985 /* XXX Tue 10/11/2005
6986 * Only dump this type's dictionary, rather than the inherited
6987 * dictionaries. (there are multiple entries in m_pPerInstInfo, but
6988 * only print the last one, which is the one for this class).
6989 * cloned from Genericdict.cpp
6991 PTR_Dictionary currentDictionary(mt->GetDictionary());
6992 if( currentDictionary != NULL )
6994 PTR_DictionaryEntry entry(currentDictionary->EntryAddr(0));
6996 PTR_DictionaryLayout layout( clazz->GetDictionaryLayout() );
6998 DisplayStartStructure( "Dictionary",
6999 DPtrToPreferredAddr(currentDictionary),
7000 //if there is a layout, use it to compute
7001 //the size, otherwise there is just the one
7003 DictionaryLayout::GetFirstDictionaryBucketSize(mt->GetNumGenericArgs(), layout),
7006 DisplayStartArrayWithOffset( m_pEntries, NULL, Dictionary,
7009 /* REVISIT_TODO Thu 12/15/2005
7010 * use VERBOSE_TYPES here.
7012 _ASSERTE(CHECK_OPT(METHODTABLES));
7014 //for each generic arg, there is a type handle slot
7015 for( unsigned i = 0; i < mt->GetNumGenericArgs(); ++i )
7016 DumpDictionaryEntry("Entry", TypeHandleSlot, entry + i);
7018 //now check for a layout. If it is present, then there are more
7020 if( layout != NULL && (layout->GetNumUsedSlots() > 0) )
7022 unsigned numUsedSlots = layout->GetNumUsedSlots();
7023 for( unsigned i = 0; i < numUsedSlots; ++i )
7025 //DictionaryLayout::GetEntryLayout
7026 PTR_DictionaryEntryLayout entryLayout(layout->GetEntryLayout(i));
7028 //Dictionary::GetSlotAddr
7029 PTR_DictionaryEntry ent(currentDictionary->EntryAddr(mt->GetNumGenericArgs() + i));
7031 DumpDictionaryEntry( "Entry", entryLayout->GetKind(), ent );
7034 if( layout != NULL )
7036 /* REVISIT_TODO Thu 12/15/2005
7037 * Where is this data?
7040 DisplayEndArray( "Total Per instance Info",
7041 METHODTABLES ); //m_pEntries
7042 DisplayEndStructure( METHODTABLES ); //Dictionary
7044 DisplayEndStructure( METHODTABLES ); //m_pPerInstInfo
7048 WriteFieldStr( debug_m_szClassName,
7049 PTR_BYTE(TO_TADDR(mt->debug_m_szClassName)), MethodTable,
7051 #if 0 //already dumping the optional member
7052 PTR_InterfaceInfo imap( TO_TADDR(mt->m_pIMapDEBUG) );
7053 /* REVISIT_TODO Mon 10/24/2005
7054 * Dump interface map
7056 DisplayStartArrayWithOffset( m_pIMapDEBUG, NULL, MethodTable,
7058 DisplayEndArray( "Total Interfaces", METHODTABLES );
7062 if( mt->HasDispatchMapSlot() )
7064 PTR_DispatchMap dispatchMap(mt->GetDispatchMap());
7066 DisplayStartStructure( "DispatchMap",
7067 DPtrToPreferredAddr(dispatchMap),
7068 DispatchMap::GetObjectSize(dispatchMap->GetMapSize()),
7071 IF_OPT(VERBOSE_TYPES )
7073 DispatchMap::Iterator iter(mt);
7074 DisplayStartArray( "DispatchMap", NULL, VERBOSE_TYPES );
7075 while( iter.Next() )
7077 DispatchMapEntry * ent = iter.Entry();
7079 DisplayStartElement( "Entry", METHODTABLES );
7080 DisplayStartVStructure( "TypeID", METHODTABLES );
7081 DispatchMapTypeID typeID = ent->GetTypeID();
7082 if( typeID.IsThisClass() )
7083 DisplayWriteElementFlag("IsThisClass", true, METHODTABLES );
7084 else if( typeID.IsImplementedInterface() )
7086 DisplayWriteElementFlag( "IsImplementedInterface",
7087 true, METHODTABLES );
7088 DisplayWriteElementInt( "GetInterfaceNum",
7089 typeID.GetInterfaceNum(), METHODTABLES );
7091 DisplayEndStructure( METHODTABLES ); //TypeID
7092 m_display->WriteElementInt( "SlotNumber",
7093 ent->GetSlotNumber() );
7094 DisplayWriteElementInt( "TargetSlotNumber",
7095 ent->GetSlotNumber(), METHODTABLES );
7097 m_display->EndElement(); //Entry
7100 DisplayEndArray("Total Dispatch Map Entries", METHODTABLES );
7104 CoverageRead(PTR_TO_TADDR(dispatchMap),
7105 DispatchMap::GetObjectSize(dispatchMap->GetMapSize()));
7108 DisplayEndStructure( METHODTABLES ); //DispatchMap
7111 IF_OPT( METHODTABLES )
7113 m_display->StartStructureWithOffset("Vtable",
7114 mt->GetVtableOffset(),
7115 mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t),
7116 DataPtrToDisplay(PTR_TO_TADDR(mt) + mt->GetVtableOffset()),
7117 mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t));
7120 MethodTable::VtableIndirectionSlotIterator itIndirect = mt->IterateVtableIndirectionSlots();
7121 while (itIndirect.Next())
7124 sc.addr = dac_cast<TADDR>(itIndirect.GetIndirectionSlot());
7125 sc.nSlots = (WORD)itIndirect.GetNumSlots();
7126 sc.isRelative = MethodTable::VTableIndir2_t::isRelative;
7127 m_discoveredSlotChunks.AppendEx(sc);
7130 IF_OPT(VERBOSE_TYPES)
7132 DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7133 for( unsigned i = 0; i < mt->GetNumVtableIndirections(); ++i )
7135 DisplayStartElement( "Slot", ALWAYS );
7136 DisplayWriteElementInt( "Index", i, ALWAYS );
7137 TADDR base = dac_cast<TADDR>(&(mt->GetVtableIndirections()[i]));
7138 DPTR(MethodTable::VTableIndir2_t) tgt = MethodTable::VTableIndir_t::GetValueMaybeNullAtPtr(base);
7139 DisplayWriteElementPointer( "Pointer",
7140 DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7142 DisplayWriteElementString( "Type", "chunk indirection",
7144 DisplayEndElement( ALWAYS ); //Slot
7147 if (mt->HasNonVirtualSlotsArray())
7149 DisplayStartElement( "Slot", ALWAYS );
7150 DisplayWriteElementInt( "Index", -1, ALWAYS );
7151 PTR_PCODE tgt = mt->GetNonVirtualSlotsArray();
7152 DisplayWriteElementPointer( "Pointer",
7153 DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7155 DisplayWriteElementString( "Type", "non-virtual chunk indirection",
7157 DisplayEndElement( ALWAYS ); //Slot
7160 sc.addr = dac_cast<TADDR>(tgt);
7161 sc.nSlots = (mt->GetNumVtableSlots() - mt->GetNumVirtuals());
7162 sc.isRelative = false;
7163 m_discoveredSlotChunks.AppendEx(sc);
7165 else if (mt->HasSingleNonVirtualSlot())
7167 DumpSlot((unsigned)-1, mt->GetSlot(mt->GetNumVirtuals()));
7170 DisplayEndList( ALWAYS ); //vtable
7174 CoverageRead( PTR_TO_TADDR(mt) + mt->GetVtableOffset(),
7175 mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t) );
7177 if (mt->HasNonVirtualSlotsArray())
7179 CoverageRead( PTR_TO_TADDR(mt->GetNonVirtualSlotsArray()),
7180 mt->GetNonVirtualSlotsArraySize() );
7184 DisplayEndStructure(ALWAYS); //Vtable
7187 if( mt->HasInterfaceMap() && CHECK_OPT(METHODTABLES) )
7189 PTR_InterfaceInfo ifMap = mt->GetInterfaceMap();
7190 m_display->StartArrayWithOffset( "InterfaceMap",
7191 offsetof(MethodTable, m_pInterfaceMap),
7194 for( unsigned i = 0; i < mt->GetNumInterfaces(); ++i )
7196 PTR_InterfaceInfo info = ifMap + i;
7197 DisplayStartStructure( "InterfaceInfo_t", DPtrToPreferredAddr(info),
7198 sizeof(*info), METHODTABLES );
7199 WriteFieldMethodTable( m_pMethodTable,
7200 info->GetMethodTable(),
7201 InterfaceInfo_t, METHODTABLES );
7202 DisplayEndStructure( METHODTABLES ); //InterfaceInfo_t
7204 DisplayEndArray( "Total InterfaceInfos",
7205 METHODTABLES ); //InterfaceMap
7208 //rest of the optional members
7210 //GenericStatics comes after the generic dictionaries. So if I
7211 //don't have extents, I can't print them.
7212 if( haveCompleteExtents &&
7213 mt->HasGenericsStaticsInfo() &&
7214 CHECK_OPT(METHODTABLES)
7217 PTR_GenericsStaticsInfo genStatics = mt->GetGenericsStaticsInfo();
7218 m_display->StartStructureWithOffset( "OptionalMember_"
7219 "GenericsStaticsInfo",
7220 mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GenericsStaticsInfo),
7221 sizeof(*genStatics),
7222 DPtrToPreferredAddr(genStatics),
7223 sizeof(*genStatics) );
7225 PTR_FieldDesc fieldDescs = ReadPointerMaybeNull((GenericsStaticsInfo *) genStatics, &GenericsStaticsInfo::m_pFieldDescs);
7226 if( fieldDescs == NULL )
7228 DisplayWriteFieldPointer( m_pFieldDescs, NULL, GenericsStaticsInfo,
7233 DisplayStartArrayWithOffset( m_pFieldDescs, NULL,
7234 GenericsStaticsInfo, ALWAYS );
7235 _ASSERTE(clazz == GetClassFromMT(mt));
7236 for( int i = 0; i < clazz->GetNumStaticFields(); ++i )
7238 PTR_FieldDesc fd = fieldDescs + i;
7239 DumpFieldDesc( fd, "FieldDesc" );
7241 DisplayEndArray( "Total Static Fields", ALWAYS ); // m_pFieldDescs
7243 DisplayWriteFieldUInt( m_DynamicTypeID, (DWORD)genStatics->m_DynamicTypeID,
7244 GenericsStaticsInfo, METHODTABLES );
7246 DisplayEndStructure( METHODTABLES );//OptionalMember_GenericsStaticsInfo
7250 #ifdef FEATURE_COMINTEROP
7251 if (haveCompleteExtents &&
7252 mt->HasGuidInfo() &&
7253 CHECK_OPT(METHODTABLES)
7256 PTR_GuidInfo guidInfo(*mt->GetGuidInfoPtr());
7258 if (guidInfo != NULL)
7260 m_display->StartStructureWithOffset( "OptionalMember_GuidInfo",
7261 mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GuidInfo),
7263 DPtrToPreferredAddr(guidInfo),
7267 GuidToString( guidInfo->m_Guid, buf );
7268 DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
7270 DisplayWriteFieldFlag( m_bGeneratedFromName,
7271 guidInfo->m_bGeneratedFromName,
7273 DisplayEndStructure( ALWAYS ); // OptionalMember_GuidInfo
7277 if (haveCompleteExtents &&
7278 mt->HasCCWTemplate()
7279 && CHECK_OPT(METHODTABLES)
7282 PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(*mt->GetCCWTemplatePtr()));
7283 m_display->WriteFieldPointer( "OptionalMember_CCWTemplate",
7284 mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_CCWTemplate),
7286 DPtrToPreferredAddr(ccwTemplate)
7289 #endif // FEATURE_COMINTEROP
7291 DisplayEndStructure( METHODTABLES ); //MethodTable
7292 } // NativeImageDumper::DumpMethodTable
7294 #pragma warning(pop)
7298 NativeImageDumper::DumpMethodTableSlotChunk( TADDR slotChunk, COUNT_T numSlots, bool isRelative )
7300 IF_OPT( METHODTABLES )
7305 slotsSize = numSlots * sizeof(RelativePointer<PCODE>);
7309 slotsSize = numSlots * sizeof(PCODE);
7311 DisplayStartStructure( "MethodTableSlotChunk", DataPtrToDisplay(slotChunk), slotsSize, METHODTABLES );
7313 IF_OPT(VERBOSE_TYPES)
7315 DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7316 for( unsigned i = 0; i < numSlots; ++i )
7321 target = RelativePointer<PCODE>::GetValueMaybeNullAtPtr(slotChunk + i * sizeof(RelativePointer<PCODE>));
7325 target = dac_cast<PTR_PCODE>(slotChunk)[i];
7328 DumpSlot(i, target);
7330 DisplayEndList( ALWAYS ); //Slot list
7333 CoverageRead( slotChunk, slotsSize );
7334 DisplayEndStructure(ALWAYS); //Slot chunk
7340 NativeImageDumper::DumpSlot( unsigned index, PCODE tgt )
7342 IF_OPT(VERBOSE_TYPES)
7344 DisplayStartElement( "Slot", ALWAYS );
7345 DisplayWriteElementInt( "Index", index, ALWAYS );
7346 DisplayWriteElementPointer( "Pointer",
7347 DataPtrToDisplay(tgt),
7349 if( !isInRange(TO_TADDR(tgt)) )
7351 DisplayWriteElementString( "Type", "external",
7354 else if( isPrecode(TO_TADDR(tgt))
7355 && Precode::IsValidType(PTR_Precode(TO_TADDR(tgt))->GetType()) )
7357 PTR_Precode precode(TO_TADDR(tgt));
7358 DisplayWriteElementString( "Type", "precode",
7360 //DumpPrecode( precode, module );
7364 DisplayWriteElementString( "Type", "code pointer",
7367 DisplayEndElement( ALWAYS ); //Slot
7371 NativeImageDumper::EnumMnemonics NativeImageDumper::s_SSMDExtendedFlags[] =
7373 #define SSMD_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
7375 #define SSMD_ACCESS_ENTRY(x) NativeImageDumper::EnumMnemonics( x, mdMemberAccessMask, W(#x) )
7376 SSMD_ACCESS_ENTRY(mdPrivateScope),
7377 SSMD_ACCESS_ENTRY(mdPrivate),
7378 SSMD_ACCESS_ENTRY(mdFamANDAssem),
7379 SSMD_ACCESS_ENTRY(mdAssem),
7380 SSMD_ACCESS_ENTRY(mdFamily),
7381 SSMD_ACCESS_ENTRY(mdFamORAssem),
7382 SSMD_ACCESS_ENTRY(mdPublic),
7383 #undef SSMD_ACCESS_ENTRY
7385 SSMD_ENTRY(mdStatic),
7386 SSMD_ENTRY(mdFinal),
7387 SSMD_ENTRY(mdVirtual),
7388 SSMD_ENTRY(mdHideBySig),
7390 SSMD_ENTRY(mdVtableLayoutMask),
7391 SSMD_ENTRY(mdNewSlot),
7393 SSMD_ENTRY(mdCheckAccessOnOverride),
7394 SSMD_ENTRY(mdAbstract),
7395 SSMD_ENTRY(mdSpecialName),
7397 SSMD_ENTRY(mdPinvokeImpl),
7398 SSMD_ENTRY(mdUnmanagedExport),
7400 SSMD_ENTRY(mdRTSpecialName),
7401 SSMD_ENTRY(mdHasSecurity),
7402 SSMD_ENTRY(mdRequireSecObject),
7404 NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdILStub,
7406 NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdLCGMethod,
7407 W("nomdLCGMethod") ),
7411 //maps MethodClassification to a name for a MethodDesc
7412 const char * const s_MDTypeName[] =
7414 "MethodDesc", //mcIL
7415 "FCallMethodDesc", //mcFCall
7416 "NDirectMethodDesc", //mcNDirect
7417 "EEImplMethodDesc", //mcEEImpl - //public StoredSigMethodDesc
7418 "ArrayMethodDesc", //mcArray - //public StoredSigMethodDesc
7419 "InstantiatedMethodDesc", //mcInstantiated
7420 #if defined(FEATURE_COMINTEROP)
7421 "ComPlusCallMethodDesc", //mcComInterop
7425 "DynamicMethodDesc", //mcDynamic -- //public StoredSigMethodDesc
7428 unsigned s_MDSizes[] =
7430 sizeof(MethodDesc), //mcIL
7431 sizeof(FCallMethodDesc), //mcFCall
7432 sizeof(NDirectMethodDesc), //mcNDirect
7433 sizeof(EEImplMethodDesc), //mcEEImpl
7434 sizeof(ArrayMethodDesc), //mcArray
7435 sizeof(InstantiatedMethodDesc), //mcInstantiated
7436 #if defined(FEATURE_COMINTEROP)
7437 sizeof(ComPlusCallMethodDesc), //mcComInterop
7441 sizeof(DynamicMethodDesc), //mcDynamic
7444 static NativeImageDumper::EnumMnemonics g_NDirectFlags[] =
7446 #define NDF_ENTRY(x) NativeImageDumper::EnumMnemonics( NDirectMethodDesc:: x, W(#x) )
7447 NDF_ENTRY(kEarlyBound),
7448 NDF_ENTRY(kHasSuppressUnmanagedCodeAccess),
7449 NDF_ENTRY(kIsMarshalingRequiredCached),
7450 NDF_ENTRY(kCachedMarshalingRequired),
7451 NDF_ENTRY(kNativeAnsi),
7452 NDF_ENTRY(kLastError),
7453 NDF_ENTRY(kNativeNoMangle),
7454 NDF_ENTRY(kVarArgs),
7455 NDF_ENTRY(kStdCall),
7456 NDF_ENTRY(kThisCall),
7457 NDF_ENTRY(kIsQCall),
7458 NDF_ENTRY(kStdCallWithRetBuf),
7461 NativeImageDumper::EnumMnemonics NativeImageDumper::s_IMDFlags[] =
7463 #define IMD_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, W(#x) )
7465 #define IMD_KIND_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, InstantiatedMethodDesc::KindMask, W(#x) )
7466 IMD_KIND_ENTRY(GenericMethodDefinition),
7467 IMD_KIND_ENTRY(UnsharedMethodInstantiation),
7468 IMD_KIND_ENTRY(SharedMethodInstantiation),
7469 IMD_KIND_ENTRY(WrapperStubWithInstantiations),
7470 #undef IMD_KIND_ENTRY
7472 #ifdef EnC_SUPPORTED
7473 // Method is a new virtual function added through EditAndContinue.
7474 IMD_ENTRY(EnCAddedMethod),
7475 #endif // EnC_SUPPORTED
7477 IMD_ENTRY(Unrestored),
7479 #ifdef FEATURE_COMINTEROP
7480 IMD_ENTRY(HasComPlusCallInfo),
7481 #endif // FEATURE_COMINTEROP
7486 void NativeImageDumper::DumpPrecode( PTR_Precode precode, PTR_Module module )
7488 _ASSERTE(isPrecode(PTR_TO_TADDR(precode)));
7490 PrecodeType pType = precode->GetType();
7493 #define DISPLAY_PRECODE(type) \
7494 IF_OPT_AND(PRECODES, METHODDESCS) \
7496 PTR_ ## type p( precode->As ## type () ); \
7497 DisplayStartStructure( # type, \
7498 DPtrToPreferredAddr(p), \
7499 sizeof(*p), ALWAYS ); \
7500 WriteFieldMethodDesc( m_pMethodDesc, \
7503 TADDR target = p->GetTarget(); \
7504 DisplayWriteElementPointer("Target",\
7505 DataPtrToDisplay(target),\
7507 DisplayEndStructure( ALWAYS ); \
7511 DISPLAY_PRECODE(StubPrecode); break;
7512 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7513 case PRECODE_NDIRECT_IMPORT:
7514 DISPLAY_PRECODE(NDirectImportPrecode); break;
7516 #ifdef HAS_FIXUP_PRECODE
7518 #ifdef HAS_RELATIVE_FIXUP_PRECODE
7519 _ASSERTE(!"unreachable"); break;
7520 #else // HAS_RELATIVE_FIXUP_PRECODE
7521 IF_OPT_AND(PRECODES, METHODDESCS)
7523 PTR_FixupPrecode p( precode->AsFixupPrecode() );
7524 DisplayStartStructure( "FixupPrecode",
7525 DPtrToPreferredAddr(p),
7528 PTR_MethodDesc precodeMD(p->GetMethodDesc());
7529 #ifdef HAS_FIXUP_PRECODE_CHUNKS
7531 DisplayWriteFieldInt( m_MethodDescChunkIndex,
7532 p->m_MethodDescChunkIndex, FixupPrecode,
7534 DisplayWriteFieldInt( m_PrecodeChunkIndex,
7535 p->m_PrecodeChunkIndex, FixupPrecode,
7537 if( p->m_PrecodeChunkIndex == 0 )
7539 //dump the location of the Base
7540 DisplayWriteElementAddress( "PrecodeChunkBase",
7541 DataPtrToDisplay(p->GetBase()),
7542 sizeof(void*), ALWAYS );
7544 //Make sure I align up if there is no code slot to make
7545 //sure that I get the padding
7546 TADDR mdPtrStart = p->GetBase()
7547 + (p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
7548 TADDR mdPtrEnd = ALIGN_UP( mdPtrStart + sizeof(MethodDesc*),
7550 CoverageRead( mdPtrStart, (ULONG32)(mdPtrEnd - mdPtrStart) );
7551 TADDR precodeMDSlot = p->GetBase()
7552 + p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT;
7553 DoWriteFieldMethodDesc( "MethodDesc",
7554 (DWORD)(precodeMDSlot - PTR_TO_TADDR(p)),
7555 sizeof(TADDR), precodeMD );
7557 #else //HAS_FIXUP_PRECODE_CHUNKS
7558 WriteFieldMethodDesc( m_pMethodDesc,
7560 FixupPrecode, ALWAYS );
7561 #endif //HAS_FIXUP_PRECODE_CHUNKS
7562 TADDR target = p->GetTarget();
7563 DisplayWriteElementPointer("Target",
7564 DataPtrToDisplay(target),
7566 /* REVISIT_TODO Thu 01/05/2006
7567 * dump slot with offset if it is here
7569 DisplayEndStructure( ALWAYS ); //FixupPrecode
7572 #endif // HAS_RELATIVE_FIXUP_PRECODE
7573 #endif // HAS_FIXUP_PRECODE
7574 #ifdef HAS_RELATIVE_FIXUP_PRECODE
7575 case PRECODE_RELATIVE_FIXUP:
7576 IF_OPT_AND(PRECODES, METHODDESCS)
7578 PTR_RelativeFixupPrecode p( precode->AsRelativeFixupPrecode() );
7579 DisplayStartStructure( "RelativeFixupPrecode",
7580 DPtrToPreferredAddr(p),
7583 PTR_MethodDesc precodeMD(p->GetMethodDesc());
7585 DisplayWriteFieldInt( m_MethodDescChunkIndex,
7586 p->m_MethodDescChunkIndex, RelativeFixupPrecode,
7588 DisplayWriteFieldInt( m_PrecodeChunkIndex,
7589 p->m_PrecodeChunkIndex, RelativeFixupPrecode,
7591 if( p->m_PrecodeChunkIndex == 0 )
7593 //dump the location of the Base
7594 DisplayWriteElementAddress( "PrecodeChunkBase",
7595 DataPtrToDisplay(p->GetBase()),
7596 sizeof(void*), ALWAYS );
7598 //Make sure I align up if there is no code slot to make
7599 //sure that I get the padding
7600 TADDR mdPtrStart = p->GetBase()
7601 + (p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
7602 TADDR mdPtrEnd = ALIGN_UP( mdPtrStart + sizeof(MethodDesc*),
7604 CoverageRead( mdPtrStart, (ULONG32)(mdPtrEnd - mdPtrStart) );
7605 TADDR precodeMDSlot = p->GetBase()
7606 + p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT;
7607 DoWriteFieldMethodDesc( "MethodDesc",
7608 (DWORD)(precodeMDSlot - PTR_TO_TADDR(p)),
7609 sizeof(TADDR), precodeMD );
7611 TADDR target = p->GetTarget();
7612 DisplayWriteElementPointer("Target",
7613 DataPtrToDisplay(target),
7615 /* REVISIT_TODO Thu 01/05/2006
7616 * dump slot with offset if it is here
7618 DisplayEndStructure( ALWAYS ); //RelativeFixupPrecode
7621 #endif // HAS_RELATIVE_FIXUP_PRECODE
7622 #ifdef HAS_THISPTR_RETBUF_PRECODE
7623 case PRECODE_THISPTR_RETBUF:
7624 DISPLAY_PRECODE(ThisPtrRetBufPrecode); break;
7627 _ASSERTE( !"Unsupported precode type" );
7628 #undef DISPLAY_PRECODE
7629 #undef PrecodeMDWrite
7634 #pragma warning(push)
7635 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
7637 void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module )
7639 //StoredSigMethodDesc
7641 MethodClassification mc =
7642 (MethodClassification)md->GetClassification();
7643 _ASSERTE(mc >= 0 && mc < mcCount);
7644 const char * mdTypeName = s_MDTypeName[mc];
7645 unsigned mdSize = (unsigned)md->SizeOf();
7647 DisplayStartStructure( mdTypeName, DPtrToPreferredAddr(md),
7648 mdSize, METHODDESCS );
7652 MethodDescToString( md, buf );
7653 DisplayWriteElementStringW( "Name", (const WCHAR *)buf, METHODDESCS );
7658 WriteFieldStr(m_pszDebugMethodName,
7659 PTR_BYTE(TO_TADDR(md->m_pszDebugMethodName)),
7660 MethodDesc, METHODDESCS);
7661 WriteFieldStr(m_pszDebugClassName,
7662 PTR_BYTE(TO_TADDR(md->m_pszDebugClassName)),
7663 MethodDesc, METHODDESCS);
7664 WriteFieldStr(m_pszDebugMethodSignature,
7665 PTR_BYTE(TO_TADDR(md->m_pszDebugMethodSignature)),
7666 MethodDesc, METHODDESCS);
7670 CoverageReadString(TO_TADDR(md->m_pszDebugMethodName));
7671 CoverageReadString(TO_TADDR(md->m_pszDebugClassName));
7672 CoverageReadString(TO_TADDR(md->m_pszDebugMethodSignature));
7676 DisplayWriteFieldInt( m_wFlags3AndTokenRemainder, md->m_wFlags3AndTokenRemainder,
7677 MethodDesc, METHODDESCS );
7679 DisplayWriteFieldInt( m_chunkIndex, md->m_chunkIndex,
7680 MethodDesc, METHODDESCS );
7682 /* XXX Fri 03/24/2006
7683 * This is a workaround. The InstantiatedMethodDescs are in chunks, but there's
7684 * no obvious place to display the chunk, so display the bounds here.
7686 if( mc == mcInstantiated && md->m_chunkIndex == 0 )
7688 PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
7689 DisplayWriteElementAddress( "MethodDescChunk", DPtrToPreferredAddr(chunk),
7690 chunk->SizeOf(), METHODDESCS );
7693 DisplayWriteFieldEnumerated( m_bFlags2, md->m_bFlags2, MethodDesc,
7694 s_MDFlag2, W(", "), METHODDESCS );
7696 DisplayWriteFieldInt( m_wSlotNumber, md->GetSlot(), MethodDesc,
7698 DisplayWriteFieldEnumerated( m_wFlags, md->m_wFlags, MethodDesc,
7699 s_MDC, W(", "), METHODDESCS );
7705 PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
7706 //chunk is implicitly remapped because it's calculated from the pointer
7708 PTR_MethodTable mt = chunk->GetMethodTable();
7709 if( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
7711 if ( md->IsTypicalMethodDefinition() )
7714 m_import->GetMethodProps(md->GetMemberDef(), NULL, NULL, NULL, 0,
7715 NULL, NULL, NULL, &dwRVA, NULL);
7719 _ASSERTE(m_ILHostCopy);
7720 _ASSERTE(m_ILSectionStart);
7721 _ASSERTE(dwRVA >= m_ILSectionStart);
7722 _ASSERTE(dwRVA < (m_ILSectionStart + m_ILSectionSize));
7723 //The RVA is from the start of the file, so convert it
7724 //to an RVA to the start of the .text section.
7725 TADDR pILTarget = (TADDR)m_decoder.GetRvaData(dwRVA);
7726 COR_ILMETHOD * pILHeader = (COR_ILMETHOD*)(m_ILHostCopy + dwRVA - m_ILSectionStart);
7728 COR_ILMETHOD_DECODER decoder(pILHeader);
7730 DisplayStartStructure( "IL",
7731 DataPtrToDisplay(pILTarget),
7732 PEDecoder::ComputeILMethodSize(pILTarget),
7735 DisplayWriteElementInt( "CodeSize", decoder.GetCodeSize(), ALWAYS );
7737 // Dump the disassembled IL code?
7739 DisplayEndStructure( ALWAYS );
7745 if( md->HasPrecode() )
7747 PTR_Precode precode( md->GetPrecode() );
7749 DumpPrecode( precode, module );
7751 if ( md->HasNonVtableSlot() )
7753 DisplayWriteElementInt( "Slot", (DWORD)(md->GetAddrOfSlot() - PTR_TO_TADDR(md)), ALWAYS);
7755 if (md->HasNativeCodeSlot())
7757 DisplayWriteElementInt( "NativeCode", DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)), ALWAYS);
7758 //m_display->WriteFieldPointer( "NativeCode",
7759 // DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)),
7761 // md->GetNativeCode() );
7763 if (md->HasMethodImplSlot())
7765 DisplayStartVStructure( "MethodImpl", METHODDESCS );
7766 PTR_MethodImpl impl(md->GetMethodImpl());
7767 PTR_DWORD slots = impl->GetSlots() - 1; // GetSlots returns the address of the first real slot (past the size)
7768 unsigned numSlots = impl->GetSize();
7769 _ASSERTE(!numSlots || numSlots == slots[0]);
7770 _ASSERTE(slots == NULL || isInRange(PTR_TO_TADDR(slots)));
7771 if ((slots != NULL) && isInRange(PTR_TO_TADDR(slots)))
7773 DisplayWriteFieldAddress(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7774 (numSlots + 1) * sizeof(*slots),
7775 MethodImpl, METHODDESCS);
7779 DisplayWriteFieldPointer(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7780 MethodImpl, METHODDESCS);
7783 _ASSERTE(impl->pImplementedMD.IsNull()
7784 || isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())));
7785 if (!impl->pImplementedMD.IsNull() &&
7786 isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())))
7788 DisplayWriteFieldAddress( pImplementedMD,
7789 DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDsNonNull())),
7790 numSlots * sizeof(RelativePointer <MethodDesc*>),
7791 MethodImpl, METHODDESCS );
7795 DisplayWriteFieldPointer( pImplementedMD,
7796 DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDs())),
7797 MethodImpl, METHODDESCS );
7799 DisplayEndVStructure( METHODDESCS );
7801 if (md->HasStoredSig())
7803 DisplayStartVStructure( "StoredSigMethodDesc", METHODDESCS );
7804 PTR_StoredSigMethodDesc ssmd(md);
7805 //display signature information.
7806 if( isInRange(ssmd->GetSigRVA()) )
7808 DisplayWriteFieldAddress(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7809 ssmd->m_cSig, StoredSigMethodDesc,
7814 DisplayWriteFieldPointer(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7815 StoredSigMethodDesc, METHODDESCS);
7818 CoverageRead(TO_TADDR(ssmd->GetSigRVA()), ssmd->m_cSig);
7819 DisplayWriteFieldInt( m_cSig, ssmd->m_cSig,
7820 StoredSigMethodDesc, METHODDESCS );
7822 DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7823 ssmd->m_dwExtendedFlags,
7824 StoredSigMethodDesc,
7825 s_SSMDExtendedFlags, W(", "),
7828 DisplayEndVStructure( METHODDESCS ); //StoredSigMethodDesc
7830 if( mc == mcDynamic )
7832 PTR_DynamicMethodDesc dmd(md);
7833 DisplayStartVStructure( "DynamicMethodDesc", METHODDESCS );
7834 WriteFieldStr( m_pszMethodName, PTR_BYTE(dmd->GetMethodName()),
7835 DynamicMethodDesc, METHODDESCS );
7836 if( !CHECK_OPT(METHODDESCS) )
7837 CoverageReadString( PTR_TO_TADDR(dmd->GetMethodName()) );
7838 DisplayWriteFieldPointer( m_pResolver,
7839 DPtrToPreferredAddr(dmd->m_pResolver),
7840 DynamicMethodDesc, METHODDESCS );
7842 DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7843 dmd->m_dwExtendedFlags,
7845 s_SSMDExtendedFlags, W(", "),
7848 DisplayEndVStructure( METHODDESCS );
7852 PTR_FCallMethodDesc fcmd(md);
7853 DisplayStartVStructure( "FCallMethodDesc", METHODDESCS );
7855 DisplayWriteFieldInt( m_dwECallID,
7860 DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7862 if( mc == mcNDirect )
7864 PTR_NDirectMethodDesc ndmd(md);
7865 DisplayStartVStructure( "NDirectMethodDesc", METHODDESCS );
7866 DPTR(NDirectMethodDesc::temp1) nd( PTR_HOST_MEMBER_TADDR(NDirectMethodDesc, ndmd, ndirect) );
7867 DisplayStartStructureWithOffset( ndirect,
7868 DPtrToPreferredAddr(nd),
7869 sizeof(*nd), NDirectMethodDesc,
7871 DisplayWriteFieldPointer( m_pNativeNDirectTarget,
7872 DataPtrToDisplay((TADDR)nd->m_pNativeNDirectTarget),
7873 NDirectMethodDesc::temp1,
7875 DisplayWriteFieldEnumerated( m_wFlags, nd->m_wFlags,
7876 NDirectMethodDesc::temp1,
7877 g_NDirectFlags, W(", "),
7880 WriteFieldStr( m_pszEntrypointName,
7881 PTR_BYTE(dac_cast<TADDR>(ndmd->GetEntrypointName())),
7882 NDirectMethodDesc::temp1, METHODDESCS );
7883 if( !CHECK_OPT(METHODDESCS) )
7884 CoverageReadString(dac_cast<TADDR>(ndmd->GetEntrypointName()));
7887 DisplayWriteFieldInt( m_dwECallID,
7889 NDirectMethodDesc::temp1,
7894 WriteFieldStr( m_pszLibName,
7895 PTR_BYTE(dac_cast<TADDR>(ndmd->GetLibNameRaw())),
7896 NDirectMethodDesc::temp1, METHODDESCS );
7898 if( !CHECK_OPT(METHODDESCS) )
7899 CoverageReadString( dac_cast<TADDR>(ndmd->GetLibNameRaw()) );
7901 PTR_NDirectWriteableData wnd( ndmd->GetWriteableData() );
7902 DisplayStartStructureWithOffset( m_pWriteableData,
7903 DPtrToPreferredAddr(wnd),
7905 NDirectMethodDesc::temp1,
7907 DisplayWriteFieldPointer( m_pNDirectTarget,
7908 DataPtrToDisplay((TADDR)wnd->m_pNDirectTarget), NDirectWriteableData, METHODDESCS );
7909 if( !CHECK_OPT(METHODDESCS) )
7910 CoverageRead( PTR_TO_TADDR(wnd), sizeof(*wnd) );
7911 DisplayEndStructure( METHODDESCS ); //m_pWriteableData
7913 PTR_NDirectImportThunkGlue glue(ndmd->GetNDirectImportThunkGlue());
7915 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7918 // import thunk glue is not needed for P/Invoke that is not inlinable
7919 DisplayWriteFieldPointer( m_pImportThunkGlue,
7921 NDirectMethodDesc::temp1,
7926 DisplayStartStructureWithOffset( m_pImportThunkGlue,
7927 DPtrToPreferredAddr(glue),
7929 NDirectMethodDesc::temp1,
7932 DisplayStartStructureWithOffset( m_ImportThunkGlue,
7933 DPtrToPreferredAddr(glue),
7935 NDirectMethodDesc::temp1,
7938 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7939 /* REVISIT_TODO Thu 01/05/2006
7940 * Dump this properly as a precode
7942 WriteFieldMethodDesc( m_pMethodDesc, glue->m_pMethodDesc,
7943 NDirectImportThunkGlue, METHODDESCS );
7945 PTR_Precode p(glue);
7946 DumpPrecode( p, module );
7948 if( !CHECK_OPT(METHODDESCS) )
7949 CoverageRead(PTR_TO_TADDR(glue), sizeof(*glue));
7950 /* REVISIT_TODO Fri 12/16/2005
7951 * Factor out this code into some shared precode dumping code
7953 #else //!HAS_NDIRECT_IMPORT_PRECODE
7954 /* REVISIT_TODO Fri 10/27/2006
7955 * For Whidbey AMD64 (!HAS_NDIRECT_IMPORT_PRECODE), I don't have this data structure in the output.
7957 #endif //HAS_NDIRECT_IMPORT_PRECODE
7959 DisplayEndStructure( METHODDESCS ); //m_pImportThunkGlue
7960 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7965 DisplayWriteFieldInt( m_cbStackArgumentSize,
7966 nd->m_cbStackArgumentSize,
7967 NDirectMethodDesc::temp1, METHODDESCS );
7970 WriteFieldMethodDesc( m_pStubMD,
7971 nd->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc::temp1, nd, m_pStubMD)),
7972 NDirectMethodDesc::temp1, METHODDESCS );
7974 DisplayEndStructure( METHODDESCS ); //ndirect
7977 DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7979 if( mc == mcEEImpl )
7981 DisplayStartVStructure( "EEImplMethodDesc", METHODDESCS );
7982 DisplayEndVStructure( METHODDESCS );
7984 #if defined(FEATURE_COMINTEROP)
7985 if( mc == mcComInterop )
7987 PTR_ComPlusCallMethodDesc cpmd(md);
7988 DisplayStartVStructure( "ComPlusCallMethodDesc", METHODDESCS );
7989 PTR_ComPlusCallInfo compluscall((TADDR)cpmd->m_pComPlusCallInfo);
7991 if (compluscall == NULL)
7993 DisplayWriteFieldPointer( m_pComPlusCallInfo,
7995 ComPlusCallMethodDesc,
8000 DumpComPlusCallInfo( compluscall, METHODDESCS );
8003 DisplayEndVStructure( METHODDESCS ); //ComPlusCallMethodDesc
8006 if( mc == mcInstantiated )
8008 PTR_InstantiatedMethodDesc imd(md);
8009 DisplayStartVStructure( "InstantiatedMethodDesc", METHODDESCS );
8010 unsigned kind = imd->m_wFlags2
8011 & InstantiatedMethodDesc::KindMask;
8012 if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
8014 PTR_DictionaryLayout layout(dac_cast<TADDR>(imd->GetDictLayoutRaw()));
8017 WriteFieldDictionaryLayout( "m_pDictLayout",
8018 offsetof(InstantiatedMethodDesc, m_pDictLayout ),
8019 fieldsize(InstantiatedMethodDesc, m_pDictLayout),
8021 GetDependencyFromMD(md)->pImport );
8025 while( layout != NULL )
8027 CoverageRead( PTR_TO_TADDR(layout),
8028 sizeof(DictionaryLayout)
8029 + sizeof(DictionaryEntryLayout)
8030 * (layout->m_numSlots - 1) );
8031 layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
8036 InstantiatedMethodDesc::WrapperStubWithInstantiations )
8038 PTR_MethodDesc wimd(imd->IMD_GetWrappedMethodDesc());
8039 if( wimd == NULL || !DoWriteFieldAsFixup( "m_pWrappedMethodDesc",
8040 offsetof(InstantiatedMethodDesc, m_pWrappedMethodDesc),
8041 fieldsize(InstantiatedMethodDesc, m_pWrappedMethodDesc),
8042 PTR_TO_TADDR(wimd) ) )
8044 WriteFieldMethodDesc( m_pWrappedMethodDesc, wimd,
8045 InstantiatedMethodDesc, METHODDESCS );
8050 _ASSERTE(imd->m_pDictLayout.IsNull());
8051 DisplayWriteFieldPointer( m_pDictLayout, NULL,
8052 InstantiatedMethodDesc,
8055 //now handle the contents of the m_pMethInst/m_pPerInstInfo union.
8056 unsigned numSlots = imd->m_wNumGenericArgs;
8057 PTR_Dictionary inst(imd->IMD_GetMethodDictionary());
8059 if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
8061 dictSize = sizeof(TypeHandle);
8063 else if( kind == InstantiatedMethodDesc::WrapperStubWithInstantiations )
8065 PTR_InstantiatedMethodDesc wrapped =
8066 PTR_InstantiatedMethodDesc(imd->IMD_GetWrappedMethodDesc());
8067 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(wrapped)) )
8069 /* XXX Mon 03/27/2006
8070 * Note that 4 is the correct answer for all IMDs at this time.
8073 MethodDescToString( md, buf );
8074 //m_display->ErrorPrintF( "WARNING! InstantiatedMethodDesc %S wraps a MethodDesc that is a fixup. I cannot accurately determine the size of the associated generic dictionary. Assuming 4.\n", (const WCHAR *)buf );
8075 dictSize = (imd->GetNumGenericMethodArgs() + 4) * sizeof(void*);
8079 PTR_DictionaryLayout layout(wrapped->IsSharedByGenericMethodInstantiations()
8080 ? dac_cast<TADDR>(wrapped->GetDictLayoutRaw()) : NULL );
8081 dictSize = DictionaryLayout::GetFirstDictionaryBucketSize(imd->GetNumGenericMethodArgs(),
8087 dictSize = sizeof(TypeHandle);
8089 //instantiations has the number of slots of
8090 //GetNumGenericMethodArgs.
8093 m_display->WriteFieldPointer( "m_pPerInstInfo",
8094 offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8095 fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8103 m_display->StartStructureWithOffset( "m_pPerInstInfo",
8104 offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8105 fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8106 DPtrToPreferredAddr(inst),
8109 DisplayStartArray( "InstantiationInfo", W("[%-2s]: %s"),
8111 /* REVISIT_TODO Thu 03/23/2006
8112 * This doesn't dump the contents of the dictionary which are
8113 * hanging around after the real slots. Get around to doing that.
8115 for( unsigned i = 0; i < numSlots
8116 && CHECK_OPT(METHODDESCS); ++i )
8118 DisplayStartElement( "Handle", METHODDESCS );
8119 DisplayWriteElementInt( "Index", i, METHODDESCS );
8121 TypeHandle thArg = inst->GetInstantiation()[i].GetValue();
8123 WriteElementTypeHandle( "TypeHandle", thArg);
8125 /* XXX Fri 03/24/2006
8126 * There is no really good home for TypeDescs, so I gotta check
8127 * lots of places for them.
8129 if( !CORCOMPILE_IS_POINTER_TAGGED(thArg.AsTAddr()) &&
8130 thArg.IsTypeDesc() )
8132 PTR_TypeDesc td(thArg.AsTypeDesc());
8133 if( isInRange(PTR_TO_TADDR(td)) )
8135 m_discoveredTypeDescs.AppendEx(td);
8138 DisplayEndElement( METHODDESCS ); //Handle
8140 //Instantiation Info
8141 DisplayEndArray( "Total TypeHandles", METHODDESCS );
8143 DisplayEndVStructure(METHODDESCS); //m_pPerInstInfo;
8144 if( !CHECK_OPT(METHODDESCS) )
8145 CoverageRead(PTR_TO_TADDR(inst), numSlots * sizeof(*inst));
8148 DisplayWriteFieldEnumerated( m_wFlags2, imd->m_wFlags2,
8149 InstantiatedMethodDesc, s_IMDFlags,
8150 W(", "), METHODDESCS );
8151 DisplayWriteFieldInt( m_wNumGenericArgs, imd->m_wNumGenericArgs,
8152 InstantiatedMethodDesc, METHODDESCS );
8154 #ifdef FEATURE_COMINTEROP
8155 if (imd->IMD_HasComPlusCallInfo())
8157 PTR_ComPlusCallInfo compluscall = imd->IMD_GetComPlusCallInfo();
8158 DumpComPlusCallInfo( compluscall, METHODDESCS );
8160 #endif // FEATURE_COMINTEROP
8162 DisplayEndStructure( METHODDESCS );
8165 DisplayEndStructure( METHODDESCS ); //MethodDesc (mdTypeName)
8166 if( !CHECK_OPT(METHODDESCS) )
8167 CoverageRead( PTR_TO_TADDR(md), mdSize );
8171 #pragma warning(pop)
8174 NativeImageDumper::EnumMnemonics NativeImageDumper::s_EECLIFlags[] =
8176 #define EECLI_FLAGS_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClassLayoutInfo:: x, W(#x) )
8177 EECLI_FLAGS_ENTRY(e_BLITTABLE),
8178 EECLI_FLAGS_ENTRY(e_MANAGED_SEQUENTIAL),
8179 EECLI_FLAGS_ENTRY(e_ZERO_SIZED),
8180 EECLI_FLAGS_ENTRY(e_HAS_EXPLICIT_SIZE),
8181 #undef EECLI_FLAGS_ENTRY
8186 #pragma warning(push)
8187 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
8190 NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
8192 PTR_EEClass clazz = mt->GetClass();
8194 _ASSERTE(CHECK_OPT(EECLASSES));
8195 _ASSERTE(clazz != NULL);
8196 _ASSERTE(isInRange(PTR_TO_TADDR(clazz)));
8198 const char * eeClassType;
8200 if( clazz->HasLayout() )
8201 eeClassType = "LayoutEEClass";
8202 else if( mt->IsArray() )
8203 eeClassType = "ArrayClass";
8204 else if( clazz->IsDelegate() )
8205 eeClassType = "DelegateEEClass";
8207 eeClassType = "EEClass";
8209 DisplayStartStructure( eeClassType, DPtrToPreferredAddr(clazz), clazz->GetSize(),
8213 MethodTableToString( mt, buf );
8214 DisplayWriteElementStringW( "Name", (const WCHAR *)buf, EECLASSES );
8217 PTR_GuidInfo guidInfo = clazz->GetGuidInfo();
8218 if(guidInfo != NULL)
8220 DisplayStartStructureWithOffset( m_pGuidInfo,
8221 DPtrToPreferredAddr(guidInfo),
8222 sizeof(*guidInfo), EEClass,
8225 GuidToString( guidInfo->m_Guid, buf );
8226 DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
8228 DisplayWriteFieldFlag( m_bGeneratedFromName,
8229 guidInfo->m_bGeneratedFromName,
8230 GuidInfo, EECLASSES );
8231 DisplayEndStructure( EECLASSES ); //guidinfo
8235 /* XXX Fri 10/14/2005
8236 * if Clazz isn't an interface, m_pGuidInfo is undefined.
8238 DisplayWriteFieldPointerAnnotated( m_pGuidInfo, PTR_TO_TADDR(guidInfo),
8239 W("Invalid"), EEClass, EECLASSES );
8244 WriteFieldStr( m_szDebugClassName,
8245 PTR_BYTE(TO_TADDR(clazz->m_szDebugClassName)),
8246 EEClass, EECLASSES );
8247 DisplayWriteFieldFlag( m_fDebuggingClass, clazz->m_fDebuggingClass,
8248 EEClass, EECLASSES );
8251 WriteFieldMethodTable( m_pMethodTable, clazz->GetMethodTable(), EEClass,
8254 WriteFieldCorElementType( m_NormType, (CorElementType)clazz->m_NormType,
8255 EEClass, EECLASSES );
8257 PTR_FieldDesc fdList = clazz->GetFieldDescList();
8259 ULONG fieldCount = (ULONG)CountFields(mt);
8260 _ASSERTE((fdList == NULL) == (fieldCount == 0));
8264 m_display->StartStructureWithOffset( "m_pFieldDescList",
8265 offsetof(EEClass, m_pFieldDescList),
8266 fieldsize(EEClass, m_pFieldDescList),
8267 DPtrToPreferredAddr(fdList),
8269 sizeof(*fdList) * fieldCount :
8272 IF_OPT(VERBOSE_TYPES)
8274 if( fdList != NULL )
8276 DisplayStartArray( "FieldDescs", NULL, EECLASSES );
8277 for( SIZE_T i = 0; i < fieldCount; ++i )
8279 PTR_FieldDesc fd = fdList + i;
8281 DumpFieldDesc( fd, "FieldDesc" );
8283 DisplayEndArray( "Total FieldDescs", EECLASSES ); //FieldDescs
8286 else if( (fdList != NULL) && CHECK_OPT(DEBUG_COVERAGE) )
8288 for( SIZE_T i = 0; i < fieldCount; ++i )
8290 PTR_FieldDesc fd = fdList + i;
8292 if( fd != NULL && fd->m_debugName != NULL )
8293 CoverageReadString( fd->m_debugName );
8296 CoverageRead( PTR_TO_TADDR(fdList), sizeof(*fdList) * fieldCount );
8299 DisplayEndStructure( EECLASSES ); //FieldDescList
8301 DisplayWriteFieldEnumerated( m_dwAttrClass, clazz->GetAttrClass(),
8302 EEClass, s_CorTypeAttr, W(" "), EECLASSES );
8303 DisplayWriteFieldEnumerated( m_VMFlags, clazz->m_VMFlags, EEClass,
8304 s_VMFlags, W(", "), EECLASSES );
8306 PTR_MethodDescChunk chunk = clazz->GetChunks();
8308 DisplayStartArrayWithOffset( m_pChunks, NULL, EEClass, EECLASSES );
8309 while( chunk != NULL )
8311 DisplayStartStructure( "MethodDescChunk",
8312 DPtrToPreferredAddr(chunk),
8313 chunk->SizeOf(), EECLASSES );
8314 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(chunk->GetMethodTable())));
8315 PTR_MethodTable chunkMT = chunk->GetMethodTable();
8316 DisplayWriteFieldPointer( m_methodTable,
8317 DPtrToPreferredAddr(chunkMT),
8318 MethodDescChunk, EECLASSES );
8319 PTR_MethodDescChunk chunkNext = chunk->GetNextChunk();
8320 DisplayWriteFieldPointer( m_next,
8321 DPtrToPreferredAddr(chunkNext),
8322 MethodDescChunk, EECLASSES );
8323 DisplayWriteFieldInt( m_size, chunk->m_size, MethodDescChunk,
8325 DisplayWriteFieldInt( m_count, chunk->m_count, MethodDescChunk,
8327 DisplayWriteFieldInt( m_flagsAndTokenRange, chunk->m_flagsAndTokenRange, MethodDescChunk,
8329 /* XXX Wed 12/14/2005
8330 * Don't skip walking this array. I need to make sure I touch the
8333 DisplayStartArray( "MethodDescs", NULL, METHODDESCS );
8334 PTR_MethodDesc md(chunk->GetFirstMethodDesc());
8337 IF_OPT_OR(METHODDESCS, DEBUG_COVERAGE)
8339 PTR_Module module = mt->GetModule();
8340 if(CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module) ))
8341 DumpMethodDesc( md, PTR_Module((TADDR)0) );
8343 DumpMethodDesc( md, module );
8346 // Check whether the next MethodDesc is within the bounds of the current chunks
8347 TADDR pNext = PTR_HOST_TO_TADDR(md) + md->SizeOf();
8348 TADDR pEnd = PTR_HOST_TO_TADDR(chunk) + chunk->SizeOf();
8350 md = (pNext < pEnd) ? PTR_MethodDesc(pNext) : NULL;
8353 DisplayEndArray( "Total MethodDescs", METHODDESCS); //MethodDescs
8355 chunk = chunk->GetNextChunk();
8357 DisplayEndStructure( EECLASSES ); //MethodDescChunk
8360 DisplayEndArray( "Total MethodDescChunks", EECLASSES );
8361 /* REVISIT_TODO Fri 10/14/2005
8362 * Dump the class dependencies
8364 //_ASSERTE(!clazz->m_classDependencies.TestAnyBit());
8366 /* REVISIT_TODO Mon 10/24/2005
8367 * Create vstructure for union?
8370 #ifdef FEATURE_COMINTEROP
8371 if( clazz->IsBlittable() || clazz->HasLayout() )
8373 DisplayWriteFieldInt(m_cbNativeSize, clazz->m_cbNativeSize, EEClass,
8376 else if( clazz->IsInterface() )
8378 DisplayWriteFieldPointer( m_ohDelegate,
8379 DataPtrToDisplay(clazz->m_ohDelegate),
8380 EEClass, EECLASSES );
8384 static const WCHAR * ifnames[] ={W("Dual"),W("Vtable"),W("Dispatch")};
8385 m_display->WriteFieldEnumerated( "ComInterfaceType",
8387 m_ComInterfaceType),
8389 m_ComInterfaceType),
8390 (int)clazz->m_ComInterfaceType,
8391 ifnames[(int)clazz->m_ComInterfaceType] );
8394 DisplayWriteFieldInt( m_cbNativeSize, clazz->m_cbNativeSize,
8395 EEClass, EECLASSES );
8398 #if defined(FEATURE_COMINTEROP)
8399 PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(clazz->m_pccwTemplate));
8400 if( ccwTemplate != NULL )
8402 DisplayWriteFieldPointer( m_pccwTemplate, NULL, EEClass,
8407 /* REVISIT_TODO Fri 10/14/2005
8410 DisplayWriteFieldPointer( m_pccwTemplate,
8411 DPtrToPreferredAddr(ccwTemplate), EEClass,
8414 #endif // defined(FEATURE_COMINTEROP)
8416 //fields for classes that aren't just EEClasses.
8417 if( clazz->HasLayout() )
8419 PTR_LayoutEEClass layoutClass(PTR_TO_TADDR(clazz));
8420 DisplayStartVStructure("LayoutEEClass", EECLASSES );
8422 PTR_EEClassLayoutInfo eecli( PTR_HOST_MEMBER_TADDR( LayoutEEClass,
8425 DisplayStartStructureWithOffset( m_LayoutInfo,
8426 DPtrToPreferredAddr(eecli),
8427 sizeof(EEClassLayoutInfo),
8428 LayoutEEClass, EECLASSES );
8429 /* REVISIT_TODO Fri 10/14/2005
8430 * Dump EEClassLayoutInfo
8432 DisplayWriteFieldInt( m_cbNativeSize, eecli->m_cbNativeSize,
8433 EEClassLayoutInfo, VERBOSE_TYPES );
8434 DisplayWriteFieldInt( m_cbManagedSize, eecli->m_cbManagedSize,
8435 EEClassLayoutInfo, VERBOSE_TYPES );
8436 DisplayWriteFieldInt( m_LargestAlignmentRequirementOfAllMembers,
8437 eecli->m_LargestAlignmentRequirementOfAllMembers,
8438 EEClassLayoutInfo, VERBOSE_TYPES );
8439 DisplayWriteFieldInt( m_ManagedLargestAlignmentRequirementOfAllMembers,
8440 eecli->m_ManagedLargestAlignmentRequirementOfAllMembers,
8441 EEClassLayoutInfo, VERBOSE_TYPES );
8442 DisplayWriteFieldEnumerated( m_bFlags, eecli->m_bFlags,
8443 EEClassLayoutInfo, s_EECLIFlags, W(", "),
8445 DisplayWriteFieldInt( m_numCTMFields, eecli->m_numCTMFields,
8446 EEClassLayoutInfo, VERBOSE_TYPES );
8447 PTR_FieldMarshaler fmArray = eecli->GetFieldMarshalers();
8448 DisplayWriteFieldAddress( m_pFieldMarshalers,
8449 DPtrToPreferredAddr(fmArray),
8450 eecli->m_numCTMFields
8451 * MAXFIELDMARSHALERSIZE,
8452 EEClassLayoutInfo, VERBOSE_TYPES );
8453 /* REVISIT_TODO Wed 03/22/2006
8454 * Dump the various types of FieldMarshalers.
8457 DisplayStartArrayWithOffset( m_pFieldMarshalers, NULL,
8458 EEClassLayoutInfo, VERBOSE_TYPES );
8459 for( unsigned i = 0; i < eecli->m_numCTMFields; ++i )
8461 /* REVISIT_TODO Wed 03/22/2006
8462 * Try to display the type of the field marshaler in the future.
8464 PTR_FieldMarshaler current = fmArray + i;
8465 DisplayStartStructure( "FieldMarshaler",
8466 DPtrToPreferredAddr(current),
8467 sizeof(*current), VERBOSE_TYPES );
8468 WriteFieldFieldDesc( m_pFD, PTR_FieldDesc(TO_TADDR(current->m_pFD)),
8469 FieldMarshaler, VERBOSE_TYPES );
8470 DisplayWriteFieldInt( m_dwExternalOffset,
8471 current->m_dwExternalOffset, FieldMarshaler,
8473 DisplayEndStructure( VERBOSE_TYPES ); //FieldMarshaler
8476 DisplayEndArray( "Number of FieldMarshalers", VERBOSE_TYPES ); //m_pFieldMarshalers
8479 DisplayEndStructure( EECLASSES ); //LayoutInfo
8481 DisplayEndVStructure( EECLASSES ); //LayoutEEClass
8483 else if( mt->IsArray() )
8485 PTR_ArrayClass arrayClass(PTR_TO_TADDR(clazz));
8486 DisplayStartVStructure( "ArrayClass", EECLASSES);
8489 m_display->WriteFieldInt( "m_rank", offsetof(ArrayClass, m_rank),
8490 fieldsize(ArrayClass, m_rank),
8491 arrayClass->GetRank() );
8493 DoWriteFieldCorElementType( "m_ElementType",
8494 offsetof(ArrayClass, m_ElementType),
8495 fieldsize(ArrayClass, m_ElementType),
8496 arrayClass->GetArrayElementType() );
8498 DisplayEndVStructure( EECLASSES ); //ArrayClass
8500 else if( clazz->IsDelegate() )
8502 PTR_DelegateEEClass delegateClass(PTR_TO_TADDR(clazz));
8503 DisplayStartVStructure( "DelegateEEClass", EECLASSES );
8505 DumpFieldStub( m_pStaticCallStub, delegateClass->m_pStaticCallStub,
8506 DelegateEEClass, EECLASSES );
8507 DumpFieldStub( m_pInstRetBuffCallStub,
8508 delegateClass->m_pInstRetBuffCallStub,
8509 DelegateEEClass, EECLASSES );
8511 WriteFieldMethodDesc( m_pInvokeMethod,
8512 delegateClass->GetInvokeMethod(),
8513 DelegateEEClass, EECLASSES );
8514 DumpFieldStub( m_pMultiCastInvokeStub,
8515 delegateClass->m_pMultiCastInvokeStub,
8516 DelegateEEClass, EECLASSES );
8518 DPTR(UMThunkMarshInfo)
8519 umInfo(TO_TADDR(delegateClass->m_pUMThunkMarshInfo));
8521 if( umInfo == NULL )
8523 DisplayWriteFieldPointer( m_pUMThunkMarshInfo, NULL,
8524 DelegateEEClass, EECLASSES );
8528 DisplayStartStructureWithOffset( m_pUMThunkMarshInfo,
8529 DPtrToPreferredAddr(umInfo),
8531 DelegateEEClass, EECLASSES );
8532 /* REVISIT_TODO Fri 10/14/2005
8533 * DumpUMThunkMarshInfo
8535 DisplayEndStructure( EECLASSES ); //UMThunkMarshInfo
8538 WriteFieldMethodDesc( m_pBeginInvokeMethod,
8539 delegateClass->GetBeginInvokeMethod(),
8540 DelegateEEClass, EECLASSES );
8541 WriteFieldMethodDesc( m_pEndInvokeMethod,
8542 delegateClass->GetEndInvokeMethod(),
8543 DelegateEEClass, EECLASSES );
8544 DisplayWriteFieldPointer( m_pMarshalStub, delegateClass->m_pMarshalStub,
8545 DelegateEEClass, EECLASSES );
8547 WriteFieldMethodDesc( m_pForwardStubMD,
8548 PTR_MethodDesc(TO_TADDR(delegateClass->m_pForwardStubMD)),
8549 DelegateEEClass, EECLASSES );
8550 WriteFieldMethodDesc( m_pReverseStubMD,
8551 PTR_MethodDesc(TO_TADDR(delegateClass->m_pReverseStubMD)),
8552 DelegateEEClass, EECLASSES );
8554 #ifdef FEATURE_COMINTEROP
8555 DPTR(ComPlusCallInfo) compluscall((TADDR)delegateClass->m_pComPlusCallInfo);
8556 if (compluscall == NULL)
8558 DisplayWriteFieldPointer( m_pComPlusCallInfo,
8565 DumpComPlusCallInfo( compluscall, EECLASSES );
8567 #endif // FEATURE_COMINTEROP
8569 DisplayEndVStructure( EECLASSES ); //DelegateEEClass
8572 DisplayEndStructure( EECLASSES ); //eeClassType
8574 PTR_EEClassOptionalFields pClassOptional = clazz->GetOptionalFields();
8577 DisplayStartStructure( "EEClassOptionalFields", DPtrToPreferredAddr(pClassOptional), sizeof(EEClassOptionalFields),
8580 #ifdef FEATURE_COMINTEROP
8581 PTR_SparseVTableMap sparseVTMap(TO_TADDR(pClassOptional->m_pSparseVTableMap));
8582 if( sparseVTMap == NULL )
8584 DisplayWriteFieldPointer( m_pSparseVTableMap, NULL, EEClassOptionalFields,
8589 _ASSERTE( !"Untested code" );
8592 m_display->StartStructure( "m_SparseVTableMap",
8593 DPtrToPreferredAddr(sparseVTMap),
8594 sizeof(*sparseVTMap) );
8596 _ASSERTE(sparseVTMap->m_MapList != NULL);
8597 PTR_SparseVTableMap_Entry mapList(TO_TADDR(sparseVTMap->m_MapList));
8598 DisplayStartArray( "m_MapList", NULL, EECLASSES );
8599 for( WORD i = 0; i < sparseVTMap->m_MapEntries; ++i )
8601 DisplayWriteFieldInt( m_Start, mapList[i].m_Start,
8602 SparseVTableMap::Entry, EECLASSES );
8603 DisplayWriteFieldInt( m_Span, mapList[i].m_Span,
8604 SparseVTableMap::Entry, EECLASSES );
8605 DisplayWriteFieldInt( m_Span, mapList[i].m_MapTo,
8606 SparseVTableMap::Entry, EECLASSES );
8609 DisplayEndArray( "Total Entries", EECLASSES ); //m_MapList
8611 DisplayWriteFieldInt( m_MapEntries, sparseVTMap->m_MapEntries,
8612 SparseVTableMap, EECLASSES );
8613 DisplayWriteFieldInt( m_Allocated, sparseVTMap->m_Allocated,
8614 SparseVTableMap, EECLASSES );
8615 DisplayWriteFieldInt( m_LastUsed, sparseVTMap->m_LastUsed,
8616 SparseVTableMap, EECLASSES );
8617 DisplayWriteFieldInt( m_VTSlot, sparseVTMap->m_VTSlot,
8618 SparseVTableMap, EECLASSES );
8619 DisplayWriteFieldInt( m_MTSlot, sparseVTMap->m_MTSlot,
8620 SparseVTableMap, EECLASSES );
8622 DisplayEndStructure( EECLASSES ); //SparseVTableMap
8625 WriteFieldTypeHandle( m_pCoClassForIntf, pClassOptional->m_pCoClassForIntf,
8626 EEClassOptionalFields, EECLASSES );
8628 PTR_ClassFactoryBase classFactory(TO_TADDR(pClassOptional->m_pClassFactory));
8629 if( classFactory != NULL )
8631 DisplayWriteFieldPointer( m_pClassFactory, NULL, EEClassOptionalFields,
8636 /* REVISIT_TODO Fri 10/14/2005
8637 * Dump ComClassFactory
8639 DisplayWriteFieldPointer( m_pClassFactory,
8640 DPtrToPreferredAddr(classFactory),
8641 EEClassOptionalFields, EECLASSES );
8643 #endif // FEATURE_COMINTEROP
8645 PTR_DictionaryLayout layout = pClassOptional->m_pDictLayout;
8646 if( layout == NULL )
8648 DisplayWriteFieldPointer( m_pDictLayout, NULL, EEClassOptionalFields, EECLASSES );
8652 IF_OPT(VERBOSE_TYPES)
8654 WriteFieldDictionaryLayout( "m_pDictLayout",
8655 offsetof(EEClassOptionalFields, m_pDictLayout),
8656 fieldsize(EEClassOptionalFields, m_pDictLayout),
8657 layout, GetDependencyFromMT(mt)->pImport );
8661 while( layout != NULL )
8663 CoverageRead( PTR_TO_TADDR(layout),
8664 sizeof(DictionaryLayout)
8665 + sizeof(DictionaryEntryLayout)
8666 * (layout->m_numSlots - 1) );
8667 layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
8671 PTR_BYTE varianceInfo = pClassOptional->GetVarianceInfo();
8672 if( varianceInfo == NULL )
8674 DisplayWriteFieldPointer( m_pVarianceInfo, NULL,
8675 EEClassOptionalFields, EECLASSES );
8679 /* REVISIT_TODO Fri 10/14/2005
8680 * Dump variance info
8682 DisplayWriteFieldPointer( m_pVarianceInfo,
8683 DPtrToPreferredAddr(varianceInfo), EEClassOptionalFields,
8687 DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID,
8688 EEClassOptionalFields, EECLASSES );
8690 DisplayEndStructure( EECLASSES ); // EEClassOptionalFields
8692 } // NativeImageDumper::DumpEEClassForMethodTable
8694 #pragma warning(pop)
8700 TDT_IsParamTypeDesc,
8701 TDT_IsArrayTypeDesc,
8702 TDT_IsTypeVarTypeDesc,
8705 const char * const g_typeDescTypeNames[] =
8713 int g_typeDescSizes[] =
8716 sizeof(ParamTypeDesc),
8717 sizeof(ArrayTypeDesc),
8718 sizeof(TypeVarTypeDesc),
8719 -1//sizeof(FnPtrTypeDesc) -- variable size
8721 TypeDescType getTypeDescType( PTR_TypeDesc td )
8723 _ASSERTE(td != NULL);
8725 return TDT_IsArrayTypeDesc;
8726 if( td->HasTypeParam() )
8727 return TDT_IsParamTypeDesc;
8728 if( td->IsGenericVariable() )
8729 return TDT_IsTypeVarTypeDesc;
8730 if( td->GetInternalCorElementType() == ELEMENT_TYPE_FNPTR )
8731 return TDT_IsFnPtrTypeDesc;
8732 return TDT_IsTypeDesc;
8734 NativeImageDumper::EnumMnemonics NativeImageDumper::s_TDFlags[] =
8737 #define TDF_ENTRY(x) NativeImageDumper::EnumMnemonics(TypeDesc:: x, W(#x) )
8738 TDF_ENTRY(enum_flag_NeedsRestore),
8739 TDF_ENTRY(enum_flag_PreRestored),
8740 TDF_ENTRY(enum_flag_Unrestored),
8741 TDF_ENTRY(enum_flag_UnrestoredTypeKey),
8742 TDF_ENTRY(enum_flag_IsNotFullyLoaded),
8743 TDF_ENTRY(enum_flag_DependenciesLoaded),
8747 NativeImageDumper::EnumMnemonics s_CConv[] =
8749 #define CC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
8751 #define CC_CALLCONV_ENTRY(x) NativeImageDumper::EnumMnemonics( x, IMAGE_CEE_CS_CALLCONV_MASK, W(#x) )
8752 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_VARARG),
8753 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_FIELD),
8754 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG),
8755 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_PROPERTY),
8756 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_UNMGD),
8757 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERICINST),
8758 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_NATIVEVARARG),
8759 #undef CC_CALLCONV_ENTRY
8761 CC_ENTRY(IMAGE_CEE_CS_CALLCONV_HASTHIS),
8762 CC_ENTRY(IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS),
8763 CC_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERIC)
8767 void NativeImageDumper::DumpTypeDesc( PTR_TypeDesc td )
8769 _ASSERTE(CHECK_OPT(TYPEDESCS));
8770 TypeDescType tdt = getTypeDescType(td);
8771 int size = g_typeDescSizes[(int)tdt];
8774 _ASSERTE(tdt == TDT_IsFnPtrTypeDesc);
8775 size = FnPtrTypeDesc::DacSize(PTR_TO_TADDR(td));
8777 DisplayStartStructure( g_typeDescTypeNames[(int)tdt],
8778 DPtrToPreferredAddr(td), size, TYPEDESCS );
8780 //first handle the fields of typedesc
8781 WriteFieldCorElementType( m_typeAndFlags, td->GetInternalCorElementType(),
8782 TypeDesc, TYPEDESCS );
8783 DisplayWriteFieldEnumerated( m_typeAndFlags, td->m_typeAndFlags, TypeDesc,
8784 s_TDFlags, W(", "), TYPEDESCS );
8785 if( tdt == TDT_IsParamTypeDesc || tdt == TDT_IsArrayTypeDesc )
8787 PTR_ParamTypeDesc ptd(td);
8788 DisplayStartVStructure( "ParamTypeDesc", TYPEDESCS );
8789 WriteFieldMethodTable( m_TemplateMT, ptd->GetTemplateMethodTableInternal(),
8790 ParamTypeDesc, TYPEDESCS );
8791 WriteFieldTypeHandle( m_Arg, ptd->m_Arg,
8792 ParamTypeDesc, TYPEDESCS );
8793 DisplayWriteFieldPointer( m_hExposedClassObject,
8794 DataPtrToDisplay(ptd->m_hExposedClassObject),
8795 ParamTypeDesc, TYPEDESCS );
8797 DisplayEndVStructure( TYPEDESCS ); //ParamTypeDesc
8799 else if( tdt == TDT_IsFnPtrTypeDesc )
8801 PTR_FnPtrTypeDesc ftd(td);
8802 DisplayStartVStructure( "FnPtrTypeDesc", TYPEDESCS );
8803 DisplayWriteFieldInt( m_NumArgs, ftd->m_NumArgs, FnPtrTypeDesc,
8805 DisplayWriteFieldEnumerated( m_CallConv, ftd->m_CallConv,
8806 FnPtrTypeDesc, s_CConv, W(", "),
8808 DisplayStartArrayWithOffset( m_RetAndArgTypes, W("[%-4s]: %s"),
8809 FnPtrTypeDesc, TYPEDESCS );
8810 PTR_TypeHandle args( PTR_HOST_MEMBER_TADDR(FnPtrTypeDesc, ftd,
8811 m_RetAndArgTypes) );
8812 for( unsigned i = 0; i < ftd->m_NumArgs; ++i )
8814 DisplayStartElement( "Argument", TYPEDESCS );
8815 DisplayWriteElementInt( "Index", i, TYPEDESCS );
8817 WriteElementTypeHandle( "TypeHandle", args[i] );
8818 DisplayEndElement( TYPEDESCS );
8820 DisplayEndArray( "Total Arguments", TYPEDESCS );
8821 DisplayEndVStructure( TYPEDESCS );
8823 else if( tdt == TDT_IsTypeVarTypeDesc )
8825 PTR_TypeVarTypeDesc tvtd(td);
8826 DisplayStartVStructure( "TypeVarTypeDesc", TYPEDESCS );
8827 DisplayWriteFieldPointer( m_pModule,
8828 DPtrToPreferredAddr(tvtd->GetModule()),
8829 TypeVarTypeDesc, TYPEDESCS );
8830 DisplayWriteFieldUInt( m_typeOrMethodDef,
8831 tvtd->m_typeOrMethodDef,
8832 TypeVarTypeDesc, TYPEDESCS );
8833 DisplayWriteFieldInt( m_numConstraints, tvtd->m_numConstraints,
8834 TypeVarTypeDesc, TYPEDESCS );
8835 if( tvtd->m_constraints == NULL )
8837 DisplayWriteFieldPointer( m_constraints, NULL, TypeVarTypeDesc,
8842 DisplayStartStructureWithOffset( m_constraints,
8843 DPtrToPreferredAddr(tvtd->m_constraints),
8844 sizeof(*tvtd->m_constraints) *
8845 tvtd->m_numConstraints,
8846 TypeVarTypeDesc, TYPEDESCS );
8847 DisplayStartArray( "Constraints", NULL, TYPEDESCS );
8848 for( unsigned i = 0; i < tvtd->m_numConstraints; ++i )
8850 WriteElementTypeHandle( "TypeHandle", tvtd->m_constraints[i] );
8852 DisplayEndArray( "Total Constraints", TYPEDESCS ); //Constraints
8853 DisplayEndStructure( TYPEDESCS ); //m_constraints
8855 DisplayWriteFieldPointer( m_hExposedClassObject,
8856 DataPtrToDisplay(tvtd->m_hExposedClassObject),
8857 TypeVarTypeDesc, TYPEDESCS );
8858 DisplayWriteFieldUInt( m_token, tvtd->m_token, TypeVarTypeDesc,
8860 DisplayWriteFieldInt( m_index, tvtd->m_index, TypeVarTypeDesc,
8863 DisplayEndVStructure( TYPEDESCS ); //TypeVarTypeDesc
8867 DisplayEndStructure( TYPEDESCS ); // g_typeDescTypeNames
8871 void NativeImageDumper::DumpDictionaryEntry( const char * elementName,
8872 DictionaryEntryKind kind,
8873 PTR_DictionaryEntry entry )
8875 m_display->StartElement( elementName );
8876 const char * name = NULL;
8880 m_display->WriteEmptyElement("EmptySlot");
8882 case TypeHandleSlot:
8884 TypeHandle th = dac_cast<DPTR(FixupPointer<TypeHandle>)>(entry)->GetValue();
8885 WriteElementTypeHandle( "TypeHandle", th );
8886 /* XXX Fri 03/24/2006
8887 * There is no straightforward home for these, so make sure to
8890 if( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc() )
8892 PTR_TypeDesc td(th.AsTypeDesc());
8893 if( isInRange(PTR_TO_TADDR(td)) )
8895 m_discoveredTypeDescs.AppendEx(td);
8900 case MethodDescSlot:
8903 PTR_MethodDesc md(TO_TADDR(*entry));
8904 WriteElementMethodDesc( "MethodDesc", md );
8907 case MethodEntrySlot:
8908 name = "MethodEntry";
8909 goto StandardEntryDisplay;
8910 case ConstrainedMethodEntrySlot:
8911 name = "ConstrainedMethodEntry";
8912 goto StandardEntryDisplay;
8913 case DispatchStubAddrSlot:
8914 name = "DispatchStubAddr";
8915 goto StandardEntryDisplay;
8916 /* REVISIT_TODO Tue 10/11/2005
8917 * Print out name information here
8920 name = "FieldDescSlot";
8921 StandardEntryDisplay:
8922 m_display->WriteElementPointer(name, DataPtrToDisplay((TADDR)*entry));
8925 _ASSERTE( !"unreachable" );
8927 m_display->EndElement(); //elementName
8930 #ifdef FEATURE_READYTORUN
8931 IMAGE_DATA_DIRECTORY * NativeImageDumper::FindReadyToRunSection(DWORD type)
8933 PTR_READYTORUN_SECTION pSections = dac_cast<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(m_pReadyToRunHeader) + sizeof(READYTORUN_HEADER));
8934 for (DWORD i = 0; i < m_pReadyToRunHeader->NumberOfSections; i++)
8936 // Verify that section types are sorted
8937 _ASSERTE(i == 0 || (pSections[i - 1].Type < pSections[i].Type));
8939 READYTORUN_SECTION * pSection = pSections + i;
8940 if (pSection->Type == type)
8941 return &pSection->Section;
8947 // Ready to Run specific dumping methods
8949 void NativeImageDumper::DumpReadyToRun()
8951 m_pReadyToRunHeader = m_decoder.GetReadyToRunHeader();
8953 m_nativeReader = NativeFormat::NativeReader(dac_cast<PTR_BYTE>(m_decoder.GetBase()), m_decoder.GetVirtualSize());
8955 IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindReadyToRunSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS);
8956 if (pRuntimeFunctionsDir != NULL)
8958 m_pRuntimeFunctions = dac_cast<PTR_RUNTIME_FUNCTION>(m_decoder.GetDirectoryData(pRuntimeFunctionsDir));
8959 m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION);
8963 m_nRuntimeFunctions = 0;
8966 IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindReadyToRunSection(READYTORUN_SECTION_METHODDEF_ENTRYPOINTS);
8967 if (pEntryPointsDir != NULL)
8968 m_methodDefEntryPoints = NativeFormat::NativeArray((TADDR)&m_nativeReader, pEntryPointsDir->VirtualAddress);
8970 DisplayStartCategory("NativeInfo", NATIVE_INFO);
8973 DumpReadyToRunHeader();
8975 DisplayEndCategory(NATIVE_INFO); //NativeInfo
8977 IF_OPT_OR3(METHODS, GC_INFO, DISASSEMBLE_CODE)
8978 DumpReadyToRunMethods();
8984 const NativeImageDumper::EnumMnemonics s_ReadyToRunFlags[] =
8986 #define RTR_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
8987 RTR_FLAGS(READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE),
8991 void NativeImageDumper::DumpReadyToRunHeader()
8995 m_display->StartStructure( "READYTORUN_HEADER",
8996 DPtrToPreferredAddr(dac_cast<PTR_READYTORUN_HEADER>(m_pReadyToRunHeader)),
8997 sizeof(*m_pReadyToRunHeader) );
8999 DisplayWriteFieldUInt( Signature, m_pReadyToRunHeader->Signature, READYTORUN_HEADER, ALWAYS );
9000 DisplayWriteFieldUInt( MajorVersion, m_pReadyToRunHeader->MajorVersion, READYTORUN_HEADER, ALWAYS );
9001 DisplayWriteFieldUInt( MinorVersion, m_pReadyToRunHeader->MinorVersion, READYTORUN_HEADER, ALWAYS );
9003 DisplayWriteFieldEnumerated( Flags, m_pReadyToRunHeader->Flags,
9004 READYTORUN_HEADER, s_ReadyToRunFlags, W(", "),
9007 m_display->EndStructure(); //READYTORUN_HEADER
9011 void NativeImageDumper::DumpReadyToRunMethods()
9013 DisplayStartArray("Methods", NULL, METHODS);
9015 for (uint rid = 1; rid <= m_methodDefEntryPoints.GetCount(); rid++)
9018 if (!m_methodDefEntryPoints.TryGetAt(rid - 1, &offset))
9022 offset = m_nativeReader.DecodeUnsigned(offset, &id);
9029 m_nativeReader.DecodeUnsigned(offset, &val);
9033 // TODO: Dump fixups from dac_cast<TADDR>(m_pLayout->GetBase()) + offset
9042 _ASSERTE(id < m_nRuntimeFunctions);
9043 PTR_RUNTIME_FUNCTION pRuntimeFunction = m_pRuntimeFunctions + id;
9044 PCODE pEntryPoint = dac_cast<TADDR>(m_decoder.GetBase()) + pRuntimeFunction->BeginAddress;
9047 AppendTokenName(TokenFromRid(rid, mdtMethodDef), buf, m_import);
9049 DumpReadyToRunMethod(pEntryPoint, pRuntimeFunction, buf);
9052 DisplayEndArray("Total Methods", METHODS); //Methods
9055 extern PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntimeFunction, /* out */ SIZE_T * pSize);
9057 void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNCTION pRuntimeFunction, SString& name)
9059 //Read the GCInfo to get the total method size.
9060 unsigned methodSize = 0;
9061 unsigned gcInfoSize = UINT_MAX;
9063 SIZE_T nUnwindDataSize;
9064 PTR_VOID pUnwindData = GetUnwindDataBlob(dac_cast<TADDR>(m_decoder.GetBase()), pRuntimeFunction, &nUnwindDataSize);
9066 // GCInfo immediatelly follows unwind data
9067 PTR_CBYTE gcInfo = dac_cast<PTR_CBYTE>(pUnwindData) + nUnwindDataSize;
9069 void(*stringOutFn)(const char *, ...);
9072 stringOutFn = stringOut;
9076 stringOutFn = nullStringOut;
9080 PTR_CBYTE curGCInfoPtr = gcInfo;
9081 g_holdStringOutData.Clear();
9082 GCDump gcDump(GCINFO_VERSION);
9083 gcDump.gcPrintf = stringOutFn;
9084 UINT32 r2rversion = m_pReadyToRunHeader->MajorVersion;
9085 UINT32 gcInfoVersion = GCInfoToken::ReadyToRunVersionToGcInfoVersion(r2rversion);
9086 GCInfoToken gcInfoToken = { curGCInfoPtr, gcInfoVersion };
9088 #if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
9089 GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
9090 methodSize = gcInfoDecoder.GetCodeLength();
9093 //dump the data to a string first so we can get the gcinfo size.
9096 stringOutFn("method info Block:\n");
9097 curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0);
9104 stringOutFn("PointerTable:\n");
9105 curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9108 gcInfoSize = curGCInfoPtr - gcInfo;
9109 #elif defined(USE_GC_INFO_DECODER)
9110 stringOutFn("PointerTable:\n");
9111 curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9113 gcInfoSize = (unsigned)(curGCInfoPtr - gcInfo);
9117 //data is output below.
9120 DisplayStartElement("Method", METHODS);
9121 DisplayWriteElementStringW("Name", (const WCHAR *)name, METHODS);
9123 DisplayStartStructure("GCInfo",
9124 DPtrToPreferredAddr(gcInfo),
9128 DisplayStartTextElement("Contents", GC_INFO);
9129 DisplayWriteXmlTextBlock(("%S", (const WCHAR *)g_holdStringOutData), GC_INFO);
9130 DisplayEndTextElement(GC_INFO); //Contents
9132 DisplayEndStructure(METHODS); //GCInfo
9134 DisplayStartStructure("Code", DataPtrToDisplay(pEntryPoint), methodSize,
9137 IF_OPT(DISASSEMBLE_CODE)
9139 // Disassemble hot code. Read the code into the host process.
9140 /* REVISIT_TODO Mon 10/24/2005
9141 * Is this align up right?
9143 BYTE * codeStartHost =
9144 reinterpret_cast<BYTE*>(PTR_READ(pEntryPoint,
9145 (ULONG32)ALIGN_UP(methodSize,
9147 DisassembleMethod(codeStartHost, methodSize);
9150 DisplayEndStructure(METHODS); //Code
9152 DisplayEndElement(METHODS); //Method
9154 #endif // FEATURE_READYTORUN
9157 void NativeImageDumper::RecordTypeRef( mdTypeRef token, PTR_MethodTable mt )
9160 m_mtToTypeRefMap.Add( mt, token );
9162 mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt )
9164 return m_mtToTypeRefMap.Find(mt);
9168 #else //!FEATURE_PREJIT
9169 //dummy implementation for dac
9170 HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase,
9172 IXCLRDataDisplay* display,
9173 IXCLRLibrarySupport* support,
9174 IXCLRDisassemblySupport* dis)
9178 #endif //FEATURE_PREJIT
9180 /* REVISIT_TODO Mon 10/10/2005
9181 * Here is where it gets bad. There is no DAC build of gcdump, so instead
9182 * build it directly into the the dac. That's what all these ugly defines
9186 #pragma warning(disable:4244) // conversion from 'unsigned int' to 'unsigned short', possible loss of data
9187 #pragma warning(disable:4189) // local variable is initialized but not referenced
9193 #define GC_NOTRIGGER
9194 #include <gcdecoder.cpp>
9198 #if defined _DEBUG && defined _TARGET_X86_
9200 // disable FPO for checked build
9201 #pragma optimize("y", off)
9206 #define _ASSERTE(a) do {} while (0)
9208 #include <gcdump.cpp>
9211 #undef LIMITED_METHOD_CONTRACT
9212 #undef WRAPPER_NO_CONTRACT
9214 #include <i386/gcdumpx86.cpp>
9215 #else // !_TARGET_X86_
9217 #include <gcdumpnonx86.cpp>
9218 #endif // !_TARGET_X86_
9221 #pragma warning(default:4244)
9222 #pragma warning(default:4189)