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 precodeName = "FixupPrecode"; break;
3490 #endif // HAS_FIXUP_PRECODE
3491 #ifdef HAS_THISPTR_RETBUF_PRECODE
3492 case PRECODE_THISPTR_RETBUF:
3493 precodeName = "ThisPtrRetBufPrecode"; break;
3494 #endif // HAS_THISPTR_RETBUF_PRECODE
3500 precodeBuf.AppendPrintf( W("%S (0x%p)"), precodeName, addr );
3502 //get MethodDesc from precode and dump the target
3503 PTR_MethodDesc precodeMD(maybePrecode->GetMethodDesc());
3504 precodeBuf.Append( W(" for ") );
3505 MethodDescToString(precodeMD, precodeBuf);
3507 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)precodeBuf);
3510 return wcslen(name);
3514 PTR_CORCOMPILE_IMPORT_SECTION pImportSection = m_decoder.GetNativeImportSectionForRVA(rva);
3515 if (pImportSection != NULL)
3517 const char * wbRangeName = NULL;
3518 switch (pImportSection->Type)
3520 case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
3521 wbRangeName = "ExternalMethod";
3525 case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
3526 wbRangeName = "VirtualMethod";
3529 case CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH:
3530 wbRangeName = "StubDispatch";
3534 // This method is only ever called for targets of direct calls right now and so the only
3535 // import that can meaninfully show up here is external method thunk.
3540 TempBuffer fixupThunkBuf;
3541 fixupThunkBuf.AppendPrintf( W("%S (0x%p) for "), wbRangeName, addr );
3542 FixupThunkToString(pImportSection, (TADDR)addr, fixupThunkBuf);
3544 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)fixupThunkBuf);
3547 return wcslen(name);
3550 else if( g_dacImpl->GetJitHelperFunctionName(addr,
3551 _countof(bigByteBuffer),
3552 (char*)bigByteBuffer,
3556 _snwprintf_s( name, nameSize, _TRUNCATE, W("%S"), bigByteBuffer );
3557 return wcslen(name);
3562 if( m_mscorwksBase <= addr &&
3563 addr < (m_mscorwksBase + m_mscorwksSize) )
3565 *offset = addr - m_mscorwksBase;
3566 _snwprintf_s( name, nameSize, _TRUNCATE, W("clr") );
3567 return wcslen(name);
3569 for( COUNT_T i = 0; i < m_numDependencies; ++i )
3571 const Dependency& dep = m_dependencies[i];
3572 if( dep.pLoadedAddress <= addr &&
3573 addr < (dep.pLoadedAddress + dep.size) )
3575 *offset = addr - dep.pLoadedAddress;
3576 _snwprintf_s( name, nameSize, _TRUNCATE, W("%s.ni"), dep.name );
3577 return wcslen(name);
3585 BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
3587 PTR_SIZE_T fixupPtr(TO_TADDR(fixupCell));
3588 m_display->StartElement( "Fixup" );
3589 m_display->WriteElementPointer( "Address",
3590 DataPtrToDisplay( TO_TADDR(fixupCell) ) );
3591 m_display->WriteElementUInt( "TaggedValue", (DWORD)*fixupPtr );
3592 WriteElementsFixupBlob(pSection, *fixupPtr);
3593 m_display->EndElement();
3598 void NativeImageDumper::DumpMethodFixups(PTR_Module module,
3601 _ASSERTE( CHECK_OPT(METHODS) );
3603 COUNT_T nImportSections;
3604 PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
3606 //create the first element outside of the callback. The callback creates
3607 //subsequent elements.
3608 module->FixupDelayListAux( fixupList, this,
3609 &NativeImageDumper::HandleFixupForMethodDump,
3610 pImportSections, nImportSections,
3614 IMAGE_SECTION_HEADER * NativeImageDumper::FindSection( char const * name )
3616 COUNT_T numberOfSections = m_decoder.GetNumberOfSections();
3617 PTR_IMAGE_SECTION_HEADER curSection( m_decoder.FindFirstSection() );
3619 for ( ; numberOfSections > 0; --numberOfSections, ++curSection )
3621 if ( ! strncmp( reinterpret_cast< char * >( curSection->Name ), name, 8 ) )
3625 if ( ! numberOfSections )
3631 NativeImageDumper::EnumMnemonics NativeImageDumper::s_ModulePersistedFlags[] =
3633 #define MPF_ENTRY(f) NativeImageDumper::EnumMnemonics(Module::f, W(#f))
3634 MPF_ENTRY(COMPUTED_GLOBAL_CLASS),
3636 MPF_ENTRY(COMPUTED_STRING_INTERNING),
3637 MPF_ENTRY(NO_STRING_INTERNING),
3639 MPF_ENTRY(COMPUTED_WRAP_EXCEPTIONS),
3640 MPF_ENTRY(WRAP_EXCEPTIONS),
3642 MPF_ENTRY(COMPUTED_RELIABILITY_CONTRACT),
3644 MPF_ENTRY(COLLECTIBLE_MODULE),
3645 MPF_ENTRY(COMPUTED_IS_PRE_V4_ASSEMBLY),
3646 MPF_ENTRY(IS_PRE_V4_ASSEMBLY),
3647 MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED),
3648 MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS),
3650 MPF_ENTRY(COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP),
3651 MPF_ENTRY(LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME),
3655 //VirtualSectionTypes.
3656 #define TEXTIFY(x) W(#x)
3657 static const NativeImageDumper::EnumMnemonics s_virtualSectionFlags [] =
3660 #define CORCOMPILE_SECTION_IBCTYPE(ibcType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(ibcType)),
3661 CORCOMPILE_SECTION_IBCTYPES()
3662 #undef CORCOMPILE_SECTION_IBCTYPE
3664 #define CORCOMPILE_SECTION_RANGE_TYPE(rangeType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(rangeType) W("Range")),
3665 CORCOMPILE_SECTION_RANGE_TYPES()
3666 #undef CORCOMPILE_SECTION_RANGE_TYPE
3668 const WCHAR * g_sectionNames[] =
3670 W("SECTION_DUMMY"), // the first section start at 0x1. Make the array 1 based.
3671 #define CORCOMPILE_SECTION_TYPE(section) W("SECTION_") TEXTIFY(section),
3672 CORCOMPILE_SECTION_TYPES()
3673 #undef CORCOMPILE_SECTION
3680 #pragma warning(push)
3681 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3684 void NativeImageDumper::DumpModule( PTR_Module module )
3687 //the module is the fisrt thing in the .data section. We use this fact for
3688 //the sectionBases down below.
3689 // _ASSERTE(m_decoder.GetDataRva(PTR_TO_TADDR(module))
3690 // == FindSection(".data")->VirtualAddress );
3692 DisplayStartStructure( "module", DPtrToPreferredAddr(module),
3693 sizeof(*module), MODULE );
3694 PTR_PEFile file = module->m_file;
3695 _ASSERTE(file == NULL);
3696 DisplayWriteFieldPointer( m_file, DPtrToPreferredAddr(file), Module,
3699 PTR_MethodDesc dllMain( TO_TADDR(module->m_pDllMain) );
3700 WriteFieldMethodDesc( m_pDllMain, dllMain, Module,
3703 _ASSERTE(module->m_dwTransientFlags == 0U);
3704 DisplayWriteFieldUInt(m_dwTransientFlags, module->m_dwTransientFlags,
3709 DisplayWriteFieldEnumerated( m_dwPersistedFlags, module->m_dwPersistedFlags,
3710 Module, s_ModulePersistedFlags, W("|"), MODULE );
3712 DisplayWriteFieldPointer( m_pAssembly,
3713 DPtrToPreferredAddr(module->m_pAssembly),
3715 _ASSERTE(module->m_pAssembly == NULL); //never appears in the image
3717 DisplayWriteFieldUInt( m_moduleRef, module->m_moduleRef, Module, MODULE );
3718 DisplayWriteFieldInt( m_dwDebuggerJMCProbeCount,
3719 module->m_dwDebuggerJMCProbeCount, Module, MODULE );
3720 /* REVISIT_TODO Fri 10/14/2005
3723 PTR_MscorlibBinder binder = module->m_pBinder;
3724 if( NULL != binder )
3726 DisplayStartStructureWithOffset( m_pBinder, DPtrToPreferredAddr(binder),
3727 sizeof(*binder), Module,
3730 //these four fields don't have anything useful in ngen images.
3731 DisplayWriteFieldPointer( m_classDescriptions,
3732 DPtrToPreferredAddr(binder->m_classDescriptions),
3733 MscorlibBinder, MODULE );
3734 DisplayWriteFieldPointer( m_methodDescriptions,
3735 DPtrToPreferredAddr(binder->m_methodDescriptions),
3736 MscorlibBinder, MODULE );
3737 DisplayWriteFieldPointer( m_fieldDescriptions,
3738 DPtrToPreferredAddr(binder->m_fieldDescriptions),
3739 MscorlibBinder, MODULE );
3740 DisplayWriteFieldPointer( m_pModule,
3741 DPtrToPreferredAddr(binder->m_pModule),
3742 MscorlibBinder, MODULE );
3744 DisplayWriteFieldInt( m_cClasses, binder->m_cClasses, MscorlibBinder,
3746 DisplayWriteFieldAddress( m_pClasses,
3747 DPtrToPreferredAddr(binder->m_pClasses),
3748 sizeof(*binder->m_pClasses)
3749 * binder->m_cClasses,
3750 MscorlibBinder, MODULE );
3751 DisplayWriteFieldInt( m_cFields, binder->m_cFields, MscorlibBinder,
3753 DisplayWriteFieldAddress( m_pFields,
3754 DPtrToPreferredAddr(binder->m_pFields),
3755 sizeof(*binder->m_pFields)
3756 * binder->m_cFields,
3757 MscorlibBinder, MODULE );
3758 DisplayWriteFieldInt( m_cMethods, binder->m_cMethods, MscorlibBinder,
3760 DisplayWriteFieldAddress( m_pMethods,
3761 DPtrToPreferredAddr(binder->m_pMethods),
3762 sizeof(*binder->m_pMethods)
3763 * binder->m_cMethods,
3764 MscorlibBinder, MODULE );
3766 DisplayEndStructure( MODULE ); //m_pBinder
3770 DisplayWriteFieldPointer( m_pBinder, NULL, Module, MODULE );
3774 /* REVISIT_TODO Tue 10/25/2005
3775 * unconditional dependencies, activations, class dependencies, thunktable
3779 //round trip the LookupMap back through the DAC so that we don't have an
3780 //interior host pointer.
3781 PTR_LookupMapBase lookupMap( PTR_TO_TADDR(module)
3782 + offsetof(Module, m_TypeDefToMethodTableMap) );
3783 TraverseMap( lookupMap, "m_TypeDefToMethodTableMap",
3784 offsetof(Module, m_TypeDefToMethodTableMap),
3785 fieldsize(Module, m_TypeDefToMethodTableMap),
3786 &NativeImageDumper::IterateTypeDefToMTCallback );
3788 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3789 + offsetof(Module, m_TypeRefToMethodTableMap) );
3791 TraverseMap( lookupMap, "m_TypeRefToMethodTableMap",
3792 offsetof(Module, m_TypeRefToMethodTableMap),
3793 fieldsize(Module, m_TypeRefToMethodTableMap),
3794 &NativeImageDumper::IterateTypeRefToMTCallback );
3796 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3797 + offsetof(Module, m_MethodDefToDescMap) );
3798 TraverseMap( lookupMap, "m_MethodDefToDescMap",
3799 offsetof(Module, m_MethodDefToDescMap),
3800 fieldsize(Module, m_MethodDefToDescMap),
3801 &NativeImageDumper::IterateMethodDefToMDCallback);
3803 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3804 + offsetof(Module, m_FieldDefToDescMap) );
3805 TraverseMap( lookupMap, "m_FieldDefToDescMap",
3806 offsetof(Module, m_FieldDefToDescMap),
3807 fieldsize(Module, m_FieldDefToDescMap),
3808 &NativeImageDumper::IterateFieldDefToFDCallback);
3810 TraverseMemberRefToDescHash(module->m_pMemberRefToDescHashTable, "m_pMemberRefToDescHashTable",
3811 offsetof(Module, m_pMemberRefToDescHashTable),
3812 fieldsize(Module, m_pMemberRefToDescHashTable),
3815 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3816 + offsetof(Module, m_GenericParamToDescMap) );
3818 TraverseMap( lookupMap, "m_GenericParamToDescMap",
3819 offsetof(Module, m_GenericParamToDescMap),
3820 fieldsize(Module, m_GenericParamToDescMap),
3821 &NativeImageDumper::IterateGenericParamToDescCallback);
3823 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3824 + offsetof(Module, m_GenericTypeDefToCanonMethodTableMap) );
3826 TraverseMap( lookupMap, "m_GenericTypeDefToCanonMethodTableMap",
3827 offsetof(Module, m_GenericTypeDefToCanonMethodTableMap),
3828 fieldsize(Module, m_GenericTypeDefToCanonMethodTableMap),
3829 &NativeImageDumper::IterateTypeDefToMTCallback );
3831 lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3832 + offsetof(Module, m_FileReferencesMap) );
3833 TraverseMap( lookupMap, "m_FileReferencesMap",
3834 offsetof(Module, m_FileReferencesMap),
3835 fieldsize(Module, m_FileReferencesMap),
3836 &NativeImageDumper::IterateMemberRefToDescCallback);
3838 lookupMap = PTR_LookupMapBase(PTR_TO_TADDR(module)
3839 + offsetof(Module,m_ManifestModuleReferencesMap));
3841 TraverseMap( lookupMap, "m_ManifestModuleReferencesMap",
3842 offsetof(Module, m_ManifestModuleReferencesMap),
3843 fieldsize(Module, m_ManifestModuleReferencesMap),
3844 &NativeImageDumper::IterateManifestModules);
3846 TraverseClassHash( module->m_pAvailableClasses, "m_pAvailableClasses",
3847 offsetof(Module, m_pAvailableClasses),
3848 fieldsize(Module, m_pAvailableClasses), true );
3850 TraverseTypeHash( module->m_pAvailableParamTypes, "m_pAvailableParamTypes",
3851 offsetof(Module, m_pAvailableParamTypes),
3852 fieldsize(Module, m_pAvailableParamTypes) );
3853 TraverseInstMethodHash( module->m_pInstMethodHashTable,
3854 "m_pInstMethodHashTable",
3855 offsetof(Module, m_pInstMethodHashTable),
3856 fieldsize(Module, m_pInstMethodHashTable),
3858 TraverseStubMethodHash( module->m_pStubMethodHashTable,
3859 "m_pStubMethodHashTable",
3860 offsetof(Module, m_pStubMethodHashTable),
3861 fieldsize(Module, m_pStubMethodHashTable),
3866 TraverseClassHash( module->m_pAvailableClassesCaseIns,
3867 "m_pAvailableClassesCaseIns",
3868 offsetof(Module, m_pAvailableClassesCaseIns),
3869 fieldsize(Module, m_pAvailableClassesCaseIns),
3873 #ifdef FEATURE_COMINTEROP
3874 TraverseGuidToMethodTableHash( module->m_pGuidToTypeHash,
3875 "m_pGuidToTypeHash",
3876 offsetof(Module, m_pGuidToTypeHash),
3877 fieldsize(Module, m_pGuidToTypeHash),
3880 #endif // FEATURE_COMINTEROP
3882 _ASSERTE(module->m_pProfilingBlobTable == NULL);
3884 DisplayWriteFieldFlag( m_nativeImageProfiling,
3885 module->m_nativeImageProfiling, Module, MODULE );
3887 DisplayWriteFieldPointer( m_methodProfileList,
3888 DataPtrToDisplay((TADDR)module->m_methodProfileList),
3890 _ASSERTE(module->m_methodProfileList == NULL);
3892 /* REVISIT_TODO Tue 10/04/2005
3893 * Dump module->m_moduleCtorInfo
3895 PTR_ModuleCtorInfo ctorInfo( PTR_HOST_MEMBER_TADDR(Module, module,
3896 m_ModuleCtorInfo) );
3898 DisplayStartStructureWithOffset( m_ModuleCtorInfo,
3899 DPtrToPreferredAddr(ctorInfo),
3901 Module, SLIM_MODULE_TBLS );
3902 DisplayWriteFieldInt( numElements, ctorInfo->numElements, ModuleCtorInfo,
3904 DisplayWriteFieldInt( numLastAllocated, ctorInfo->numLastAllocated,
3905 ModuleCtorInfo, SLIM_MODULE_TBLS );
3906 DisplayWriteFieldInt( numElementsHot, ctorInfo->numElementsHot,
3907 ModuleCtorInfo, SLIM_MODULE_TBLS );
3908 DisplayWriteFieldAddress( ppMT, DPtrToPreferredAddr(ctorInfo->ppMT),
3909 ctorInfo->numElements * sizeof(RelativePointer<MethodTable*>),
3910 ModuleCtorInfo, SLIM_MODULE_TBLS );
3911 /* REVISIT_TODO Tue 03/21/2006
3912 * is cctorInfoHot and cctorInfoCold actually have anything interesting
3915 DisplayWriteFieldAddress( cctorInfoHot,
3916 DPtrToPreferredAddr(ctorInfo->cctorInfoHot),
3917 sizeof(*ctorInfo->cctorInfoHot)
3918 * ctorInfo->numElementsHot,
3919 ModuleCtorInfo, SLIM_MODULE_TBLS );
3920 DisplayWriteFieldAddress( cctorInfoCold,
3921 DPtrToPreferredAddr(ctorInfo->cctorInfoCold),
3922 sizeof(*ctorInfo->cctorInfoCold)
3923 * (ctorInfo->numElements
3924 - ctorInfo->numElementsHot),
3925 ModuleCtorInfo, SLIM_MODULE_TBLS );
3926 /* XXX Thu 03/23/2006
3927 * See ModuleCtorInfo::Save for why these are +1.
3929 DisplayWriteFieldAddress( hotHashOffsets,
3930 DPtrToPreferredAddr(ctorInfo->hotHashOffsets),
3931 (ctorInfo->numHotHashes + 1)
3932 * sizeof(*ctorInfo->hotHashOffsets),
3933 ModuleCtorInfo, SLIM_MODULE_TBLS );
3934 DisplayWriteFieldAddress( coldHashOffsets,
3935 DPtrToPreferredAddr(ctorInfo->coldHashOffsets),
3936 (ctorInfo->numColdHashes + 1)
3937 * sizeof(*ctorInfo->coldHashOffsets),
3938 ModuleCtorInfo, SLIM_MODULE_TBLS );
3940 DisplayWriteFieldInt( numHotHashes, ctorInfo->numHotHashes, ModuleCtorInfo,
3942 DisplayWriteFieldInt( numColdHashes, ctorInfo->numColdHashes,
3943 ModuleCtorInfo, SLIM_MODULE_TBLS );
3945 DisplayWriteFieldAddress( ppHotGCStaticsMTs,
3946 DPtrToPreferredAddr(ctorInfo->ppHotGCStaticsMTs),
3947 ctorInfo->numHotGCStaticsMTs
3948 * sizeof(*ctorInfo->ppHotGCStaticsMTs),
3949 ModuleCtorInfo, SLIM_MODULE_TBLS );
3950 DisplayWriteFieldAddress( ppColdGCStaticsMTs,
3951 DPtrToPreferredAddr(ctorInfo->ppColdGCStaticsMTs),
3952 ctorInfo->numColdGCStaticsMTs
3953 * sizeof(*ctorInfo->ppColdGCStaticsMTs),
3954 ModuleCtorInfo, SLIM_MODULE_TBLS );
3955 DisplayWriteFieldInt( numHotGCStaticsMTs, ctorInfo->numHotGCStaticsMTs,
3956 ModuleCtorInfo, SLIM_MODULE_TBLS );
3957 DisplayWriteFieldInt( numColdGCStaticsMTs, ctorInfo->numColdGCStaticsMTs,
3958 ModuleCtorInfo, SLIM_MODULE_TBLS );
3960 DisplayEndStructure( SLIM_MODULE_TBLS ); //m_ModuleCtorInfo
3962 _ASSERTE(module->m_pNgenStats == NULL);
3964 DisplayWriteFieldPointer( m_pNgenStats,
3965 DataPtrToDisplay((TADDR)module->m_pNgenStats),
3968 DisplayWriteFieldAddress(m_propertyNameSet,
3969 DPtrToPreferredAddr(module->m_propertyNameSet),
3970 sizeof(module->m_propertyNameSet[0]) *
3971 module->m_nPropertyNameSet,
3974 DisplayWriteFieldPointer( m_ModuleID,
3975 DataPtrToDisplay(dac_cast<TADDR>(module->m_ModuleID)),
3977 _ASSERTE(module->m_ModuleID == NULL);
3979 /* XXX Tue 04/11/2006
3980 * Value is either -1 or 0, so no need to rebase.
3982 DisplayWriteFieldPointer( m_pRegularStaticOffsets,
3983 PTR_TO_TADDR(module->m_pRegularStaticOffsets),
3985 _ASSERTE(module->m_pRegularStaticOffsets == (void*)-1
3986 || module->m_pRegularStaticOffsets == 0 );
3988 DisplayWriteFieldInt( m_dwMaxGCRegularStaticHandles,
3989 module->m_dwMaxGCRegularStaticHandles, Module, MODULE );
3990 DisplayWriteFieldInt( m_dwRegularStaticsBlockSize, module->m_dwRegularStaticsBlockSize,
3992 DisplayWriteFieldAddress( m_pDynamicStaticsInfo,
3993 DataPtrToDisplay((TADDR)module->m_pDynamicStaticsInfo),
3994 module->m_maxDynamicEntries
3995 * sizeof(*(module->m_pDynamicStaticsInfo)),
3998 DisplayWriteFieldInt( m_cDynamicEntries,
3999 (int)module->m_cDynamicEntries, Module, MODULE );
4001 CoverageRead(TO_TADDR(module->m_pDynamicStaticsInfo),
4002 (int)(module->m_maxDynamicEntries
4003 * sizeof(*(module->m_pDynamicStaticsInfo))));
4007 _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL);
4008 DisplayWriteFieldPointer( m_debuggerSpecificData.m_pDynamicILCrst,
4009 DataPtrToDisplay(dac_cast<TADDR>(module->m_debuggerSpecificData.m_pDynamicILCrst)),
4013 /* REVISIT_TODO Wed 09/21/2005
4014 * Get me in the debugger and look at the activations and module/class
4016 * As well as the thunks.
4019 /* REVISIT_TODO Wed 09/21/2005
4020 * Dump the following
4025 DisplayWriteFieldInt( m_DefaultDllImportSearchPathsAttributeValue,
4026 module->m_DefaultDllImportSearchPathsAttributeValue, Module, MODULE );
4029 DisplayEndStructure(MODULE); //Module
4032 #pragma warning(pop)
4035 bool NativeImageDumper::isPrecode(TADDR maybePrecode)
4037 PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
4039 return !!module->IsZappedPrecode(maybePrecode);
4043 void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget,
4045 PTR_LookupMapBase map,
4048 DisplayStartElement( "Entry", MODULE_TABLES );
4050 PTR_MethodTable mt(mtTarget);
4052 DisplayWriteElementUInt( "Token", rid | mdtTypeDef, MODULE_TABLES );
4053 /* REVISIT_TODO Fri 10/21/2005
4054 * Can I use WriteElementMethodTable here?
4056 DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4058 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4059 /* REVISIT_TODO Fri 09/30/2005
4060 * This handles the extra entries in the type table that shouldn't be there.
4062 if( rid == 0 || ((rid != 1) && (mtTarget == NULL)) )
4064 DisplayWriteElementString( "Name", "mdTypeDefNil", MODULE_TABLES );
4069 MethodTableToString( mt, buf );
4070 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4072 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4074 DisplayEndElement( MODULE_TABLES );
4076 if( isInRange(PTR_TO_TADDR(mt)) )
4078 m_discoveredMTs.AppendEx(mt);
4079 PTR_EEClass clazz = GetClassFromMT(mt);
4080 if( isInRange(PTR_TO_TADDR(clazz)) )
4081 m_discoveredClasses.AppendEx(mt);
4085 void NativeImageDumper::IterateTypeRefToMTCallback( TADDR mtTarget,
4087 PTR_LookupMapBase map,
4090 DisplayStartElement( "Entry", MODULE_TABLES );
4092 mtTarget = ((FixupPointer<TADDR>&)mtTarget).GetValue();
4094 PTR_MethodTable mt(mtTarget);
4097 RecordTypeRef(rid | mdtTypeRef, mt);
4100 DisplayWriteElementUInt( "Token", rid | mdtTypeRef, MODULE_TABLES );
4102 DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4107 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4108 DisplayWriteElementString( "Name", "mdtTypeRefNil", MODULE_TABLES );
4110 else if( mt == NULL )
4112 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4113 IF_OPT(MODULE_TABLES)
4114 WriteElementMDToken( "Name", mdtTypeRef | rid );
4116 else if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
4118 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
4120 // This guy writes two things FixupTargetValue and FixupTargetName
4122 WriteElementsFixupBlob( NULL,PTR_TO_TADDR(mt));
4127 MethodTableToString( mt, buf );
4128 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4129 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4131 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4133 DisplayEndElement( MODULE_TABLES );
4134 if( isInRange(mtTarget) )
4136 m_discoveredMTs.AppendEx(mt);
4137 PTR_EEClass clazz = GetClassFromMT(mt);
4138 if( isInRange(PTR_TO_TADDR(clazz)) )
4139 m_discoveredClasses.AppendEx(mt);
4143 void NativeImageDumper::IterateMethodDefToMDCallback( TADDR mdTarget,
4145 PTR_LookupMapBase map,
4148 DisplayStartElement( "Entry", MODULE_TABLES );
4150 PTR_MethodDesc md(mdTarget);
4152 DisplayWriteElementUInt( "Token", rid | mdtMethodDef, MODULE_TABLES );
4154 DisplayWriteElementPointer( "MethodDesc", DPtrToPreferredAddr(md),
4157 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4160 DisplayWriteElementString( "Name", "mdtMethodDefNil", MODULE_TABLES );
4165 MethodDescToString( md, buf );
4166 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4168 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4170 DisplayEndElement( MODULE_TABLES );
4171 //m_discoveredMDs.AppendEx(md);
4174 void NativeImageDumper::IterateFieldDefToFDCallback( TADDR fdTarget,
4176 PTR_LookupMapBase map,
4179 PTR_FieldDesc fd(fdTarget);
4180 DisplayStartElement( "Entry", MODULE_TABLES );
4183 DisplayWriteElementUInt( "Token", rid | mdtFieldDef, MODULE_TABLES );
4185 DisplayWriteElementPointer( "FieldDef", DPtrToPreferredAddr(fd),
4188 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4191 DisplayWriteElementString( "Name", "mdtFieldDefNil", MODULE_TABLES );
4196 FieldDescToString( fd, mdtFieldDef | rid, buf );
4197 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4199 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4201 DisplayEndElement( MODULE_TABLES );
4202 /* XXX Mon 10/17/2005
4203 * All FieldDescs are reachable from the EEClasses
4205 //m_discoveredFDs.AppendEx(PTR_FieldDesc(fdTarget));
4208 void NativeImageDumper::IterateMemberRefToDescCallback( TADDR mrTarget,
4210 PTR_LookupMapBase map,
4213 DisplayStartElement( "Entry", MODULE_TABLES );
4216 bool isFieldRef = (flags & IS_FIELD_MEMBER_REF) != 0;
4217 mdToken targetToken = mdtMemberRef | rid;
4218 mrTarget = ((FixupPointer<TADDR>&)mrTarget).GetValue();
4219 DisplayWriteElementUInt( "Token", targetToken, MODULE_TABLES );
4220 DisplayWriteElementPointer( isFieldRef ? "FieldDesc" : "MethodDesc",
4221 DataPtrToDisplay(mrTarget), MODULE_TABLES );
4226 buf.Append( W("mdtMemberDefNil") );
4228 else if( CORCOMPILE_IS_POINTER_TAGGED(mrTarget) )
4230 WriteElementsFixupBlob( NULL, mrTarget );
4232 else if( isFieldRef )
4234 FieldDescToString( PTR_FieldDesc(mrTarget), buf );
4238 MethodDescToString( PTR_MethodDesc(mrTarget), buf );
4240 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4241 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4243 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4245 DisplayEndElement(MODULE_TABLES);
4246 //m_discoveredMTs.AppendEx(mt);
4249 void NativeImageDumper::IterateGenericParamToDescCallback( TADDR tdTarget,
4251 PTR_LookupMapBase map,
4254 PTR_TypeDesc td(tdTarget);
4255 DisplayStartElement( "Entry", MODULE_TABLES );
4258 DisplayWriteElementUInt( "Token", rid | mdtGenericParam, MODULE_TABLES );
4260 DisplayWriteElementPointer( "GenericParam", DPtrToPreferredAddr(td),
4263 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4264 if( rid == 0 || td == NULL )
4266 DisplayWriteElementString( "Name", "mdtGenericParamNil", MODULE_TABLES );
4271 TypeDescToString( td, buf );
4272 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4274 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4276 DisplayEndElement( MODULE_TABLES );
4280 void NativeImageDumper::IterateFileReferencesCallback(TADDR moduleTarget,
4282 PTR_LookupMapBase map,
4285 DisplayStartElement( "Entry", MODULE_TABLES );
4287 PTR_Module module(moduleTarget);
4289 DisplayWriteElementUInt( "Token", rid | mdtFile, MODULE_TABLES );
4291 DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4294 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4295 if( rid == 0 || (module == NULL) )
4297 DisplayWriteElementString( "Name", "mdtFileNil", MODULE_TABLES );
4302 AppendTokenName(mdtFile | rid, buf);
4303 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4305 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4307 DisplayEndElement( MODULE_TABLES );
4308 //m_discoveredFDs.AppendEx(mt);
4312 void NativeImageDumper::IterateManifestModules( TADDR moduleTarget,
4314 PTR_LookupMapBase map,
4317 DisplayStartElement( "Entry", MODULE_TABLES );
4319 moduleTarget = ((FixupPointer<TADDR>&)moduleTarget).GetValue();
4321 PTR_Module module(moduleTarget);
4323 DisplayWriteElementUInt( "Token", rid | mdtAssemblyRef, MODULE_TABLES );
4325 DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4327 DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4328 if( rid == 0 || (module == NULL) )
4330 DisplayWriteElementString( "Name", "mdtAssemblyRefNil", MODULE_TABLES );
4335 AppendTokenName(mdtAssemblyRef | rid, buf, m_import);
4336 DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4338 DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4340 DisplayEndElement( MODULE_TABLES );
4341 //m_discoveredFDs.AppendEx(mt);
4344 void NativeImageDumper::TraverseMap(PTR_LookupMapBase map, const char * name,
4345 unsigned offset, unsigned fieldSize,
4346 void(NativeImageDumper::*cb)(TADDR,
4354 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
4357 DisplayStartVStructure(name, MODULE);
4359 DisplayStartArray( "Tables", W("%s"), MODULE );
4360 PTR_LookupMapBase current = map;
4363 DWORD cbTable = map->MapIsCompressed() ? map->cbTable : map->dwCount * sizeof(*map->pTable);
4367 DisplayWriteElementAddress( "Table",
4368 DPtrToPreferredAddr(map->pTable),
4373 CoverageRead( PTR_TO_TADDR(map->pTable), cbTable );
4374 _ASSERTE(current == map || current->hotItemList == NULL);
4375 current = current->pNext;
4376 }while( current != NULL );
4378 DisplayEndArray( "Total Tables", MODULE ); //Tables
4380 DisplayWriteFieldAddress( hotItemList,
4381 DPtrToPreferredAddr(map->hotItemList),
4382 map->dwNumHotItems * sizeof(*map->hotItemList),
4383 LookupMapBase, MODULE );
4385 DisplayStartArray( "Map", W("[%s]: %s %s%s %s %s %s"), MODULE_TABLES );
4387 IF_OPT_OR3(MODULE_TABLES, EECLASSES, METHODTABLES)
4389 LookupMap<TADDR>::Iterator iter(dac_cast<DPTR(LookupMap<TADDR>)>(map));
4394 TADDR element = iter.GetElementAndFlags(&flags);
4395 (this->*cb)( element, flags, map, rid );
4400 CoverageRead( PTR_TO_TADDR(map->hotItemList),
4401 map->dwNumHotItems * sizeof(*map->hotItemList) );
4402 DisplayEndArray( "Total" , MODULE_TABLES );//Map
4404 DisplayEndVStructure(MODULE); //name
4407 // Templated method containing the core code necessary to traverse hash tables based on NgenHash (see
4409 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4410 void NativeImageDumper::TraverseNgenHash(DPTR(HASH_CLASS) pTable,
4415 void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4421 m_display->WriteFieldPointer(name, offset, fieldSize, NULL);
4426 m_display->StartStructureWithOffset(name, offset, fieldSize,
4427 DPtrToPreferredAddr(pTable),
4428 sizeof(HASH_CLASS));
4431 DisplayWriteFieldPointer(m_pModule,
4432 DPtrToPreferredAddr(pTable->GetModule()),
4433 HASH_CLASS, MODULE);
4435 // Dump warm (volatile) entries.
4436 DisplayWriteFieldUInt(m_cWarmEntries, pTable->m_cWarmEntries, HASH_CLASS, MODULE);
4437 DisplayWriteFieldUInt(m_cWarmBuckets, pTable->m_cWarmBuckets, HASH_CLASS, MODULE);
4438 DisplayWriteFieldAddress(m_pWarmBuckets,
4439 DPtrToPreferredAddr(pTable->GetWarmBuckets()),
4440 sizeof(HASH_ENTRY_CLASS*) * pTable->m_cWarmBuckets,
4441 HASH_CLASS, MODULE);
4443 // Dump hot (persisted) entries.
4444 DPTR(typename HASH_CLASS::PersistedEntries) pHotEntries(PTR_HOST_MEMBER_TADDR(HASH_CLASS, pTable, m_sHotEntries));
4445 DisplayStartStructureWithOffset(m_sHotEntries, DPtrToPreferredAddr(pHotEntries),
4446 sizeof(typename HASH_CLASS::PersistedEntries),
4447 HASH_CLASS, MODULE);
4448 TraverseNgenPersistedEntries<HASH_CLASS, HASH_ENTRY_CLASS>(pTable, pHotEntries, saveClasses, DisplayEntryFunction, pContext);
4449 DisplayEndStructure(MODULE); // Hot entries
4451 // Dump cold (persisted) entries.
4452 DPTR(typename HASH_CLASS::PersistedEntries) pColdEntries(PTR_HOST_MEMBER_TADDR(HASH_CLASS, pTable, m_sColdEntries));
4453 DisplayStartStructureWithOffset(m_sColdEntries, DPtrToPreferredAddr(pColdEntries),
4454 sizeof(typename HASH_CLASS::PersistedEntries),
4455 HASH_CLASS, MODULE);
4456 TraverseNgenPersistedEntries<HASH_CLASS, HASH_ENTRY_CLASS>(pTable, pColdEntries, saveClasses, DisplayEntryFunction, pContext);
4457 DisplayEndStructure(MODULE); // Cold entries
4459 DisplayEndStructure(MODULE); // pTable
4462 // Helper used by TraverseNgenHash above to traverse an ngen persisted section of a table (separated out here
4463 // because NgenHash-based tables can have two such sections, one for hot and one for cold entries).
4464 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4465 void NativeImageDumper::TraverseNgenPersistedEntries(DPTR(HASH_CLASS) pTable,
4466 DPTR(typename HASH_CLASS::PersistedEntries) pEntries,
4468 void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4471 // Display top-level fields.
4472 DisplayWriteFieldUInt(m_cEntries, pEntries->m_cEntries, typename HASH_CLASS::PersistedEntries, MODULE);
4473 DisplayWriteFieldUInt(m_cBuckets, pEntries->m_cBuckets, typename HASH_CLASS::PersistedEntries, MODULE);
4474 DisplayWriteFieldAddress(m_pBuckets,
4475 DPtrToPreferredAddr(pTable->GetPersistedBuckets(pEntries)),
4476 pEntries->m_cBuckets ? pTable->GetPersistedBuckets(pEntries)->GetSize(pEntries->m_cBuckets) : 0,
4477 typename HASH_CLASS::PersistedEntries, MODULE);
4478 DisplayWriteFieldAddress(m_pEntries,
4479 DPtrToPreferredAddr(pTable->GetPersistedEntries(pEntries)),
4480 sizeof(typename HASH_CLASS::PersistedEntry) * pEntries->m_cEntries,
4481 typename HASH_CLASS::PersistedEntries, MODULE);
4483 // Display entries (or maybe just the classes referenced by those entries).
4484 DisplayStartArray("Entries", NULL, SLIM_MODULE_TBLS);
4486 // Enumerate bucket list.
4487 for (DWORD i = 0; i < pEntries->m_cBuckets; ++i)
4489 // Get index of the first entry and the count of entries in the bucket.
4490 DWORD dwEntryId, cEntries;
4491 pTable->GetPersistedBuckets(pEntries)->GetBucket(i, &dwEntryId, &cEntries);
4493 // Loop over entries.
4494 while (cEntries && (CHECK_OPT(SLIM_MODULE_TBLS)
4495 || CHECK_OPT(EECLASSES)
4496 || CHECK_OPT(METHODTABLES)))
4498 // Lookup entry in the array via the index we have.
4499 typename HASH_CLASS::PTR_PersistedEntry pEntry(PTR_TO_TADDR(pTable->GetPersistedEntries(pEntries)) +
4500 (dwEntryId * sizeof(typename HASH_CLASS::PersistedEntry)));
4502 IF_OPT(SLIM_MODULE_TBLS)
4504 DisplayStartStructure("PersistedEntry",
4505 DPtrToPreferredAddr(pEntry),
4506 sizeof(typename HASH_CLASS::PersistedEntry), SLIM_MODULE_TBLS);
4509 // Display entry via a member function specific to the type of hash table we're traversing. Each
4510 // sub-class of NgenHash hash its own entry structure that is embedded NgenHash's entry. The
4511 // helper function expects a pointer to this inner entry.
4512 DPTR(HASH_ENTRY_CLASS) pInnerEntry(PTR_TO_MEMBER_TADDR(typename HASH_CLASS::PersistedEntry, pEntry, m_sValue));
4513 (this->*DisplayEntryFunction)(pContext, pInnerEntry, saveClasses);
4515 IF_OPT(SLIM_MODULE_TBLS)
4517 DisplayWriteFieldUInt(m_iHashValue, pEntry->m_iHashValue,
4518 typename HASH_CLASS::PersistedEntry, SLIM_MODULE_TBLS);
4520 DisplayEndStructure(SLIM_MODULE_TBLS); // Entry
4528 DisplayEndArray("Total Entries", SLIM_MODULE_TBLS); // Entry array
4531 void NativeImageDumper::TraverseClassHashEntry(void *pContext, PTR_EEClassHashEntry pEntry, bool saveClasses)
4533 IF_OPT(SLIM_MODULE_TBLS)
4535 DisplayStartStructure("EEClassHashEntry",
4536 DPtrToPreferredAddr(pEntry),
4537 sizeof(EEClassHashEntry), SLIM_MODULE_TBLS);
4540 size_t datum = size_t(PTR_TO_TADDR(pEntry->GetData()));
4542 if (datum & EECLASSHASH_TYPEHANDLE_DISCR)
4544 IF_OPT(SLIM_MODULE_TBLS)
4546 /* REVISIT_TODO Tue 10/25/2005
4547 * Raw data with annotation?
4550 tk = EEClassHashTable::UncompressModuleAndClassDef(pEntry->GetData());
4551 DoWriteFieldMDToken("Token",
4552 offsetof(EEClassHashEntry, m_Data),
4553 fieldsize(EEClassHashEntry, m_Data),
4559 PTR_MethodTable pMT(TO_TADDR(datum));
4560 IF_OPT(SLIM_MODULE_TBLS)
4562 DoWriteFieldMethodTable("MethodTable",
4563 offsetof(EEClassHashEntry, m_Data),
4564 fieldsize(EEClassHashEntry, m_Data),
4570 // These are MethodTables. Get back to the EEClass from there.
4571 if (isInRange(PTR_TO_TADDR(pMT)))
4572 m_discoveredMTs.AppendEx(pMT);
4575 PTR_EEClass pClass = GetClassFromMT(pMT);
4576 if (isInRange(PTR_TO_TADDR(pClass)))
4577 m_discoveredClasses.AppendEx(pMT);
4582 IF_OPT(SLIM_MODULE_TBLS)
4584 DisplayWriteFieldPointer(m_pEncloser,
4585 DPtrToPreferredAddr(pEntry->GetEncloser()),
4586 EEClassHashEntry, SLIM_MODULE_TBLS);
4587 DisplayEndStructure(SLIM_MODULE_TBLS);
4591 void NativeImageDumper::TraverseClassHash(PTR_EEClassHashTable pTable,
4597 TraverseNgenHash<EEClassHashTable, EEClassHashEntry>(pTable,
4602 &NativeImageDumper::TraverseClassHashEntry,
4606 #ifdef FEATURE_COMINTEROP
4608 void NativeImageDumper::TraverseGuidToMethodTableEntry(void *pContext, PTR_GuidToMethodTableEntry pEntry, bool saveClasses)
4610 IF_OPT(SLIM_MODULE_TBLS)
4612 DisplayStartStructure("GuidToMethodTableEntry",
4613 DPtrToPreferredAddr(pEntry),
4614 sizeof(GuidToMethodTableEntry), SLIM_MODULE_TBLS);
4617 WriteFieldMethodTable(m_pMT, pEntry->m_pMT, GuidToMethodTableEntry, ALWAYS);
4620 GuidToString( *(pEntry->m_Guid), buf );
4621 DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidToMethodTableEntry, ALWAYS );
4623 DisplayEndStructure( SLIM_MODULE_TBLS );
4626 void NativeImageDumper::TraverseGuidToMethodTableHash(PTR_GuidToMethodTableHashTable pTable,
4632 TraverseNgenHash<GuidToMethodTableHashTable, GuidToMethodTableEntry>(pTable,
4637 &NativeImageDumper::TraverseGuidToMethodTableEntry,
4641 #endif // FEATURE_COMINTEROP
4643 void NativeImageDumper::TraverseMemberRefToDescHashEntry(void *pContext, PTR_MemberRefToDescHashEntry pEntry, bool saveClasses)
4645 IF_OPT(SLIM_MODULE_TBLS)
4647 DisplayStartStructure("MemberRefToDescHashEntry",
4648 DPtrToPreferredAddr(pEntry),
4649 sizeof(MemberRefToDescHashEntry), SLIM_MODULE_TBLS);
4652 if(pEntry->m_value & IS_FIELD_MEMBER_REF)
4653 WriteFieldFieldDesc(m_value, dac_cast<PTR_FieldDesc>(pEntry->m_value & (~MEMBER_REF_MAP_ALL_FLAGS)), MemberRefToDescHashEntry, MODULE_TABLES);
4655 WriteFieldMethodDesc(m_value, dac_cast<PTR_MethodDesc>(pEntry->m_value), MemberRefToDescHashEntry, MODULE_TABLES);
4657 DisplayEndStructure( SLIM_MODULE_TBLS );
4660 void NativeImageDumper::TraverseMemberRefToDescHash(PTR_MemberRefToDescHashTable pTable,
4666 TraverseNgenHash<MemberRefToDescHashTable, MemberRefToDescHashEntry>(pTable,
4671 &NativeImageDumper::TraverseMemberRefToDescHashEntry,
4676 void NativeImageDumper::TraverseTypeHashEntry(void *pContext, PTR_EETypeHashEntry pEntry, bool saveClasses)
4678 TypeHandle th = pEntry->GetTypeHandle();
4679 IF_OPT(SLIM_MODULE_TBLS)
4681 DisplayStartStructure("EETypeHashEntry",
4682 DPtrToPreferredAddr(pEntry),
4683 sizeof(EETypeHashEntry), SLIM_MODULE_TBLS);
4685 DoWriteFieldTypeHandle("TypeHandle",
4686 offsetof(EETypeHashEntry, m_data),
4687 fieldsize(EETypeHashEntry, m_data),
4691 if (!CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc())
4693 PTR_TypeDesc td(th.AsTypeDesc());
4694 if (isInRange(PTR_TO_TADDR(td)))
4695 m_discoveredTypeDescs.AppendEx(td);
4696 if (td->HasTypeParam())
4698 PTR_ParamTypeDesc ptd(td);
4700 /* REVISIT_TODO Thu 12/15/2005
4701 * Check OwnsTemplateMethodTable. However, this asserts in
4702 * this special completely unrestored and messed up state
4703 * (also, it chases through MT->GetClass()). There isn't
4704 * all that much harm here (bloats m_discoveredMTs though,
4705 * but not by a huge amount.
4707 PTR_MethodTable mt(ptd->GetTemplateMethodTableInternal());
4708 if (isInRange(PTR_TO_TADDR(mt)))
4710 m_discoveredMTs.AppendEx(mt);
4711 if (mt->IsClassPointerValid())
4713 PTR_EEClass pClass = mt->GetClass();
4714 if (isInRange(PTR_TO_TADDR(pClass)))
4715 m_discoveredClasses.AppendEx(mt);
4722 PTR_MethodTable mt(th.AsTAddr());
4724 if (isInRange( PTR_TO_TADDR(mt)))
4725 m_discoveredMTs.AppendEx(mt);
4726 //don't use GetClassFromMT here. mt->m_pEEClass might be a
4727 //fixup. In that case, just skip it.
4728 if (mt->IsClassPointerValid())
4730 PTR_EEClass pClass = mt->GetClass();
4731 if (isInRange(PTR_TO_TADDR(pClass)))
4732 m_discoveredClasses.AppendEx(mt);
4736 IF_OPT(SLIM_MODULE_TBLS)
4738 DisplayEndStructure(SLIM_MODULE_TBLS);
4742 void NativeImageDumper::TraverseTypeHash(PTR_EETypeHashTable pTable,
4747 TraverseNgenHash<EETypeHashTable, EETypeHashEntry>(pTable,
4752 &NativeImageDumper::TraverseTypeHashEntry,
4756 void NativeImageDumper::TraverseInstMethodHashEntry(void *pContext, PTR_InstMethodHashEntry pEntry, bool saveClasses)
4758 PTR_Module pModule((TADDR)pContext);
4760 IF_OPT(SLIM_MODULE_TBLS)
4762 DisplayStartStructure("InstMethodHashEntry",
4763 DPtrToPreferredAddr(pEntry),
4764 sizeof(InstMethodHashEntry), SLIM_MODULE_TBLS);
4767 IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4771 PTR_MethodDesc md = pEntry->GetMethod();
4772 _ASSERTE(md != NULL);
4774 //if we want methoddescs, write the data field as a
4775 //structure with the whole contents of the method desc.
4776 m_display->StartVStructureWithOffset("data", offsetof(InstMethodHashEntry, data),
4777 sizeof(pEntry->data));
4778 DumpMethodDesc(md, pModule);
4779 DisplayEndVStructure(ALWAYS); //data
4783 PTR_MethodDesc md = pEntry->GetMethod();
4784 WriteFieldMethodDesc(data, md,
4785 InstMethodHashEntry, ALWAYS);
4789 CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4791 IF_OPT(SLIM_MODULE_TBLS)
4793 DisplayEndStructure(SLIM_MODULE_TBLS);
4797 void NativeImageDumper::TraverseStubMethodHashEntry(void *pContext, PTR_StubMethodHashEntry pEntry, bool saveClasses)
4799 PTR_Module pModule((TADDR)pContext);
4801 IF_OPT(SLIM_MODULE_TBLS)
4803 DisplayStartStructure("StubMethodHashEntry",
4804 DPtrToPreferredAddr(pEntry),
4805 sizeof(StubMethodHashEntry), SLIM_MODULE_TBLS);
4808 IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4810 PTR_MethodDesc md = pEntry->GetMethod();
4811 _ASSERTE(md != NULL);
4813 PTR_MethodDesc stub = pEntry->GetStubMethod();
4814 _ASSERTE(stub != NULL);
4818 //if we want methoddescs, write the data fields as a
4819 //structure with the whole contents of the method desc.
4820 m_display->StartVStructureWithOffset("pMD", offsetof(StubMethodHashEntry, pMD),
4821 sizeof(pEntry->pMD));
4822 DumpMethodDesc(md, pModule);
4823 DisplayEndVStructure(ALWAYS); //pMD
4825 m_display->StartVStructureWithOffset("pStubMD", offsetof(StubMethodHashEntry, pStubMD),
4826 sizeof(pEntry->pStubMD));
4827 DumpMethodDesc(stub, pModule);
4828 DisplayEndVStructure(ALWAYS); //pStubMD
4832 WriteFieldMethodDesc(pMD, md,
4833 StubMethodHashEntry, ALWAYS);
4834 WriteFieldMethodDesc(pStubMD, stub,
4835 StubMethodHashEntry, ALWAYS);
4839 CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4841 IF_OPT(SLIM_MODULE_TBLS)
4843 DisplayEndStructure(SLIM_MODULE_TBLS);
4847 void NativeImageDumper::TraverseInstMethodHash(PTR_InstMethodHashTable pTable,
4849 unsigned fieldOffset,
4853 TraverseNgenHash<InstMethodHashTable, InstMethodHashEntry>(pTable,
4858 &NativeImageDumper::TraverseInstMethodHashEntry,
4859 (void*)dac_cast<TADDR>(module));
4862 void NativeImageDumper::TraverseStubMethodHash(PTR_StubMethodHashTable pTable,
4864 unsigned fieldOffset,
4868 TraverseNgenHash<StubMethodHashTable, StubMethodHashEntry>(pTable,
4873 &NativeImageDumper::TraverseStubMethodHashEntry,
4874 (void*)dac_cast<TADDR>(module));
4877 const NativeImageDumper::Dependency *
4878 NativeImageDumper::GetDependencyForModule( PTR_Module module )
4880 for( COUNT_T i = 0; i < m_numDependencies; ++i )
4882 if( m_dependencies[i].pModule == module )
4883 return &m_dependencies[i];
4889 const NativeImageDumper::Import *
4890 NativeImageDumper::GetImportForPointer( TADDR ptr )
4892 for( int i = 0; i < m_numImports; ++i )
4894 const Import * import = &m_imports[i];
4895 if( import->dependency->pPreferredBase == NULL )
4897 if( import->dependency->pPreferredBase <= ptr
4898 && ((import->dependency->pPreferredBase
4899 + import->dependency->size) > ptr) )
4901 //found the right target
4908 const NativeImageDumper::Dependency *
4909 NativeImageDumper::GetDependencyForPointer( TADDR ptr )
4911 for( COUNT_T i = 0; i < m_numDependencies; ++i )
4913 const Dependency * dependency = &m_dependencies[i];
4914 if( dependency->pLoadedAddress == NULL )
4916 if( dependency->pLoadedAddress <= ptr
4917 && ((dependency->pLoadedAddress + dependency->size) > ptr) )
4919 //found the right target
4926 void NativeImageDumper::DictionaryToArgString( PTR_Dictionary dictionary, unsigned numArgs, SString& buf )
4928 //this can be called with numArgs == 0 for value type instantiations.
4929 buf.Append( W("<") );
4931 for( unsigned i = 0; i < numArgs; ++i )
4934 buf.Append( W(",") );
4936 TypeHandle th = dictionary->GetInstantiation()[i].GetValue();
4937 if( CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) )
4939 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(dictionary))))
4941 //this is an RVA from another hardbound dependency. We cannot decode it
4942 buf.Append(W("OUT_OF_MODULE_FIXUP"));
4946 RVA rva = CORCOMPILE_UNTAG_TOKEN(th.AsTAddr());
4947 FixupBlobToString(rva, buf);
4952 TypeHandleToString( th, buf );
4955 buf.Append( W(">") );
4958 void NativeImageDumper::MethodTableToString( PTR_MethodTable mt, SString& buf )
4960 bool hasCompleteExtents = true;
4961 IF_OPT(DISABLE_NAMES)
4963 buf.Append( W("Disabled") );
4966 mdToken token = mdTokenNil;
4968 buf.Append( W("mdTypeDefNil") );
4971 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)));
4972 const Dependency * dependency;
4973 if( !mt->IsClassPointerValid() )
4975 if( isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))) )
4978 hasCompleteExtents = false;
4979 RVA rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
4980 PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
4984 if (kind & ENCODE_MODULE_OVERRIDE)
4986 /* int moduleIndex = */ DacSigUncompressData(sig);
4987 kind &= ~ENCODE_MODULE_OVERRIDE;
4990 _ASSERTE(kind == ENCODE_TYPE_HANDLE);
4991 CorElementType et = DacSigUncompressElementType(sig);
4992 if( et == ELEMENT_TYPE_GENERICINST )
4994 //generic instances have another element type
4995 et = DacSigUncompressElementType(sig);
4997 if (et == ELEMENT_TYPE_VALUETYPE || et == ELEMENT_TYPE_CLASS)
4999 token = DacSigUncompressToken(sig);
5006 dependency = GetDependencyForFixup(rva);
5010 //this is an RVA from another hardbound dependency. We cannot decode it
5011 buf.Append(W("OUT_OF_MODULE_FIXUP"));
5017 token = mt->GetCl();
5018 dependency = GetDependencyFromMT(mt);
5021 if( !isSelf(dependency) )
5023 AppendTokenName( dependency->entry->dwAssemblyRef, buf,
5028 _ASSERTE(dependency->pImport);
5029 if( token == mdtTypeDef )
5030 buf.Append( W("No Token") );
5032 AppendTokenName( token, buf, dependency->pImport );
5034 if( mt->HasPerInstInfo() )
5037 if( hasCompleteExtents )
5039 numDicts = mt->GetNumDicts();
5040 _ASSERTE(numDicts == CountDictionariesInClass(token, dependency->pImport));
5044 numDicts = (DWORD)CountDictionariesInClass(token, dependency->pImport);
5047 TADDR base = dac_cast<TADDR>(&(mt->GetPerInstInfo()[numDicts-1]));
5049 PTR_Dictionary dictionary( MethodTable::PerInstInfoElem_t::GetValueAtPtr(base) );
5050 unsigned numArgs = mt->GetNumGenericArgs();
5052 DictionaryToArgString( dictionary, numArgs, buf );
5057 mdToken NativeImageDumper::ConvertToTypeDef( mdToken typeToken, IMetaDataImport2* (&pImport) )
5059 _ASSERTE( (TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5060 || (TypeFromToken(typeToken) == mdtTypeSpec) );
5061 if( mdtTypeDef == TypeFromToken(typeToken) )
5063 if( mdtTypeRef == TypeFromToken(typeToken) )
5065 //convert the ref to a def.
5067 WCHAR trName[MAX_CLASS_NAME];
5069 IfFailThrow(pImport->GetTypeRefProps(typeToken, &scope, trName, _countof(trName), &trNameLen));
5070 _ASSERTE(trName[trNameLen-1] == 0);
5072 //scope is now a moduleRef or assemblyRef. Find the IMetaData import for that Ref
5073 /* REVISIT_TODO Fri 10/6/2006
5074 * How do I handle moduleRefs?
5076 _ASSERTE(TypeFromToken(scope) == mdtAssemblyRef);
5077 ReleaseHolder<IMetaDataAssemblyImport> pAssemblyImport;
5078 IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
5079 (void **)&pAssemblyImport));
5080 NativeImageDumper::Dependency * dep = GetDependency(scope, pAssemblyImport);
5082 pImport = dep->pImport;
5084 /* REVISIT_TODO Fri 10/6/2006
5085 * Does this work for inner types?
5087 //now I have the correct MetaData. Find the typeDef
5088 HRESULT hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5089 while (hr == CLDB_E_RECORD_NOTFOUND)
5091 // No matching TypeDef, try ExportedType
5092 pAssemblyImport = NULL;
5093 IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
5094 (void **)&pAssemblyImport));
5095 mdExportedType tkExportedType = mdExportedTypeNil;
5096 IfFailThrow(pAssemblyImport->FindExportedTypeByName(trName, mdExportedTypeNil, &tkExportedType));
5097 mdToken tkImplementation;
5098 IfFailThrow(pAssemblyImport->GetExportedTypeProps(tkExportedType, NULL, 0, NULL, &tkImplementation, NULL, NULL));
5099 dep = GetDependency(tkImplementation, pAssemblyImport);
5101 pImport = dep->pImport;
5102 hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5108 PCCOR_SIGNATURE pSig;
5110 IfFailThrow(pImport->GetTypeSpecFromToken(typeToken, &pSig, &cbSig));
5111 //GENERICINST (CLASS|VALUETYPE) typeDefOrRef
5112 CorElementType et = CorSigUncompressElementType(pSig);
5113 _ASSERTE(et == ELEMENT_TYPE_GENERICINST);
5114 et = CorSigUncompressElementType(pSig);
5115 _ASSERTE((et == ELEMENT_TYPE_CLASS) || (et == ELEMENT_TYPE_VALUETYPE));
5116 typeToken = CorSigUncompressToken(pSig);
5119 //we just removed one level of indirection. We still might have a ref or spec.
5120 typeToken = ConvertToTypeDef(typeToken, pImport);
5121 _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5125 SIZE_T NativeImageDumper::CountDictionariesInClass( mdToken typeToken, IMetaDataImport2 * pImport )
5127 SIZE_T myDicts; //either 0 or 1
5129 _ASSERTE((TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5130 || (TypeFromToken(typeToken) == mdtTypeSpec));
5133 //for refs and specs, convert to a def. This is a nop for defs.
5134 typeToken = ConvertToTypeDef(typeToken, pImport);
5136 _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5139 //count the number of generic arguments. If there are any, then we have a dictionary.
5140 HCORENUM hEnum = NULL;
5141 mdGenericParam params[2];
5142 ULONG numParams = 0;
5143 IfFailThrow(pImport->EnumGenericParams(&hEnum, typeToken, params, _countof(params), &numParams));
5144 myDicts = (numParams > 0) ? 1 : 0;
5146 pImport->CloseEnum(hEnum);
5148 //get my parent for the recursive call.
5150 IfFailThrow(pImport->GetTypeDefProps(typeToken, NULL, 0, NULL, NULL, &parent));
5151 return myDicts + (IsNilToken(parent) ? 0 : CountDictionariesInClass(parent, pImport));
5154 const NativeImageDumper::EnumMnemonics s_Subsystems[] =
5156 #define S_ENTRY(f,v) NativeImageDumper::EnumMnemonics(f, 0, v)
5157 S_ENTRY(IMAGE_SUBSYSTEM_UNKNOWN, W("Unknown")),
5158 S_ENTRY(IMAGE_SUBSYSTEM_NATIVE, W("Native")),
5159 S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CUI, W("Windows CUI")),
5160 S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_GUI, W("Windows GUI")),
5161 S_ENTRY(IMAGE_SUBSYSTEM_OS2_CUI, W("OS/2 CUI")),
5162 S_ENTRY(IMAGE_SUBSYSTEM_POSIX_CUI, W("POSIX CUI")),
5163 S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, W("WinCE GUI")),
5164 S_ENTRY(IMAGE_SUBSYSTEM_XBOX, W("XBox"))
5168 const NativeImageDumper::EnumMnemonics s_CorCompileHdrFlags[] =
5170 #define CCHF_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5171 CCHF_ENTRY(CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY),
5172 CCHF_ENTRY(CORCOMPILE_HEADER_IS_IBC_OPTIMIZED),
5173 CCHF_ENTRY(CORCOMPILE_HEADER_IS_READY_TO_RUN),
5177 const NativeImageDumper::EnumMnemonics s_CorPEKind[] =
5179 #define CPEK_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5181 CPEK_ENTRY(peILonly),
5182 CPEK_ENTRY(pe32BitRequired),
5183 CPEK_ENTRY(pe32Plus),
5184 CPEK_ENTRY(pe32Unmanaged),
5185 CPEK_ENTRY(pe32BitPreferred)
5188 const NativeImageDumper::EnumMnemonics s_IFH_Machine[] =
5190 #define IFH_ENTRY(f) NativeImageDumper::EnumMnemonics(f, 0, W(#f))
5191 IFH_ENTRY(IMAGE_FILE_MACHINE_UNKNOWN),
5192 IFH_ENTRY(IMAGE_FILE_MACHINE_I386),
5193 IFH_ENTRY(IMAGE_FILE_MACHINE_AMD64),
5194 IFH_ENTRY(IMAGE_FILE_MACHINE_ARMNT),
5198 const NativeImageDumper::EnumMnemonics s_IFH_Characteristics[] =
5200 #define IFH_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5201 IFH_ENTRY(IMAGE_FILE_RELOCS_STRIPPED),
5202 IFH_ENTRY(IMAGE_FILE_EXECUTABLE_IMAGE),
5203 IFH_ENTRY(IMAGE_FILE_LINE_NUMS_STRIPPED),
5204 IFH_ENTRY(IMAGE_FILE_LOCAL_SYMS_STRIPPED),
5205 IFH_ENTRY(IMAGE_FILE_AGGRESIVE_WS_TRIM),
5206 IFH_ENTRY(IMAGE_FILE_LARGE_ADDRESS_AWARE),
5207 IFH_ENTRY(IMAGE_FILE_BYTES_REVERSED_LO),
5208 IFH_ENTRY(IMAGE_FILE_32BIT_MACHINE),
5209 IFH_ENTRY(IMAGE_FILE_DEBUG_STRIPPED),
5210 IFH_ENTRY(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
5211 IFH_ENTRY(IMAGE_FILE_NET_RUN_FROM_SWAP),
5212 IFH_ENTRY(IMAGE_FILE_SYSTEM),
5213 IFH_ENTRY(IMAGE_FILE_DLL),
5214 IFH_ENTRY(IMAGE_FILE_UP_SYSTEM_ONLY),
5215 IFH_ENTRY(IMAGE_FILE_BYTES_REVERSED_HI),
5219 const NativeImageDumper::EnumMnemonics s_ImportSectionType[] =
5221 #define IST_ENTRY(f) NativeImageDumper::EnumMnemonics(f, 0, W(#f))
5222 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_UNKNOWN),
5223 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD),
5224 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH),
5225 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_STRING_HANDLE),
5226 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE),
5227 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE),
5228 IST_ENTRY(CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD),
5232 const NativeImageDumper::EnumMnemonics s_ImportSectionFlags[] =
5234 #define IST_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5235 IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_EAGER),
5236 IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_CODE),
5237 IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_PCODE),
5241 void NativeImageDumper::DumpNativeHeader()
5243 PTR_CORCOMPILE_HEADER nativeHeader(m_decoder.GetNativeHeader());
5248 #define WRITE_NATIVE_FIELD( name ) m_display->WriteFieldAddress(\
5249 # name, offsetof(CORCOMPILE_HEADER, name), \
5250 fieldsize(CORCOMPILE_HEADER, name), \
5251 RvaToDisplay( nativeHeader-> name . VirtualAddress ), \
5252 nativeHeader-> name . Size )
5254 m_display->StartStructure( "CORCOMPILE_HEADER",
5255 DPtrToPreferredAddr(nativeHeader),
5256 sizeof(*nativeHeader) );
5258 DisplayWriteFieldUInt( Signature, nativeHeader->Signature, CORCOMPILE_HEADER, ALWAYS );
5259 DisplayWriteFieldUInt( MajorVersion, nativeHeader->MajorVersion, CORCOMPILE_HEADER, ALWAYS );
5260 DisplayWriteFieldUInt( MinorVersion, nativeHeader->MinorVersion, CORCOMPILE_HEADER, ALWAYS );
5262 WRITE_NATIVE_FIELD(HelperTable);
5264 WRITE_NATIVE_FIELD(ImportSections);
5265 PTR_CORCOMPILE_IMPORT_SECTION pImportSections =
5266 nativeHeader->ImportSections.VirtualAddress
5267 + PTR_TO_TADDR(m_decoder.GetBase());
5268 DisplayStartArray( "ImportSections", NULL, ALWAYS );
5269 for( COUNT_T i = 0; i < nativeHeader->ImportSections.Size
5270 / sizeof(*pImportSections); ++i )
5272 DisplayStartStructure( "CORCOMPILE_IMPORT_SECTION",
5273 DPtrToPreferredAddr(pImportSections + i),
5274 sizeof(pImportSections[i]), ALWAYS );
5275 DisplayWriteElementAddress( "Section",
5276 RvaToDisplay(pImportSections[i].Section.VirtualAddress),
5277 pImportSections[i].Section.Size, ALWAYS );
5279 DisplayWriteFieldEnumerated( Flags, pImportSections[i].Flags,
5280 CORCOMPILE_IMPORT_SECTION, s_ImportSectionFlags, W(", "), ALWAYS );
5281 DisplayWriteFieldEnumerated( Type, pImportSections[i].Type,
5282 CORCOMPILE_IMPORT_SECTION, s_ImportSectionType, W(""), ALWAYS );
5284 DisplayWriteFieldUInt( EntrySize, pImportSections[i].EntrySize,
5285 CORCOMPILE_IMPORT_SECTION, ALWAYS );
5286 DisplayWriteFieldUInt( Signatures, pImportSections[i].Signatures,
5287 CORCOMPILE_IMPORT_SECTION, ALWAYS );
5288 DisplayWriteFieldUInt( AuxiliaryData, pImportSections[i].AuxiliaryData,
5289 CORCOMPILE_IMPORT_SECTION, ALWAYS );
5290 DisplayEndStructure( ALWAYS ); //PTR_CORCOMPILE_IMPORT_SECTION
5293 DisplayEndArray( NULL, ALWAYS ); //delayLoads
5295 WRITE_NATIVE_FIELD(VersionInfo);
5296 WRITE_NATIVE_FIELD(DebugMap);
5297 WRITE_NATIVE_FIELD(ModuleImage);
5298 WRITE_NATIVE_FIELD(CodeManagerTable);
5299 WRITE_NATIVE_FIELD(ProfileDataList);
5300 WRITE_NATIVE_FIELD(ManifestMetaData);
5302 WRITE_NATIVE_FIELD(VirtualSectionsTable);
5303 DisplayStartArray( "VirtualSections", W("%-48s%s"), SLIM_MODULE_TBLS );
5304 PTR_CORCOMPILE_VIRTUAL_SECTION_INFO sects( nativeHeader->VirtualSectionsTable.VirtualAddress + PTR_TO_TADDR(m_decoder.GetBase()) );
5305 COUNT_T numVirtualSections = nativeHeader->VirtualSectionsTable.Size / sizeof (CORCOMPILE_VIRTUAL_SECTION_INFO);
5307 for( COUNT_T i = 0; i < numVirtualSections; ++i )
5309 TempBuffer sectionNameBuf;
5310 TempBuffer sectionFlags;
5311 StackScratchBuffer scratch;
5313 sectionNameBuf.Append(g_sectionNames[VirtualSectionData::VirtualSectionType(sects[i].SectionType)]);
5315 EnumFlagsToString( sects[i].SectionType, s_virtualSectionFlags, dim(s_virtualSectionFlags),
5316 W(" | "), sectionFlags);
5318 sectionNameBuf.Append(W(" ["));
5319 sectionNameBuf.Append(sectionFlags);
5320 sectionNameBuf.Append(W("]"));
5322 DisplayStartElement( "Section", SLIM_MODULE_TBLS );
5323 DisplayWriteElementString("Name", sectionNameBuf.GetANSI(scratch), SLIM_MODULE_TBLS);
5325 DisplayWriteElementAddress( "Address",
5326 RvaToDisplay(sects[i].VirtualAddress),
5329 DisplayEndElement( SLIM_MODULE_TBLS ); //Section
5331 DisplayEndArray( "Total VirtualSections", SLIM_MODULE_TBLS );
5333 WRITE_NATIVE_FIELD(EEInfoTable);
5335 #undef WRITE_NATIVE_FIELD
5336 DisplayWriteFieldEnumerated( Flags, nativeHeader->Flags,
5337 CORCOMPILE_HEADER, s_CorCompileHdrFlags, W(", "),
5340 DisplayWriteFieldEnumerated( PEKind, nativeHeader->PEKind,
5341 CORCOMPILE_HEADER, s_CorPEKind, W(", "),
5344 DisplayWriteFieldEnumerated( COR20Flags, nativeHeader->COR20Flags,
5345 CORCOMPILE_HEADER, s_CorHdrFlags, W(", "),
5348 DisplayWriteFieldEnumerated( Machine, nativeHeader->Machine,
5349 CORCOMPILE_HEADER, s_IFH_Machine,
5350 W(""), NATIVE_INFO );
5351 DisplayWriteFieldEnumerated( Characteristics,
5352 nativeHeader->Characteristics,
5353 CORCOMPILE_HEADER, s_IFH_Characteristics,
5354 W(", "), NATIVE_INFO );
5356 m_display->EndStructure(); //CORCOMPILE_HEADER
5360 const NativeImageDumper::EnumMnemonics s_RelocType[] =
5362 #define REL_ENTRY(x) NativeImageDumper::EnumMnemonics( x, 0, W(#x))
5363 REL_ENTRY(IMAGE_REL_BASED_ABSOLUTE),
5364 REL_ENTRY(IMAGE_REL_BASED_HIGHLOW),
5365 REL_ENTRY(IMAGE_REL_BASED_DIR64),
5366 REL_ENTRY(IMAGE_REL_BASED_THUMB_MOV32),
5370 void NativeImageDumper::DumpBaseRelocs()
5375 data = m_decoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_BASERELOC, &size);
5379 DisplayStartStructure( "Relocations", DataPtrToDisplay(data), size,
5384 IMAGE_BASE_RELOCATION * pBaseRelocation = dac_cast<DPTR(IMAGE_BASE_RELOCATION)>(data);
5385 _ASSERTE(size >= pBaseRelocation->SizeOfBlock);
5387 SIZE_T rel = sizeof(IMAGE_BASE_RELOCATION);
5388 while (rel < pBaseRelocation->SizeOfBlock)
5390 USHORT typeOffset = *PTR_USHORT(data + rel);
5392 DisplayStartElement( "Entry", ALWAYS );
5394 DisplayWriteElementPointer( "Address", RvaToDisplay(pBaseRelocation->VirtualAddress + (typeOffset & 0xFFF)), ALWAYS );
5396 DisplayWriteElementEnumerated( "Type", (typeOffset >> 12),
5397 s_RelocType, W(", "), ALWAYS );
5399 DisplayEndElement( ALWAYS ); //Entry
5401 rel += sizeof(USHORT);
5404 data += pBaseRelocation->SizeOfBlock;
5405 size -= pBaseRelocation->SizeOfBlock;
5408 DisplayEndStructure( ALWAYS ); //Relocations
5412 void NativeImageDumper::DumpHelperTable()
5417 data = TO_TADDR(m_decoder.GetNativeHelperTable(&size));
5420 DisplayStartStructure( "HelperTable", DataPtrToDisplay(data), size,
5423 TADDR curEntry = data;
5424 TADDR tableEnd = data + size;
5426 while (curEntry < tableEnd)
5428 DWORD dwHelper = *PTR_DWORD(curEntry);
5430 int iHelper = (USHORT)dwHelper;
5431 _ASSERTE(iHelper < CORINFO_HELP_COUNT);
5433 DisplayStartStructure( "Helper",
5434 DataPtrToDisplay(curEntry), (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN,
5437 DisplayWriteElementUInt( "dwHelper", dwHelper, ALWAYS );
5438 DisplayWriteElementString( "Name", g_helperNames[iHelper], ALWAYS );
5440 DisplayEndStructure( ALWAYS ); //Helper
5442 curEntry += (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN;
5445 DisplayEndStructure( ALWAYS ); //HelperTable
5449 // TODO: fix these to work with the updated flags in MethodTable, AND to understand
5450 // the new overloading of component size...
5452 NativeImageDumper::EnumMnemonics s_MTFlagsLow[] =
5454 #define MTFLAG_ENTRY(x) \
5455 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5457 MTFLAG_ENTRY(UNUSED_ComponentSize_1),
5458 MTFLAG_ENTRY(StaticsMask),
5459 MTFLAG_ENTRY(StaticsMask_NonDynamic),
5460 MTFLAG_ENTRY(StaticsMask_Dynamic),
5461 MTFLAG_ENTRY(StaticsMask_Generics),
5462 MTFLAG_ENTRY(StaticsMask_CrossModuleGenerics),
5463 MTFLAG_ENTRY(NotInPZM),
5464 MTFLAG_ENTRY(GenericsMask),
5465 MTFLAG_ENTRY(GenericsMask_NonGeneric),
5466 MTFLAG_ENTRY(GenericsMask_GenericInst),
5467 MTFLAG_ENTRY(GenericsMask_SharedInst),
5468 MTFLAG_ENTRY(GenericsMask_TypicalInst),
5469 MTFLAG_ENTRY(HasVariance),
5470 MTFLAG_ENTRY(HasDefaultCtor),
5471 MTFLAG_ENTRY(HasPreciseInitCctors),
5472 #if defined(FEATURE_HFA)
5473 MTFLAG_ENTRY(IsHFA),
5474 #endif // FEATURE_HFA
5475 #if defined(UNIX_AMD64_ABI)
5476 MTFLAG_ENTRY(IsRegStructPassed),
5477 #endif // UNIX_AMD64_ABI
5478 MTFLAG_ENTRY(IsByRefLike),
5479 MTFLAG_ENTRY(UNUSED_ComponentSize_5),
5480 MTFLAG_ENTRY(UNUSED_ComponentSize_6),
5481 MTFLAG_ENTRY(UNUSED_ComponentSize_7),
5485 NativeImageDumper::EnumMnemonics s_MTFlagsHigh[] =
5487 #define MTFLAG_ENTRY(x) \
5488 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5490 #define MTFLAG_CATEGORY_ENTRY(x) \
5491 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_Mask, W("Category_") W(#x))
5493 #define MTFLAG_CATEGORY_ENTRY_WITH_MASK(x, m) \
5494 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_ ## m, W("Category_") W(#x))
5496 MTFLAG_CATEGORY_ENTRY(Class),
5497 MTFLAG_CATEGORY_ENTRY(Unused_1),
5498 MTFLAG_CATEGORY_ENTRY(Unused_2),
5499 MTFLAG_CATEGORY_ENTRY(Unused_3),
5500 MTFLAG_CATEGORY_ENTRY(ValueType),
5501 MTFLAG_CATEGORY_ENTRY(Nullable),
5502 MTFLAG_CATEGORY_ENTRY(PrimitiveValueType),
5503 MTFLAG_CATEGORY_ENTRY(TruePrimitive),
5505 MTFLAG_CATEGORY_ENTRY(Interface),
5506 MTFLAG_CATEGORY_ENTRY(Unused_4),
5507 MTFLAG_CATEGORY_ENTRY(Unused_5),
5508 MTFLAG_CATEGORY_ENTRY(Unused_6),
5510 MTFLAG_CATEGORY_ENTRY_WITH_MASK(Array, Array_Mask),
5511 MTFLAG_CATEGORY_ENTRY_WITH_MASK(IfArrayThenSzArray, IfArrayThenSzArray),
5513 #undef MTFLAG_CATEGORY_ENTRY_WITH_MASK
5514 #undef MTFLAG_CATEGORY_ENTRY
5516 MTFLAG_ENTRY(HasFinalizer),
5517 MTFLAG_ENTRY(IfNotInterfaceThenMarshalable),
5518 #if defined(FEATURE_COMINTEROP)
5519 MTFLAG_ENTRY(IfInterfaceThenHasGuidInfo),
5521 #if defined(FEATURE_ICASTABLE)
5522 MTFLAG_ENTRY(ICastable),
5524 MTFLAG_ENTRY(HasIndirectParent),
5525 MTFLAG_ENTRY(ContainsPointers),
5526 MTFLAG_ENTRY(HasTypeEquivalence),
5527 #if defined(FEATURE_COMINTEROP)
5528 MTFLAG_ENTRY(HasRCWPerTypeData),
5530 MTFLAG_ENTRY(HasCriticalFinalizer),
5531 MTFLAG_ENTRY(Collectible),
5532 MTFLAG_ENTRY(ContainsGenericVariables),
5533 #if defined(FEATURE_COMINTEROP)
5534 MTFLAG_ENTRY(ComObject),
5536 MTFLAG_ENTRY(HasComponentSize),
5541 NativeImageDumper::EnumMnemonics s_MTFlags2[] =
5543 #define MTFLAG2_ENTRY(x) \
5544 NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5545 MTFLAG2_ENTRY(HasPerInstInfo),
5546 MTFLAG2_ENTRY(HasInterfaceMap),
5547 MTFLAG2_ENTRY(HasDispatchMapSlot),
5548 MTFLAG2_ENTRY(HasNonVirtualSlots),
5549 MTFLAG2_ENTRY(HasModuleOverride),
5550 MTFLAG2_ENTRY(IsZapped),
5551 MTFLAG2_ENTRY(IsPreRestored),
5552 MTFLAG2_ENTRY(HasModuleDependencies),
5553 MTFLAG2_ENTRY(IsIntrinsicType),
5554 MTFLAG2_ENTRY(RequiresDispatchTokenFat),
5555 MTFLAG2_ENTRY(HasCctor),
5556 MTFLAG2_ENTRY(HasCCWTemplate),
5557 #ifdef FEATURE_64BIT_ALIGNMENT
5558 MTFLAG2_ENTRY(RequiresAlign8),
5560 MTFLAG2_ENTRY(HasBoxedRegularStatics),
5561 MTFLAG2_ENTRY(HasSingleNonVirtualSlot),
5562 MTFLAG2_ENTRY(DependsOnEquivalentOrForwardedStructs),
5563 #undef MTFLAG2_ENTRY
5566 NativeImageDumper::EnumMnemonics s_WriteableMTFlags[] =
5568 #define WMTFLAG_ENTRY(x) \
5569 NativeImageDumper::EnumMnemonics(MethodTableWriteableData::enum_flag_ ## x,\
5572 WMTFLAG_ENTRY(Unrestored),
5573 WMTFLAG_ENTRY(HasApproxParent),
5574 WMTFLAG_ENTRY(UnrestoredTypeKey),
5575 WMTFLAG_ENTRY(IsNotFullyLoaded),
5576 WMTFLAG_ENTRY(DependenciesLoaded),
5579 WMTFLAG_ENTRY(ParentMethodTablePointerValid),
5582 WMTFLAG_ENTRY(NGEN_IsFixedUp),
5583 WMTFLAG_ENTRY(NGEN_IsNeedsRestoreCached),
5584 WMTFLAG_ENTRY(NGEN_CachedNeedsRestore),
5585 #undef WMTFLAG_ENTRY
5588 static NativeImageDumper::EnumMnemonics s_CorElementType[] =
5590 #define CET_ENTRY(x) NativeImageDumper::EnumMnemonics(ELEMENT_TYPE_ ## x, 0, W("ELEMENT_TYPE_") W(#x))
5608 CET_ENTRY(VALUETYPE),
5612 CET_ENTRY(GENERICINST),
5613 CET_ENTRY(TYPEDBYREF),
5614 CET_ENTRY(VALUEARRAY_UNSUPPORTED),
5617 CET_ENTRY(R_UNSUPPORTED),
5622 CET_ENTRY(CMOD_REQD),
5623 CET_ENTRY(CMOD_OPT),
5624 CET_ENTRY(INTERNAL),
5626 CET_ENTRY(SENTINEL),
5631 void NativeImageDumper::DoWriteFieldCorElementType( const char * name,
5634 CorElementType type )
5637 EnumFlagsToString( (int)type, s_CorElementType, dim(s_CorElementType),
5639 m_display->WriteFieldEnumerated( name, offset, fieldSize, (unsigned)type,
5640 (const WCHAR *) buf );
5644 static NativeImageDumper::EnumMnemonics s_CorTypeAttr[] =
5646 #define CTA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5648 #define CTA_VISIBILITY_ENTRY(x) NativeImageDumper::EnumMnemonics( x, tdVisibilityMask, W(#x) )
5649 CTA_VISIBILITY_ENTRY(tdNotPublic),
5650 CTA_VISIBILITY_ENTRY(tdPublic),
5651 CTA_VISIBILITY_ENTRY(tdNestedPublic),
5652 CTA_VISIBILITY_ENTRY(tdNestedPrivate),
5653 CTA_VISIBILITY_ENTRY(tdNestedFamily),
5654 CTA_VISIBILITY_ENTRY(tdNestedAssembly),
5655 CTA_VISIBILITY_ENTRY(tdNestedFamANDAssem),
5656 CTA_VISIBILITY_ENTRY(tdNestedFamORAssem),
5657 #undef CTA_VISIBILITY_ENTRY
5659 CTA_ENTRY(tdSequentialLayout),
5660 CTA_ENTRY(tdExplicitLayout),
5662 CTA_ENTRY(tdInterface),
5664 CTA_ENTRY(tdAbstract),
5665 CTA_ENTRY(tdSealed),
5666 CTA_ENTRY(tdSpecialName),
5668 CTA_ENTRY(tdImport),
5669 CTA_ENTRY(tdSerializable),
5671 CTA_ENTRY(tdUnicodeClass),
5672 CTA_ENTRY(tdAutoClass),
5673 CTA_ENTRY(tdCustomFormatClass),
5674 CTA_ENTRY(tdCustomFormatMask),
5676 CTA_ENTRY(tdBeforeFieldInit),
5677 CTA_ENTRY(tdForwarder),
5679 CTA_ENTRY(tdRTSpecialName),
5680 CTA_ENTRY(tdHasSecurity)
5683 static NativeImageDumper::EnumMnemonics s_VMFlags[] =
5685 #define VMF_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClass::VMFLAG_ ## x, W(#x) )
5687 #ifdef FEATURE_READYTORUN
5688 VMF_ENTRY(LAYOUT_DEPENDS_ON_OTHER_MODULES),
5690 VMF_ENTRY(DELEGATE),
5691 VMF_ENTRY(FIXED_ADDRESS_VT_STATICS),
5692 VMF_ENTRY(HASLAYOUT),
5693 VMF_ENTRY(ISNESTED),
5694 VMF_ENTRY(IS_EQUIVALENT_TYPE),
5696 VMF_ENTRY(HASOVERLAYEDFIELDS),
5697 VMF_ENTRY(HAS_FIELDS_WHICH_MUST_BE_INITED),
5698 VMF_ENTRY(UNSAFEVALUETYPE),
5700 VMF_ENTRY(BESTFITMAPPING_INITED),
5701 VMF_ENTRY(BESTFITMAPPING),
5702 VMF_ENTRY(THROWONUNMAPPABLECHAR),
5705 VMF_ENTRY(HASNONPUBLICFIELDS),
5706 VMF_ENTRY(PREFER_ALIGN8),
5708 #ifdef FEATURE_COMINTEROP
5709 VMF_ENTRY(SPARSE_FOR_COMINTEROP),
5710 VMF_ENTRY(HASCOCLASSATTRIB),
5711 VMF_ENTRY(COMEVENTITFMASK),
5712 VMF_ENTRY(PROJECTED_FROM_WINRT),
5713 VMF_ENTRY(EXPORTED_TO_WINRT),
5714 #endif // FEATURE_COMINTEROP
5716 VMF_ENTRY(NOT_TIGHTLY_PACKED),
5717 VMF_ENTRY(CONTAINS_METHODIMPLS),
5718 #ifdef FEATURE_COMINTEROP
5719 VMF_ENTRY(MARSHALINGTYPE_MASK),
5720 VMF_ENTRY(MARSHALINGTYPE_INHIBIT),
5721 VMF_ENTRY(MARSHALINGTYPE_FREETHREADED),
5722 VMF_ENTRY(MARSHALINGTYPE_STANDARD),
5726 static NativeImageDumper::EnumMnemonics s_CorFieldAttr[] =
5728 #define CFA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5730 #define CFA_ACCESS_ENTRY(x) NativeImageDumper::EnumMnemonics( x, fdFieldAccessMask, W(#x) )
5731 CFA_ENTRY(fdPrivateScope),
5732 CFA_ENTRY(fdPrivate),
5733 CFA_ENTRY(fdFamANDAssem),
5734 CFA_ENTRY(fdAssembly),
5735 CFA_ENTRY(fdFamily),
5736 CFA_ENTRY(fdFamORAssem),
5737 CFA_ENTRY(fdPublic),
5738 #undef CFA_ACCESS_ENTRY
5740 CFA_ENTRY(fdStatic),
5741 CFA_ENTRY(fdInitOnly),
5742 CFA_ENTRY(fdLiteral),
5743 CFA_ENTRY(fdNotSerialized),
5745 CFA_ENTRY(fdSpecialName),
5747 CFA_ENTRY(fdPinvokeImpl),
5749 CFA_ENTRY(fdRTSpecialName),
5750 CFA_ENTRY(fdHasFieldMarshal),
5751 CFA_ENTRY(fdHasDefault),
5752 CFA_ENTRY(fdHasFieldRVA),
5756 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDFlag2[] =
5758 #define MDF2_ENTRY(x) NativeImageDumper::EnumMnemonics( MethodDesc::enum_flag2_ ## x, W("enum_flag2_") W(#x) )
5759 MDF2_ENTRY(HasStableEntryPoint),
5760 MDF2_ENTRY(HasPrecode),
5761 MDF2_ENTRY(IsUnboxingStub),
5762 MDF2_ENTRY(HasNativeCodeSlot),
5766 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDC[] =
5768 #define MDC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5770 #define MDC_ENTRY_CLASSIFICATION(x) NativeImageDumper::EnumMnemonics( x, mdcClassification, W(#x) )
5771 MDC_ENTRY_CLASSIFICATION(mcIL),
5772 MDC_ENTRY_CLASSIFICATION(mcFCall),
5773 MDC_ENTRY_CLASSIFICATION(mcNDirect),
5774 MDC_ENTRY_CLASSIFICATION(mcEEImpl),
5775 MDC_ENTRY_CLASSIFICATION(mcArray),
5776 MDC_ENTRY_CLASSIFICATION(mcInstantiated),
5777 #ifdef FEATURE_COMINTEROP
5778 MDC_ENTRY_CLASSIFICATION(mcComInterop),
5779 #endif // FEATURE_COMINTEROP
5780 MDC_ENTRY_CLASSIFICATION(mcDynamic),
5781 #undef MDC_ENTRY_CLASSIFICATION
5783 MDC_ENTRY(mdcHasNonVtableSlot),
5784 MDC_ENTRY(mdcMethodImpl),
5787 MDC_ENTRY(mdcStatic),
5789 MDC_ENTRY(mdcDuplicate),
5790 MDC_ENTRY(mdcVerifiedState),
5791 MDC_ENTRY(mdcVerifiable),
5792 MDC_ENTRY(mdcNotInline),
5793 MDC_ENTRY(mdcSynchronized),
5794 MDC_ENTRY(mdcRequiresFullSlotNumber),
5800 void NativeImageDumper::DumpTypes(PTR_Module module)
5802 _ASSERTE(CHECK_OPT(EECLASSES) || CHECK_OPT(METHODTABLES)
5803 || CHECK_OPT(TYPEDESCS));
5805 IF_OPT_OR3(METHODTABLES, EECLASSES, TYPEDESCS)
5806 m_display->StartCategory( "Types" );
5807 IF_OPT(METHODTABLES)
5809 //there may be duplicates in the list. Remove them before moving on.
5810 COUNT_T mtCount = m_discoveredMTs.GetCount();
5812 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5813 std::sort(&*m_discoveredMTs.Begin(),
5814 (&*m_discoveredMTs.Begin())
5815 + (m_discoveredMTs.End() - m_discoveredMTs.Begin()));
5816 PTR_MethodTable* newEnd = std::unique(&*m_discoveredMTs.Begin(),
5817 (&*m_discoveredMTs.Begin())
5818 + (m_discoveredMTs.End()
5819 - m_discoveredMTs.Begin()));
5820 mtCount = (COUNT_T)(newEnd - &*m_discoveredMTs.Begin());
5823 DisplayStartArray( "MethodTables", NULL, METHODTABLES );
5824 for(COUNT_T i = 0; i < mtCount; ++i )
5826 PTR_MethodTable mt = m_discoveredMTs[i];
5829 DumpMethodTable( mt, "MethodTable", module );
5832 DisplayEndArray( "Total MethodTables", METHODTABLES );
5834 DisplayStartArray( "MethodTableSlotChunks", NULL, METHODTABLES );
5836 COUNT_T slotChunkCount = m_discoveredSlotChunks.GetCount();
5837 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5838 std::sort(&*m_discoveredSlotChunks.Begin(),
5839 (&*m_discoveredSlotChunks.Begin())
5840 + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin()));
5841 SlotChunk *newEndChunks = std::unique(&*m_discoveredSlotChunks.Begin(),
5842 (&*m_discoveredSlotChunks.Begin())
5843 + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin()));
5844 slotChunkCount = (COUNT_T)(newEndChunks - &*m_discoveredSlotChunks.Begin());
5847 for (COUNT_T i = 0; i < slotChunkCount; ++i)
5849 DumpMethodTableSlotChunk(m_discoveredSlotChunks[i].addr,
5850 m_discoveredSlotChunks[i].nSlots,
5851 m_discoveredSlotChunks[i].isRelative);
5854 DisplayEndArray( "Total MethodTableSlotChunks", METHODTABLES );
5858 DisplayStartArray( "EEClasses", NULL, EECLASSES );
5860 //there may be duplicates in the list. Remove them before moving on.
5861 COUNT_T clazzCount = m_discoveredClasses.GetCount();
5862 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5863 std::sort(&*m_discoveredClasses.Begin(),
5864 (&*m_discoveredClasses.Begin())
5865 + (m_discoveredClasses.End() - m_discoveredClasses.Begin()));
5866 PTR_MethodTable * newEndClazz = std::unique(&*m_discoveredClasses.Begin(),
5867 (&*m_discoveredClasses.Begin())
5868 +(m_discoveredClasses.End()
5869 -m_discoveredClasses.Begin()));
5870 clazzCount = (COUNT_T)(newEndClazz - &*m_discoveredClasses.Begin());
5873 for(COUNT_T i = 0; i < clazzCount; ++i )
5875 PTR_MethodTable mt = m_discoveredClasses[i];
5878 DumpEEClassForMethodTable( mt );
5881 DisplayEndArray( "Total EEClasses", EECLASSES ); //EEClasses
5886 DisplayStartArray( "TypeDescs", NULL, TYPEDESCS );
5888 //there may be duplicates in the list. Remove them before moving on.
5889 COUNT_T tdCount = m_discoveredTypeDescs.GetCount();
5890 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5891 std::sort(&*m_discoveredTypeDescs.Begin(),
5892 (&*m_discoveredTypeDescs.Begin())
5893 + (m_discoveredTypeDescs.End()
5894 - m_discoveredTypeDescs.Begin()));
5895 PTR_TypeDesc* newEndTD = std::unique(&*m_discoveredTypeDescs.Begin(),
5896 (&*m_discoveredTypeDescs.Begin())
5897 +(m_discoveredTypeDescs.End()
5898 -m_discoveredTypeDescs.Begin()));
5899 tdCount = (COUNT_T)(newEndTD - &*m_discoveredTypeDescs.Begin());
5902 for(COUNT_T i = 0; i < tdCount; ++i )
5904 PTR_TypeDesc td = m_discoveredTypeDescs[i];
5910 DisplayEndArray( "Total TypeDescs", TYPEDESCS ); //EEClasses
5913 IF_OPT_OR3(EECLASSES, METHODTABLES, TYPEDESCS)
5914 m_display->EndCategory(); //Types
5917 PTR_EEClass NativeImageDumper::GetClassFromMT( PTR_MethodTable mt )
5919 /* REVISIT_TODO Tue 10/11/2005
5922 _ASSERTE( mt->IsClassPointerValid() );
5923 PTR_EEClass clazz( mt->GetClass() );
5926 PTR_MethodTable NativeImageDumper::GetParent( PTR_MethodTable mt )
5928 /* REVISIT_TODO Thu 12/01/2005
5931 PTR_MethodTable parent( ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent()) );
5932 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(parent)));
5936 //Counts the FieldDescs in a class. This is all of the non-static and static
5937 //non-literal fields.
5938 SIZE_T NativeImageDumper::CountFields( PTR_MethodTable mt )
5940 SIZE_T fieldCount = 0;
5942 HCORENUM hEnum = NULL;
5944 const Dependency * dep = GetDependencyFromMT(mt);
5945 mdToken classToken = mt->GetCl();
5948 _ASSERTE(dep->pImport);
5950 //Arrays have no token.
5951 if( RidFromToken(classToken) == 0 )
5959 IfFailThrow(dep->pImport->EnumFields( &hEnum, classToken, fields,
5966 IfFailThrow(dep->pImport->GetFieldProps( fields[0], NULL, NULL, 0,
5967 NULL, & dwAttr, NULL, NULL,
5968 NULL, NULL, NULL ) );
5969 if( !IsFdStatic(dwAttr) || !IsFdLiteral(dwAttr) )
5972 dep->pImport->CloseEnum(hEnum);
5975 const NativeImageDumper::Dependency*
5976 NativeImageDumper::GetDependencyFromMT( PTR_MethodTable mt )
5978 if( !mt->IsClassPointerValid() )
5980 //This code will not work for out of module dependencies.
5981 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))));
5983 //the EEClass is a fixup. The home for that fixup tells us the
5984 //home for the metadata.
5985 unsigned rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
5986 return GetDependencyForFixup(rva);
5988 PTR_Module module = mt->GetModule();
5989 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
5991 unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
5992 return GetDependencyForFixup(rva);
5994 return GetDependencyForModule(module);
5996 const NativeImageDumper::Dependency*
5997 NativeImageDumper::GetDependencyFromFD( PTR_FieldDesc fd )
5999 PTR_MethodTable mt = fd->GetApproxEnclosingMethodTable();
6000 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6002 //This code will not work for out of module dependencies.
6003 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(fd))));
6005 //the MethodTable has a fixup. The home for that fixup tells us the
6006 //home for the metadata.
6007 unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6008 return GetDependencyForFixup(rva);
6010 return GetDependencyFromMT(mt);
6012 const NativeImageDumper::Dependency*
6013 NativeImageDumper::GetDependencyFromMD( PTR_MethodDesc md )
6015 PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
6016 PTR_MethodTable mt = chunk->GetMethodTable();
6017 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6019 //This code will not work for out of module dependencies.
6020 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6022 //the MethodTable has a fixup. The home for that fixup tells us the
6023 //home for the metadata.
6024 unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6025 return GetDependencyForFixup(rva);
6027 return GetDependencyFromMT(mt);
6030 BOOL NativeImageDumper::DoWriteFieldAsFixup( const char * name,
6032 unsigned fieldSize, TADDR fixup)
6034 if( !CORCOMPILE_IS_POINTER_TAGGED(fixup) )
6036 if( UINT_MAX == offset )
6037 m_display->StartVStructure( name );
6039 m_display->StartVStructureWithOffset( name, offset, fieldSize );
6041 WriteElementsFixupBlob( NULL, fixup );
6042 m_display->EndVStructure(); //name
6046 void AppendTypeQualifier( CorElementType kind, DWORD rank, SString& buf )
6050 case ELEMENT_TYPE_BYREF :
6051 buf.Append( W("&") );
6053 case ELEMENT_TYPE_PTR :
6054 buf.Append( W("*") );
6056 case ELEMENT_TYPE_SZARRAY :
6057 buf.Append( W("[]") );
6059 case ELEMENT_TYPE_ARRAY :
6062 buf.Append( W("[*]") );
6066 buf.Append( W("[") );
6067 for( COUNT_T i = 0; i < rank; ++i )
6068 buf.Append( W(","));
6069 buf.Append( W("]") );
6076 void NativeImageDumper::TypeDescToString( PTR_TypeDesc td, SString& buf )
6078 _ASSERTE(!(PTR_TO_TADDR(td) & 0x2));
6079 if( td->IsGenericVariable() )
6081 PTR_TypeVarTypeDesc tvtd( PTR_TO_TADDR(td) );
6082 //From code:TypeString::AppendType
6083 mdGenericParam token = tvtd->GetToken();
6084 PTR_Module module(tvtd->GetModule());
6085 IMetaDataImport2 * pImport;
6086 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
6088 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(td))))
6090 //this is an RVA from another hardbound dependency. We cannot decode it
6091 buf.Append(W("OUT_OF_MODULE_FIXUP"));
6096 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
6097 pImport = GetDependencyForFixup(rva)->pImport;
6102 pImport = GetDependencyForModule(module)->pImport;
6104 AppendTokenName(token, buf, pImport);
6106 else if( ELEMENT_TYPE_FNPTR == td->GetInternalCorElementType() )
6108 PTR_FnPtrTypeDesc fptd( PTR_TO_TADDR(td) );
6109 buf.Append( W("(fnptr)") );
6111 else if( td->HasTypeParam() || td->IsArray() )
6113 //either a Parameter or an Array.
6114 PTR_ParamTypeDesc ptd(PTR_TO_TADDR(td));
6115 TypeHandle elemType;
6116 /* REVISIT_TODO Thu 10/5/2006
6117 * Do I need to find a rank somewhere in the TypeDesc?
6122 //td->HasTypeParam() may also be true.
6123 PTR_MethodTable mt = ptd->GetTemplateMethodTableInternal();
6124 _ASSERTE( PTR_TO_TADDR(mt) );
6125 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6127 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(ptd))))
6129 //this is an RVA from another hardbound dependency. We cannot decode it
6130 buf.Append(W("OUT_OF_MODULE_FIXUP"));
6134 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6135 FixupBlobToString(rva, buf);
6141 _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) );
6142 MethodTableToString( mt, buf );
6143 rank = PTR_ArrayTypeDesc(PTR_TO_TADDR(ptd))->GetRank();
6148 _ASSERTE(td->HasTypeParam());
6149 TypeHandle th(ptd->GetTypeParam());
6150 _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) );
6151 _ASSERTE( th.AsTAddr() );
6152 TypeHandleToString(th, buf);
6155 AppendTypeQualifier( td->GetInternalCorElementType(), rank, buf );
6160 EnumFlagsToString( (int)td->GetInternalCorElementType(), s_CorElementType, dim(s_CorElementType),
6164 void NativeImageDumper::TypeHandleToString( TypeHandle th, SString& buf )
6166 TADDR arg = th.AsTAddr();
6167 /* REVISIT_TODO Thu 10/5/2006
6168 * Is this constant somewhere?
6170 //0x2 is the subtle hint that this is a typedesc. code:TypeHandle::AsTypeDesc
6173 PTR_TypeDesc argTD( arg & ~0x2 );
6174 TypeDescToString( argTD, buf );
6178 PTR_MethodTable argMT( th.AsTAddr() );
6179 MethodTableToString( argMT, buf );
6183 void NativeImageDumper::DoWriteFieldTypeHandle( const char * name,
6189 TADDR ptr = th.AsTAddr();
6190 if( DoWriteFieldAsFixup(name, offset, fieldSize, th.AsTAddr() ) )
6194 TypeHandleToString(th, buf);
6196 buf.Append( W(" (from TypeHandle)") );
6197 /* REVISIT_TODO Fri 10/14/2005
6198 * Do a better job of this
6200 if( offset == UINT_MAX )
6202 m_display->WriteElementPointerAnnotated( name,
6203 DataPtrToDisplay(ptr),
6204 (const WCHAR*) buf );
6208 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6209 DataPtrToDisplay(ptr),
6210 (const WCHAR*) buf );
6214 void NativeImageDumper::WriteElementTypeHandle( const char * name,
6217 DoWriteFieldTypeHandle( name, UINT_MAX, UINT_MAX, th );
6220 void NativeImageDumper::DoDumpFieldStub( PTR_Stub stub, unsigned offset,
6221 unsigned fieldSize, const char * name )
6223 _ASSERTE(CHECK_OPT(EECLASSES));
6226 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6230 m_display->StartStructureWithOffset( name, offset, fieldSize,
6231 DPtrToPreferredAddr(stub),
6233 /* REVISIT_TODO Fri 10/14/2005
6236 m_display->EndStructure();
6240 #ifdef FEATURE_COMINTEROP
6241 void NativeImageDumper::DoDumpComPlusCallInfo( PTR_ComPlusCallInfo compluscall )
6243 m_display->StartStructure( "ComPlusCallInfo",
6244 DPtrToPreferredAddr(compluscall),
6245 sizeof(*compluscall) );
6247 DisplayWriteFieldPointer( m_pILStub, compluscall->m_pILStub,
6248 ComPlusCallInfo, ALWAYS);
6249 /* REVISIT_TODO Fri 12/16/2005
6250 * Coverage read stub?
6252 WriteFieldMethodTable(m_pInterfaceMT,
6253 compluscall->m_pInterfaceMT,
6254 ComPlusCallInfo, ALWAYS);
6256 PTR_MethodDesc pEventProviderMD = PTR_MethodDesc((TADDR)compluscall->m_pEventProviderMD);
6257 WriteFieldMethodDesc(m_pEventProviderMD,
6259 ComPlusCallInfo, ALWAYS);
6260 DisplayWriteFieldInt( m_cachedComSlot, compluscall->m_cachedComSlot,
6261 ComPlusCallInfo, ALWAYS );
6263 /* REVISIT_TODO Fri 12/16/2005
6264 * Dump these as mnemonics
6266 DisplayWriteFieldInt( m_flags, compluscall->m_flags,
6267 ComPlusCallInfo, ALWAYS );
6268 WriteFieldMethodDesc( m_pStubMD,
6269 compluscall->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(ComPlusCallInfo, compluscall, m_pStubMD)),
6270 ComPlusCallInfo, ALWAYS );
6273 DisplayWriteFieldInt( m_cbStackArgumentSize, compluscall->m_cbStackArgumentSize,
6274 ComPlusCallInfo, ALWAYS );
6276 DisplayWriteFieldPointer( m_pRetThunk,
6277 DataPtrToDisplay((TADDR)compluscall->m_pRetThunk),
6278 ComPlusCallInfo, ALWAYS );
6280 m_display->EndStructure(); //ComPlusCallInfo
6282 #endif // FEATURE_COMINTEROP
6284 void NativeImageDumper::DoWriteFieldStr( PTR_BYTE ptr, const char * name,
6285 unsigned offset, unsigned fieldSize )
6289 if( UINT_MAX == offset )
6290 m_display->WriteElementPointer( name, NULL );
6292 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6296 /* REVISIT_TODO Wed 03/22/2006
6297 * Obviously this does the wrong thing for UTF-8.
6301 TADDR taddr = DPtrToPreferredAddr(ptr);
6302 PTR_BYTE current = ptr;
6303 /* REVISIT_TODO Mon 03/27/2006
6304 * Actually handle UTF-8 properly
6306 while( (b = *current++) != 0 )
6307 buf.Append( (WCHAR)b );
6308 /* REVISIT_TODO Wed 03/22/2006
6309 * This seems way way way more verbose than it needs to be.
6311 if( UINT_MAX == offset )
6313 m_display->StartStructure( name, DataPtrToDisplay(taddr),
6318 m_display->StartStructureWithOffset( name, offset, fieldSize,
6319 DataPtrToDisplay(taddr),
6322 DisplayWriteElementStringW( "Value", (const WCHAR *)buf, ALWAYS );
6323 m_display->EndStructure();
6325 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6326 taddr, (const WCHAR *)buf );
6330 void NativeImageDumper::WriteFieldDictionaryLayout(const char * name,
6333 PTR_DictionaryLayout layout,
6334 IMetaDataImport2 * import)
6336 if( layout == NULL )
6338 m_display->WriteFieldPointer(name, NULL, offset, fieldSize);
6341 m_display->StartVStructureWithOffset( name, offset, fieldSize );
6342 DisplayStartArray( "DictionaryLayouts", NULL, ALWAYS );
6345 DisplayStartStructure( "DictionaryLayout", DPtrToPreferredAddr(layout),
6346 sizeof(DictionaryLayout)
6347 + sizeof(DictionaryEntryLayout)
6348 * (layout->m_numSlots - 1), ALWAYS );
6351 DisplayWriteFieldPointer( m_pNext, DataPtrToDisplay((TADDR)layout->m_pNext),
6352 DictionaryLayout, ALWAYS );
6353 DisplayWriteFieldInt( m_numSlots, layout->m_numSlots,
6354 DictionaryLayout, ALWAYS );
6355 DisplayStartArrayWithOffset( m_slots, NULL, DictionaryLayout, ALWAYS );
6356 for( unsigned i = 0; i < layout->m_numSlots; ++i )
6358 PTR_DictionaryEntryLayout entry( PTR_HOST_MEMBER_TADDR(DictionaryLayout, layout, m_slots) + (i * sizeof(DictionaryEntryLayout)) );
6359 DisplayStartStructure( "DictionaryEntryLayout",
6360 DPtrToPreferredAddr(entry), sizeof(*entry),
6362 const char * kind = NULL;
6363 switch( entry->GetKind() )
6365 #define KIND_ENTRY(x) case x : kind = # x ; break
6366 KIND_ENTRY(EmptySlot);
6367 KIND_ENTRY(TypeHandleSlot);
6368 KIND_ENTRY(MethodDescSlot);
6369 KIND_ENTRY(MethodEntrySlot);
6370 KIND_ENTRY(ConstrainedMethodEntrySlot);
6371 KIND_ENTRY(DispatchStubAddrSlot);
6372 KIND_ENTRY(FieldDescSlot);
6375 _ASSERTE( !"unreachable" );
6377 DisplayWriteElementString( "Kind", kind, ALWAYS );
6378 DisplayWriteElementPointer( "Signature", DPtrToPreferredAddr(entry->m_signature), ALWAYS );
6379 DisplayEndStructure( ALWAYS ); //DictionaryEntryLayout
6381 DisplayEndArray( "Total Dictionary Entries", ALWAYS ); //m_slots
6382 DisplayEndStructure( ALWAYS ); //Layout
6383 layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
6384 }while( layout != NULL );
6385 DisplayEndArray( "Total Dictionary Layouts", ALWAYS ); //DictionaryLayouts
6388 DisplayEndVStructure( ALWAYS ); // name
6390 void NativeImageDumper::DoWriteFieldFieldDesc( const char * name,
6397 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6402 FieldDescToString( fd, buf );
6403 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6404 DPtrToPreferredAddr(fd),
6405 (const WCHAR*) buf );
6409 void NativeImageDumper::DoWriteFieldMethodDesc( const char * name,
6416 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6418 else if( DoWriteFieldAsFixup(name, offset, fieldSize, PTR_TO_TADDR(md)) )
6425 MethodDescToString( md, buf );
6426 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6427 DPtrToPreferredAddr(md),
6428 (const WCHAR*) buf );
6432 void NativeImageDumper::EntryPointToString( TADDR pEntryPoint,
6435 const Dependency * dependency = GetDependencyForPointer(pEntryPoint);
6438 if (dependency->pModule->IsZappedPrecode(pEntryPoint))
6440 md = dac_cast<PTR_MethodDesc>(Precode::GetPrecodeFromEntryPoint(pEntryPoint)->GetMethodDesc());
6444 PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
6445 PTR_NGenLayoutInfo pNgenLayout = module->GetNGenLayoutInfo();
6446 DWORD rva = (DWORD)(pEntryPoint - PTR_TO_TADDR(m_decoder.GetBase()));
6448 for (int iRange = 0; iRange < 2; iRange++)
6450 if (pNgenLayout->m_CodeSections[iRange].IsInRange(pEntryPoint))
6452 int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1);
6453 if (MethodIndex >= 0)
6455 #ifdef WIN64EXCEPTIONS
6456 while (pNgenLayout->m_MethodDescs[iRange][MethodIndex] == 0)
6460 PTR_RUNTIME_FUNCTION pRuntimeFunction = pNgenLayout->m_pRuntimeFunctions[iRange] + MethodIndex;
6462 md = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase()));
6469 MethodDescToString(md, buf);
6472 void NativeImageDumper::MethodDescToString( PTR_MethodDesc md,
6476 buf.Append( W("mdMethodDefNil") );
6477 else if( md->IsILStub() )
6478 buf.AppendUTF8(md->AsDynamicMethodDesc()->GetName());
6481 //write the name to a temporary location, since I'm going to insert it
6482 //into the middle of a signature.
6483 TempBuffer tempName;
6485 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(md)));
6486 //work back to the EEClass. That gives us the context for the token.
6487 PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
6488 //chunk is implicitly remapped because it's calculated from the pointer
6490 PTR_MethodTable mt = chunk->GetMethodTable();
6491 const Dependency * dependency;
6492 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6494 //This code will not work for out of module dependencies.
6495 _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6497 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6498 dependency = GetDependencyForFixup(rva);
6499 mt = NULL; //make sure we don't use this for anything.
6502 dependency = GetDependencyFromMT(mt);
6504 _ASSERTE(dependency);
6507 /* REVISIT_TODO Fri 10/13/2006
6508 * Don't I need the array type name here?
6510 _ASSERTE(dependency->pImport);
6511 if( md->GetClassification() == mcArray )
6514 //We don't need to append the dependency all the time.
6515 //MethodTableToString() already appends it to the MethodTable.
6516 //Only do it in cases where we don't call MethodTableToString.
6517 if( !isSelf(dependency) )
6519 AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6521 tempName.Append(W("!"));
6524 _ASSERTE(PTR_TO_TADDR(mt));
6525 MethodTableToString( mt, tempName );
6526 tempName.Append( W("::") );
6528 //there are four hard coded names for array method descs, use these
6529 //instead of the token.
6530 PTR_ArrayMethodDesc amd(PTR_TO_TADDR(md));
6531 tempName.AppendUTF8( amd->GetMethodName() );
6535 //if we have a MethodTable, use that and compose the name
6536 //ourselves. That way we can get generic arguments.
6540 MethodTableToString( mt, tempName );
6541 tempName.Append( W("::") );
6542 IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(), NULL, bigBuffer,
6543 bigBufferSize, &size, NULL, NULL, NULL, NULL,
6545 tempName.Append(bigBuffer);
6549 //We don't need to append the dependency all the time.
6550 //MethodTableToString() already appends it to the MethodTable.
6551 //Only do it in cases where we don't call MethodTableToString.
6552 if( !isSelf(dependency) )
6554 AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6556 tempName.Append(W("!"));
6558 AppendTokenName( md->GetMemberDef(), tempName, dependency->pImport );
6561 if( mcInstantiated == md->GetClassification() )
6563 PTR_InstantiatedMethodDesc imd(PTR_TO_TADDR(md));
6564 unsigned numArgs = imd->m_wNumGenericArgs;
6565 PTR_Dictionary dict(imd->IMD_GetMethodDictionary());
6568 DictionaryToArgString( dict, numArgs, tempName );
6572 PCCOR_SIGNATURE pvSigBlob;
6574 IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(),
6586 CQuickBytes prettySig;
6587 ReleaseHolder<IMDInternalImport> pInternal;
6588 IfFailThrow(GetMDInternalInterfaceFromPublic(dependency->pImport, IID_IMDInternalImport,
6589 (void**)&pInternal));
6590 StackScratchBuffer buffer;
6591 const ANSI * ansi = tempName.GetANSI(buffer);
6592 ansi = PrettyPrintSig(pvSigBlob, cbSigBlob, ansi, &prettySig, pInternal, NULL);
6593 tempName.SetANSI( ansi );
6595 buf.Append(tempName);
6598 void NativeImageDumper::WriteElementMethodDesc( const char * name,
6603 m_display->WriteElementPointer( name, NULL );
6608 MethodDescToString( md, buf );
6609 m_display->WriteElementPointerAnnotated( name, DPtrToPreferredAddr(md),
6610 (const WCHAR*) buf );
6613 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, SString& buf )
6615 FieldDescToString( fd, mdFieldDefNil, buf );
6617 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, mdFieldDef tok,
6620 IF_OPT(DISABLE_NAMES)
6622 buf.Append( W("Disabled") );
6627 if( tok == mdFieldDefNil )
6628 buf.Append( W("mdFieldDefNil") );
6630 AppendTokenName( tok, buf );
6634 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(fd)));
6635 IMetaDataImport2 * importMD = NULL;
6636 if( !isInRange(PTR_TO_TADDR(fd)) )
6638 const Dependency * dependency = GetDependencyFromFD(fd);
6639 _ASSERTE(dependency);
6640 AppendTokenName( dependency->entry->dwAssemblyRef, buf,
6643 importMD = dependency->pImport;
6649 importMD = m_import;
6651 AppendTokenName( fd->GetMemberDef(), buf, importMD );
6655 void NativeImageDumper::DoWriteFieldAsHex( const char * name, unsigned offset,
6656 unsigned fieldSize, PTR_BYTE ptr,
6660 for( unsigned i = 0; i < dataLen; ++i )
6662 unsigned char b = ptr[i];
6663 buffer.AppendPrintf( W("%02x%02x"), (b & 0xf0) >> 4, b & 0xf );
6665 if( offset == UINT_MAX )
6667 m_display->WriteElementStringW( name, (const WCHAR *)buffer );
6671 m_display->WriteFieldStringW( name, offset, fieldSize,
6672 (const WCHAR *)buffer );
6675 void NativeImageDumper::WriteElementMDToken( const char * name, mdToken token )
6677 DoWriteFieldMDToken( name, UINT_MAX, UINT_MAX, token );
6679 void NativeImageDumper::DoWriteFieldMDToken( const char * name, unsigned offset,
6680 unsigned fieldSize, mdToken token,
6681 IMetaDataImport2 * import )
6684 if( RidFromToken(token) == mdTokenNil )
6686 AppendNilToken( token, buf );
6690 AppendToken( token, buf, import );
6692 if( UINT_MAX == offset )
6693 m_display->WriteElementEnumerated( name, token, (const WCHAR *)buf );
6696 m_display->WriteFieldEnumerated(name, offset, fieldSize, token,
6701 void NativeImageDumper::WriteElementMethodTable( const char * name,
6702 PTR_MethodTable mt )
6704 DoWriteFieldMethodTable( name, UINT_MAX, UINT_MAX, mt );
6706 void NativeImageDumper::DoWriteFieldMethodTable( const char * name,
6709 PTR_MethodTable mt )
6713 if( UINT_MAX == offset )
6714 m_display->WriteElementPointer( name, NULL );
6716 m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6718 else if( DoWriteFieldAsFixup( name, offset, fieldSize, PTR_TO_TADDR(mt) ) )
6725 MethodTableToString( mt, buf );
6726 if( UINT_MAX == offset )
6729 m_display->WriteElementPointerAnnotated( name,
6730 DPtrToPreferredAddr(mt),
6731 (const WCHAR*) buf );
6735 m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6736 DPtrToPreferredAddr(mt),
6737 (const WCHAR*) buf );
6742 const char * s_VTSCallbackNames[] =
6744 #define VTSCB_ENTRY(x) # x
6745 VTSCB_ENTRY(VTS_CALLBACK_ON_SERIALIZING),
6746 VTSCB_ENTRY(VTS_CALLBACK_ON_SERIALIZED),
6747 VTSCB_ENTRY(VTS_CALLBACK_ON_DESERIALIZING),
6748 VTSCB_ENTRY(VTS_CALLBACK_ON_DESERIALIZED),
6751 void NativeImageDumper::DumpFieldDesc( PTR_FieldDesc fd, const char * name )
6753 DisplayStartStructure( name, DPtrToPreferredAddr(fd), sizeof(*fd),
6755 WriteFieldMethodTable( m_pMTOfEnclosingClass,
6756 fd->GetApproxEnclosingMethodTable(), FieldDesc, ALWAYS );
6757 m_display->WriteFieldUInt( "m_mb", offsetof(FieldDesc, m_dword1),
6758 fieldsize(FieldDesc, m_dword1),
6759 fd->GetMemberDef() );
6760 m_display->WriteFieldFlag( "m_isStatic",
6761 offsetof(FieldDesc, m_dword1),
6762 fieldsize(FieldDesc, m_dword1),
6764 m_display->WriteFieldFlag( "m_isThreadLocal",
6765 offsetof(FieldDesc, m_dword1),
6766 fieldsize(FieldDesc, m_dword1),
6767 fd->m_isThreadLocal );
6768 m_display->WriteFieldFlag( "m_isRVA", offsetof(FieldDesc, m_dword1),
6769 fieldsize(FieldDesc, m_dword1),
6774 EnumFlagsToString( fd->m_prot, s_CorFieldAttr,
6775 _countof(s_CorFieldAttr), W(" "), buf );
6776 m_display->WriteFieldEnumerated( "m_prot",
6777 offsetof(FieldDesc, m_dword1),
6778 fieldsize(FieldDesc, m_dword1),
6779 fd->m_prot, (const WCHAR *)buf );
6781 m_display->WriteFieldFlag( "m_requiresFullMbValue",
6782 offsetof(FieldDesc, m_dword1),
6783 fieldsize(FieldDesc, m_dword1),
6784 fd->m_requiresFullMbValue );
6785 m_display->WriteFieldInt( "m_dwOffset",
6786 offsetof(FieldDesc, m_dword2),
6787 fieldsize(FieldDesc, m_dword2),
6789 DoWriteFieldCorElementType( "m_type",
6790 offsetof(FieldDesc, m_dword2),
6791 fieldsize(FieldDesc, m_dword2),
6792 (CorElementType)fd->m_type );
6794 WriteFieldStr( m_debugName, PTR_BYTE(TO_TADDR(fd->m_debugName)),
6795 FieldDesc, ALWAYS );
6797 DisplayEndStructure( ALWAYS ); //name
6801 #pragma warning(push)
6802 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
6805 NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name,
6808 _ASSERTE(NULL != mt);
6810 bool haveCompleteExtents = true;
6811 PTR_EEClass clazz = NULL;
6812 if( !mt->IsCanonicalMethodTable() && CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt->GetCanonicalMethodTable())) )
6814 /* REVISIT_TODO Wed 02/01/2006
6815 * GetExtent requires the class in order to compute GetInstAndDictSize.
6816 * If the EEClass isn't present, I cannot compute the size. If we are
6817 * in this case, skip all of the generic dictionaries.
6819 haveCompleteExtents = false;
6821 MethodTableToString( mt, buf );
6822 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 );
6824 else if( !m_isMscorlibHardBound )
6826 /* REVISIT_TODO Mon 8/20/2007
6827 * If we're not hard bound to mscorlib, most things don't work. They depend on knowing what
6828 * g_pObjectClass is. Without the hard binding to mscorlib, I can't figure that out.
6830 haveCompleteExtents = false;
6832 if( haveCompleteExtents )
6834 mt->GetSavedExtent(&start, &end);
6835 clazz = mt->GetClass();
6839 start = PTR_TO_TADDR(mt);
6840 end = start + sizeof(*mt);
6842 IF_OPT(METHODTABLES)
6844 m_display->StartStructureWithNegSpace( name, DPtrToPreferredAddr(mt),
6845 DataPtrToDisplay(start), end - start );
6848 IF_OPT(METHODTABLES)
6852 MethodTableToString( mt, buf );
6853 DisplayWriteElementStringW( "Name", (const WCHAR *)buf, ALWAYS );
6855 if( mt->ContainsPointers() )
6857 PTR_CGCDesc cgc = CGCDesc::GetCGCDescFromMT(mt);
6858 unsigned size = (unsigned)cgc->GetSize();
6859 /* REVISIT_TODO Tue 12/13/2005
6860 * Does anyone actually care about what's inside here?
6862 m_display->WriteFieldEmpty( "CGCDesc", ~size + 1, size );
6866 /* XXX Mon 10/24/2005
6867 * The MT might have a component size as the low WORD of the m_dwFlags
6868 * field, if it doesn't then that field instead represents a number of
6869 * flags, which we know as the "low flags"
6871 if (mt->HasComponentSize())
6873 DisplayWriteElementInt( "ComponentSize", mt->RawGetComponentSize(),
6878 DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & 0xFFFF, MethodTable,
6879 s_MTFlagsLow, W(", "), METHODTABLES );
6882 /* XXX Fri 10/07/2005
6883 * The low WORD of the flags is used for either a component size or flags
6884 * (see above), the high WORD is always flags. If this changes then this
6887 DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & ~0xFFFF, MethodTable,
6888 s_MTFlagsHigh, W(", "), METHODTABLES );
6890 DisplayWriteFieldInt( m_BaseSize, mt->m_BaseSize, MethodTable,
6893 DisplayWriteFieldEnumerated( m_wFlags2, mt->m_wFlags2, MethodTable,
6894 s_MTFlags2, W(", "), METHODTABLES );
6896 DisplayWriteFieldInt( m_wToken, mt->m_wToken, MethodTable,
6898 DisplayWriteFieldInt( m_wNumVirtuals, mt->m_wNumVirtuals, MethodTable,
6900 DisplayWriteFieldInt( m_wNumInterfaces, mt->m_wNumInterfaces, MethodTable,
6905 PTR_MethodTable parent = ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent());
6906 if( parent == NULL )
6908 DisplayWriteFieldPointer( m_pParentMethodTable, NULL, MethodTable,
6913 IF_OPT(METHODTABLES)
6915 DoWriteFieldMethodTable( "m_pParentMethodTable",
6916 offsetof(MethodTable, m_pParentMethodTable),
6917 fieldsize(MethodTable, m_pParentMethodTable),
6918 mt->GetParentMethodTable() );
6921 DisplayWriteFieldPointer( m_pLoaderModule,
6922 DPtrToPreferredAddr(mt->GetLoaderModule()),
6923 MethodTable, METHODTABLES );
6925 PTR_MethodTableWriteableData wd = ReadPointer((MethodTable *)mt, &MethodTable::m_pWriteableData);
6926 _ASSERTE(wd != NULL);
6927 DisplayStartStructureWithOffset( m_pWriteableData, DPtrToPreferredAddr(wd),
6928 sizeof(*wd), MethodTable, METHODTABLES );
6929 DisplayWriteFieldEnumerated( m_dwFlags, wd->m_dwFlags,
6930 MethodTableWriteableData, s_WriteableMTFlags,
6931 W(", "), METHODTABLES );
6932 DisplayWriteFieldPointer( m_hExposedClassObject,
6933 DataPtrToDisplay(wd->m_hExposedClassObject),
6934 MethodTableWriteableData, METHODTABLES );
6935 _ASSERTE(wd->m_hExposedClassObject == 0);
6936 DisplayEndStructure( METHODTABLES ); //m_pWriteableData
6938 if( !mt->IsCanonicalMethodTable() )
6940 WriteFieldMethodTable( m_pCanonMT, mt->GetCanonicalMethodTable(),
6941 MethodTable, METHODTABLES );
6945 DisplayWriteFieldPointer( m_pEEClass, DPtrToPreferredAddr(mt->GetClass()),
6946 MethodTable, METHODTABLES );
6951 WriteFieldTypeHandle( m_ElementTypeHnd,
6952 mt->GetApproxArrayElementTypeHandle(),
6953 MethodTable, METHODTABLES );
6956 if( mt->HasPerInstInfo() && haveCompleteExtents )
6958 //print out the generics dictionary info, and then print out
6959 //the contents of those dictionaries.
6960 PTR_GenericsDictInfo di = mt->GetGenericsDictInfo();
6961 _ASSERTE(NULL != di);
6963 DisplayStartStructure("GenericsDictInfo", DPtrToPreferredAddr(di), sizeof(*di), METHODTABLES);
6965 DisplayWriteFieldInt( m_wNumDicts, di->m_wNumDicts, GenericsDictInfo,
6967 DisplayWriteFieldInt( m_wNumTyPars, di->m_wNumTyPars,
6968 GenericsDictInfo, METHODTABLES);
6969 DisplayEndStructure( METHODTABLES ); //GenericsDictInfo
6971 DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo();
6973 DisplayStartStructure( "PerInstInfo",
6974 DPtrToPreferredAddr(perInstInfo),
6975 mt->GetPerInstInfoSize(),
6977 /* XXX Tue 10/11/2005
6978 * Only dump this type's dictionary, rather than the inherited
6979 * dictionaries. (there are multiple entries in m_pPerInstInfo, but
6980 * only print the last one, which is the one for this class).
6981 * cloned from Genericdict.cpp
6983 PTR_Dictionary currentDictionary(mt->GetDictionary());
6984 if( currentDictionary != NULL )
6986 PTR_DictionaryEntry entry(currentDictionary->EntryAddr(0));
6988 PTR_DictionaryLayout layout( clazz->GetDictionaryLayout() );
6990 DisplayStartStructure( "Dictionary",
6991 DPtrToPreferredAddr(currentDictionary),
6992 //if there is a layout, use it to compute
6993 //the size, otherwise there is just the one
6995 DictionaryLayout::GetFirstDictionaryBucketSize(mt->GetNumGenericArgs(), layout),
6998 DisplayStartArrayWithOffset( m_pEntries, NULL, Dictionary,
7001 /* REVISIT_TODO Thu 12/15/2005
7002 * use VERBOSE_TYPES here.
7004 _ASSERTE(CHECK_OPT(METHODTABLES));
7006 //for each generic arg, there is a type handle slot
7007 for( unsigned i = 0; i < mt->GetNumGenericArgs(); ++i )
7008 DumpDictionaryEntry("Entry", TypeHandleSlot, entry + i);
7010 //now check for a layout. If it is present, then there are more
7012 if( layout != NULL && (layout->GetNumUsedSlots() > 0) )
7014 unsigned numUsedSlots = layout->GetNumUsedSlots();
7015 for( unsigned i = 0; i < numUsedSlots; ++i )
7017 //DictionaryLayout::GetEntryLayout
7018 PTR_DictionaryEntryLayout entryLayout(layout->GetEntryLayout(i));
7020 //Dictionary::GetSlotAddr
7021 PTR_DictionaryEntry ent(currentDictionary->EntryAddr(mt->GetNumGenericArgs() + i));
7023 DumpDictionaryEntry( "Entry", entryLayout->GetKind(), ent );
7026 if( layout != NULL )
7028 /* REVISIT_TODO Thu 12/15/2005
7029 * Where is this data?
7032 DisplayEndArray( "Total Per instance Info",
7033 METHODTABLES ); //m_pEntries
7034 DisplayEndStructure( METHODTABLES ); //Dictionary
7036 DisplayEndStructure( METHODTABLES ); //m_pPerInstInfo
7040 WriteFieldStr( debug_m_szClassName,
7041 PTR_BYTE(TO_TADDR(mt->debug_m_szClassName)), MethodTable,
7043 #if 0 //already dumping the optional member
7044 PTR_InterfaceInfo imap( TO_TADDR(mt->m_pIMapDEBUG) );
7045 /* REVISIT_TODO Mon 10/24/2005
7046 * Dump interface map
7048 DisplayStartArrayWithOffset( m_pIMapDEBUG, NULL, MethodTable,
7050 DisplayEndArray( "Total Interfaces", METHODTABLES );
7054 if( mt->HasDispatchMapSlot() )
7056 PTR_DispatchMap dispatchMap(mt->GetDispatchMap());
7058 DisplayStartStructure( "DispatchMap",
7059 DPtrToPreferredAddr(dispatchMap),
7060 DispatchMap::GetObjectSize(dispatchMap->GetMapSize()),
7063 IF_OPT(VERBOSE_TYPES )
7065 DispatchMap::Iterator iter(mt);
7066 DisplayStartArray( "DispatchMap", NULL, VERBOSE_TYPES );
7067 while( iter.Next() )
7069 DispatchMapEntry * ent = iter.Entry();
7071 DisplayStartElement( "Entry", METHODTABLES );
7072 DisplayStartVStructure( "TypeID", METHODTABLES );
7073 DispatchMapTypeID typeID = ent->GetTypeID();
7074 if( typeID.IsThisClass() )
7075 DisplayWriteElementFlag("IsThisClass", true, METHODTABLES );
7076 else if( typeID.IsImplementedInterface() )
7078 DisplayWriteElementFlag( "IsImplementedInterface",
7079 true, METHODTABLES );
7080 DisplayWriteElementInt( "GetInterfaceNum",
7081 typeID.GetInterfaceNum(), METHODTABLES );
7083 DisplayEndStructure( METHODTABLES ); //TypeID
7084 m_display->WriteElementInt( "SlotNumber",
7085 ent->GetSlotNumber() );
7086 DisplayWriteElementInt( "TargetSlotNumber",
7087 ent->GetSlotNumber(), METHODTABLES );
7089 m_display->EndElement(); //Entry
7092 DisplayEndArray("Total Dispatch Map Entries", METHODTABLES );
7096 CoverageRead(PTR_TO_TADDR(dispatchMap),
7097 DispatchMap::GetObjectSize(dispatchMap->GetMapSize()));
7100 DisplayEndStructure( METHODTABLES ); //DispatchMap
7103 IF_OPT( METHODTABLES )
7105 m_display->StartStructureWithOffset("Vtable",
7106 mt->GetVtableOffset(),
7107 mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t),
7108 DataPtrToDisplay(PTR_TO_TADDR(mt) + mt->GetVtableOffset()),
7109 mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t));
7112 MethodTable::VtableIndirectionSlotIterator itIndirect = mt->IterateVtableIndirectionSlots();
7113 while (itIndirect.Next())
7116 sc.addr = dac_cast<TADDR>(itIndirect.GetIndirectionSlot());
7117 sc.nSlots = (WORD)itIndirect.GetNumSlots();
7118 sc.isRelative = MethodTable::VTableIndir2_t::isRelative;
7119 m_discoveredSlotChunks.AppendEx(sc);
7122 IF_OPT(VERBOSE_TYPES)
7124 DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7125 for( unsigned i = 0; i < mt->GetNumVtableIndirections(); ++i )
7127 DisplayStartElement( "Slot", ALWAYS );
7128 DisplayWriteElementInt( "Index", i, ALWAYS );
7129 TADDR base = dac_cast<TADDR>(&(mt->GetVtableIndirections()[i]));
7130 DPTR(MethodTable::VTableIndir2_t) tgt = MethodTable::VTableIndir_t::GetValueMaybeNullAtPtr(base);
7131 DisplayWriteElementPointer( "Pointer",
7132 DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7134 DisplayWriteElementString( "Type", "chunk indirection",
7136 DisplayEndElement( ALWAYS ); //Slot
7139 if (mt->HasNonVirtualSlotsArray())
7141 DisplayStartElement( "Slot", ALWAYS );
7142 DisplayWriteElementInt( "Index", -1, ALWAYS );
7143 PTR_PCODE tgt = mt->GetNonVirtualSlotsArray();
7144 DisplayWriteElementPointer( "Pointer",
7145 DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7147 DisplayWriteElementString( "Type", "non-virtual chunk indirection",
7149 DisplayEndElement( ALWAYS ); //Slot
7152 sc.addr = dac_cast<TADDR>(tgt);
7153 sc.nSlots = (mt->GetNumVtableSlots() - mt->GetNumVirtuals());
7154 sc.isRelative = false;
7155 m_discoveredSlotChunks.AppendEx(sc);
7157 else if (mt->HasSingleNonVirtualSlot())
7159 DumpSlot((unsigned)-1, mt->GetSlot(mt->GetNumVirtuals()));
7162 DisplayEndList( ALWAYS ); //vtable
7166 CoverageRead( PTR_TO_TADDR(mt) + mt->GetVtableOffset(),
7167 mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t) );
7169 if (mt->HasNonVirtualSlotsArray())
7171 CoverageRead( PTR_TO_TADDR(mt->GetNonVirtualSlotsArray()),
7172 mt->GetNonVirtualSlotsArraySize() );
7176 DisplayEndStructure(ALWAYS); //Vtable
7179 if( mt->HasInterfaceMap() && CHECK_OPT(METHODTABLES) )
7181 PTR_InterfaceInfo ifMap = mt->GetInterfaceMap();
7182 m_display->StartArrayWithOffset( "InterfaceMap",
7183 offsetof(MethodTable, m_pInterfaceMap),
7186 for( unsigned i = 0; i < mt->GetNumInterfaces(); ++i )
7188 PTR_InterfaceInfo info = ifMap + i;
7189 DisplayStartStructure( "InterfaceInfo_t", DPtrToPreferredAddr(info),
7190 sizeof(*info), METHODTABLES );
7191 WriteFieldMethodTable( m_pMethodTable,
7192 info->GetMethodTable(),
7193 InterfaceInfo_t, METHODTABLES );
7194 DisplayEndStructure( METHODTABLES ); //InterfaceInfo_t
7196 DisplayEndArray( "Total InterfaceInfos",
7197 METHODTABLES ); //InterfaceMap
7200 //rest of the optional members
7202 //GenericStatics comes after the generic dictionaries. So if I
7203 //don't have extents, I can't print them.
7204 if( haveCompleteExtents &&
7205 mt->HasGenericsStaticsInfo() &&
7206 CHECK_OPT(METHODTABLES)
7209 PTR_GenericsStaticsInfo genStatics = mt->GetGenericsStaticsInfo();
7210 m_display->StartStructureWithOffset( "OptionalMember_"
7211 "GenericsStaticsInfo",
7212 mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GenericsStaticsInfo),
7213 sizeof(*genStatics),
7214 DPtrToPreferredAddr(genStatics),
7215 sizeof(*genStatics) );
7217 PTR_FieldDesc fieldDescs = ReadPointerMaybeNull((GenericsStaticsInfo *) genStatics, &GenericsStaticsInfo::m_pFieldDescs);
7218 if( fieldDescs == NULL )
7220 DisplayWriteFieldPointer( m_pFieldDescs, NULL, GenericsStaticsInfo,
7225 DisplayStartArrayWithOffset( m_pFieldDescs, NULL,
7226 GenericsStaticsInfo, ALWAYS );
7227 _ASSERTE(clazz == GetClassFromMT(mt));
7228 for( int i = 0; i < clazz->GetNumStaticFields(); ++i )
7230 PTR_FieldDesc fd = fieldDescs + i;
7231 DumpFieldDesc( fd, "FieldDesc" );
7233 DisplayEndArray( "Total Static Fields", ALWAYS ); // m_pFieldDescs
7235 DisplayWriteFieldUInt( m_DynamicTypeID, (DWORD)genStatics->m_DynamicTypeID,
7236 GenericsStaticsInfo, METHODTABLES );
7238 DisplayEndStructure( METHODTABLES );//OptionalMember_GenericsStaticsInfo
7242 #ifdef FEATURE_COMINTEROP
7243 if (haveCompleteExtents &&
7244 mt->HasGuidInfo() &&
7245 CHECK_OPT(METHODTABLES)
7248 PTR_GuidInfo guidInfo(*mt->GetGuidInfoPtr());
7250 if (guidInfo != NULL)
7252 m_display->StartStructureWithOffset( "OptionalMember_GuidInfo",
7253 mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GuidInfo),
7255 DPtrToPreferredAddr(guidInfo),
7259 GuidToString( guidInfo->m_Guid, buf );
7260 DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
7262 DisplayWriteFieldFlag( m_bGeneratedFromName,
7263 guidInfo->m_bGeneratedFromName,
7265 DisplayEndStructure( ALWAYS ); // OptionalMember_GuidInfo
7269 if (haveCompleteExtents &&
7270 mt->HasCCWTemplate()
7271 && CHECK_OPT(METHODTABLES)
7274 PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(*mt->GetCCWTemplatePtr()));
7275 m_display->WriteFieldPointer( "OptionalMember_CCWTemplate",
7276 mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_CCWTemplate),
7278 DPtrToPreferredAddr(ccwTemplate)
7281 #endif // FEATURE_COMINTEROP
7283 DisplayEndStructure( METHODTABLES ); //MethodTable
7284 } // NativeImageDumper::DumpMethodTable
7286 #pragma warning(pop)
7290 NativeImageDumper::DumpMethodTableSlotChunk( TADDR slotChunk, COUNT_T numSlots, bool isRelative )
7292 IF_OPT( METHODTABLES )
7297 slotsSize = numSlots * sizeof(RelativePointer<PCODE>);
7301 slotsSize = numSlots * sizeof(PCODE);
7303 DisplayStartStructure( "MethodTableSlotChunk", DataPtrToDisplay(slotChunk), slotsSize, METHODTABLES );
7305 IF_OPT(VERBOSE_TYPES)
7307 DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7308 for( unsigned i = 0; i < numSlots; ++i )
7313 target = RelativePointer<PCODE>::GetValueMaybeNullAtPtr(slotChunk + i * sizeof(RelativePointer<PCODE>));
7317 target = dac_cast<PTR_PCODE>(slotChunk)[i];
7320 DumpSlot(i, target);
7322 DisplayEndList( ALWAYS ); //Slot list
7325 CoverageRead( slotChunk, slotsSize );
7326 DisplayEndStructure(ALWAYS); //Slot chunk
7332 NativeImageDumper::DumpSlot( unsigned index, PCODE tgt )
7334 IF_OPT(VERBOSE_TYPES)
7336 DisplayStartElement( "Slot", ALWAYS );
7337 DisplayWriteElementInt( "Index", index, ALWAYS );
7338 DisplayWriteElementPointer( "Pointer",
7339 DataPtrToDisplay(tgt),
7341 if( !isInRange(TO_TADDR(tgt)) )
7343 DisplayWriteElementString( "Type", "external",
7346 else if( isPrecode(TO_TADDR(tgt))
7347 && Precode::IsValidType(PTR_Precode(TO_TADDR(tgt))->GetType()) )
7349 PTR_Precode precode(TO_TADDR(tgt));
7350 DisplayWriteElementString( "Type", "precode",
7352 //DumpPrecode( precode, module );
7356 DisplayWriteElementString( "Type", "code pointer",
7359 DisplayEndElement( ALWAYS ); //Slot
7363 NativeImageDumper::EnumMnemonics NativeImageDumper::s_SSMDExtendedFlags[] =
7365 #define SSMD_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
7367 #define SSMD_ACCESS_ENTRY(x) NativeImageDumper::EnumMnemonics( x, mdMemberAccessMask, W(#x) )
7368 SSMD_ACCESS_ENTRY(mdPrivateScope),
7369 SSMD_ACCESS_ENTRY(mdPrivate),
7370 SSMD_ACCESS_ENTRY(mdFamANDAssem),
7371 SSMD_ACCESS_ENTRY(mdAssem),
7372 SSMD_ACCESS_ENTRY(mdFamily),
7373 SSMD_ACCESS_ENTRY(mdFamORAssem),
7374 SSMD_ACCESS_ENTRY(mdPublic),
7375 #undef SSMD_ACCESS_ENTRY
7377 SSMD_ENTRY(mdStatic),
7378 SSMD_ENTRY(mdFinal),
7379 SSMD_ENTRY(mdVirtual),
7380 SSMD_ENTRY(mdHideBySig),
7382 SSMD_ENTRY(mdVtableLayoutMask),
7383 SSMD_ENTRY(mdNewSlot),
7385 SSMD_ENTRY(mdCheckAccessOnOverride),
7386 SSMD_ENTRY(mdAbstract),
7387 SSMD_ENTRY(mdSpecialName),
7389 SSMD_ENTRY(mdPinvokeImpl),
7390 SSMD_ENTRY(mdUnmanagedExport),
7392 SSMD_ENTRY(mdRTSpecialName),
7393 SSMD_ENTRY(mdHasSecurity),
7394 SSMD_ENTRY(mdRequireSecObject),
7396 NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdILStub,
7398 NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdLCGMethod,
7399 W("nomdLCGMethod") ),
7403 //maps MethodClassification to a name for a MethodDesc
7404 const char * const s_MDTypeName[] =
7406 "MethodDesc", //mcIL
7407 "FCallMethodDesc", //mcFCall
7408 "NDirectMethodDesc", //mcNDirect
7409 "EEImplMethodDesc", //mcEEImpl - //public StoredSigMethodDesc
7410 "ArrayMethodDesc", //mcArray - //public StoredSigMethodDesc
7411 "InstantiatedMethodDesc", //mcInstantiated
7412 #if defined(FEATURE_COMINTEROP)
7413 "ComPlusCallMethodDesc", //mcComInterop
7417 "DynamicMethodDesc", //mcDynamic -- //public StoredSigMethodDesc
7420 unsigned s_MDSizes[] =
7422 sizeof(MethodDesc), //mcIL
7423 sizeof(FCallMethodDesc), //mcFCall
7424 sizeof(NDirectMethodDesc), //mcNDirect
7425 sizeof(EEImplMethodDesc), //mcEEImpl
7426 sizeof(ArrayMethodDesc), //mcArray
7427 sizeof(InstantiatedMethodDesc), //mcInstantiated
7428 #if defined(FEATURE_COMINTEROP)
7429 sizeof(ComPlusCallMethodDesc), //mcComInterop
7433 sizeof(DynamicMethodDesc), //mcDynamic
7436 static NativeImageDumper::EnumMnemonics g_NDirectFlags[] =
7438 #define NDF_ENTRY(x) NativeImageDumper::EnumMnemonics( NDirectMethodDesc:: x, W(#x) )
7439 NDF_ENTRY(kEarlyBound),
7440 NDF_ENTRY(kHasSuppressUnmanagedCodeAccess),
7441 NDF_ENTRY(kIsMarshalingRequiredCached),
7442 NDF_ENTRY(kCachedMarshalingRequired),
7443 NDF_ENTRY(kNativeAnsi),
7444 NDF_ENTRY(kLastError),
7445 NDF_ENTRY(kNativeNoMangle),
7446 NDF_ENTRY(kVarArgs),
7447 NDF_ENTRY(kStdCall),
7448 NDF_ENTRY(kThisCall),
7449 NDF_ENTRY(kIsQCall),
7450 NDF_ENTRY(kStdCallWithRetBuf),
7453 NativeImageDumper::EnumMnemonics NativeImageDumper::s_IMDFlags[] =
7455 #define IMD_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, W(#x) )
7457 #define IMD_KIND_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, InstantiatedMethodDesc::KindMask, W(#x) )
7458 IMD_KIND_ENTRY(GenericMethodDefinition),
7459 IMD_KIND_ENTRY(UnsharedMethodInstantiation),
7460 IMD_KIND_ENTRY(SharedMethodInstantiation),
7461 IMD_KIND_ENTRY(WrapperStubWithInstantiations),
7462 #undef IMD_KIND_ENTRY
7464 #ifdef EnC_SUPPORTED
7465 // Method is a new virtual function added through EditAndContinue.
7466 IMD_ENTRY(EnCAddedMethod),
7467 #endif // EnC_SUPPORTED
7469 IMD_ENTRY(Unrestored),
7471 #ifdef FEATURE_COMINTEROP
7472 IMD_ENTRY(HasComPlusCallInfo),
7473 #endif // FEATURE_COMINTEROP
7478 void NativeImageDumper::DumpPrecode( PTR_Precode precode, PTR_Module module )
7480 _ASSERTE(isPrecode(PTR_TO_TADDR(precode)));
7482 PrecodeType pType = precode->GetType();
7485 #define DISPLAY_PRECODE(type) \
7486 IF_OPT_AND(PRECODES, METHODDESCS) \
7488 PTR_ ## type p( precode->As ## type () ); \
7489 DisplayStartStructure( # type, \
7490 DPtrToPreferredAddr(p), \
7491 sizeof(*p), ALWAYS ); \
7492 WriteFieldMethodDesc( m_pMethodDesc, \
7495 TADDR target = p->GetTarget(); \
7496 DisplayWriteElementPointer("Target",\
7497 DataPtrToDisplay(target),\
7499 DisplayEndStructure( ALWAYS ); \
7503 DISPLAY_PRECODE(StubPrecode); break;
7504 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7505 case PRECODE_NDIRECT_IMPORT:
7506 DISPLAY_PRECODE(NDirectImportPrecode); break;
7508 #ifdef HAS_FIXUP_PRECODE
7510 IF_OPT_AND(PRECODES, METHODDESCS)
7512 PTR_FixupPrecode p( precode->AsFixupPrecode() );
7513 DisplayStartStructure( "FixupPrecode",
7514 DPtrToPreferredAddr(p),
7517 PTR_MethodDesc precodeMD(p->GetMethodDesc());
7518 #ifdef HAS_FIXUP_PRECODE_CHUNKS
7520 DisplayWriteFieldInt( m_MethodDescChunkIndex,
7521 p->m_MethodDescChunkIndex, FixupPrecode,
7523 DisplayWriteFieldInt( m_PrecodeChunkIndex,
7524 p->m_PrecodeChunkIndex, FixupPrecode,
7526 if( p->m_PrecodeChunkIndex == 0 )
7528 //dump the location of the Base
7529 DisplayWriteElementAddress( "PrecodeChunkBase",
7530 DataPtrToDisplay(p->GetBase()),
7531 sizeof(void*), ALWAYS );
7533 //Make sure I align up if there is no code slot to make
7534 //sure that I get the padding
7535 TADDR mdPtrStart = p->GetBase()
7536 + (p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
7537 TADDR mdPtrEnd = ALIGN_UP( mdPtrStart + sizeof(MethodDesc*),
7539 CoverageRead( mdPtrStart, (ULONG32)(mdPtrEnd - mdPtrStart) );
7540 TADDR precodeMDSlot = p->GetBase()
7541 + p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT;
7542 DoWriteFieldMethodDesc( "MethodDesc",
7543 (DWORD)(precodeMDSlot - PTR_TO_TADDR(p)),
7544 sizeof(TADDR), precodeMD );
7546 #else //HAS_FIXUP_PRECODE_CHUNKS
7547 WriteFieldMethodDesc( m_pMethodDesc,
7549 FixupPrecode, ALWAYS );
7550 #endif //HAS_FIXUP_PRECODE_CHUNKS
7551 TADDR target = p->GetTarget();
7552 DisplayWriteElementPointer("Target",
7553 DataPtrToDisplay(target),
7555 /* REVISIT_TODO Thu 01/05/2006
7556 * dump slot with offset if it is here
7558 DisplayEndStructure( ALWAYS ); //FixupPrecode
7562 #ifdef HAS_THISPTR_RETBUF_PRECODE
7563 case PRECODE_THISPTR_RETBUF:
7564 DISPLAY_PRECODE(ThisPtrRetBufPrecode); break;
7567 _ASSERTE( !"Unsupported precode type" );
7568 #undef DISPLAY_PRECODE
7569 #undef PrecodeMDWrite
7574 #pragma warning(push)
7575 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
7577 void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module )
7579 //StoredSigMethodDesc
7581 MethodClassification mc =
7582 (MethodClassification)md->GetClassification();
7583 _ASSERTE(mc >= 0 && mc < mcCount);
7584 const char * mdTypeName = s_MDTypeName[mc];
7585 unsigned mdSize = (unsigned)md->SizeOf();
7587 DisplayStartStructure( mdTypeName, DPtrToPreferredAddr(md),
7588 mdSize, METHODDESCS );
7592 MethodDescToString( md, buf );
7593 DisplayWriteElementStringW( "Name", (const WCHAR *)buf, METHODDESCS );
7598 WriteFieldStr(m_pszDebugMethodName,
7599 PTR_BYTE(TO_TADDR(md->m_pszDebugMethodName)),
7600 MethodDesc, METHODDESCS);
7601 WriteFieldStr(m_pszDebugClassName,
7602 PTR_BYTE(TO_TADDR(md->m_pszDebugClassName)),
7603 MethodDesc, METHODDESCS);
7604 WriteFieldStr(m_pszDebugMethodSignature,
7605 PTR_BYTE(TO_TADDR(md->m_pszDebugMethodSignature)),
7606 MethodDesc, METHODDESCS);
7610 CoverageReadString(TO_TADDR(md->m_pszDebugMethodName));
7611 CoverageReadString(TO_TADDR(md->m_pszDebugClassName));
7612 CoverageReadString(TO_TADDR(md->m_pszDebugMethodSignature));
7616 DisplayWriteFieldInt( m_wFlags3AndTokenRemainder, md->m_wFlags3AndTokenRemainder,
7617 MethodDesc, METHODDESCS );
7619 DisplayWriteFieldInt( m_chunkIndex, md->m_chunkIndex,
7620 MethodDesc, METHODDESCS );
7622 /* XXX Fri 03/24/2006
7623 * This is a workaround. The InstantiatedMethodDescs are in chunks, but there's
7624 * no obvious place to display the chunk, so display the bounds here.
7626 if( mc == mcInstantiated && md->m_chunkIndex == 0 )
7628 PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
7629 DisplayWriteElementAddress( "MethodDescChunk", DPtrToPreferredAddr(chunk),
7630 chunk->SizeOf(), METHODDESCS );
7633 DisplayWriteFieldEnumerated( m_bFlags2, md->m_bFlags2, MethodDesc,
7634 s_MDFlag2, W(", "), METHODDESCS );
7636 DisplayWriteFieldInt( m_wSlotNumber, md->GetSlot(), MethodDesc,
7638 DisplayWriteFieldEnumerated( m_wFlags, md->m_wFlags, MethodDesc,
7639 s_MDC, W(", "), METHODDESCS );
7645 PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
7646 //chunk is implicitly remapped because it's calculated from the pointer
7648 PTR_MethodTable mt = chunk->GetMethodTable();
7649 if( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
7651 if ( md->IsTypicalMethodDefinition() )
7654 m_import->GetMethodProps(md->GetMemberDef(), NULL, NULL, NULL, 0,
7655 NULL, NULL, NULL, &dwRVA, NULL);
7659 _ASSERTE(m_ILHostCopy);
7660 _ASSERTE(m_ILSectionStart);
7661 _ASSERTE(dwRVA >= m_ILSectionStart);
7662 _ASSERTE(dwRVA < (m_ILSectionStart + m_ILSectionSize));
7663 //The RVA is from the start of the file, so convert it
7664 //to an RVA to the start of the .text section.
7665 TADDR pILTarget = (TADDR)m_decoder.GetRvaData(dwRVA);
7666 COR_ILMETHOD * pILHeader = (COR_ILMETHOD*)(m_ILHostCopy + dwRVA - m_ILSectionStart);
7668 COR_ILMETHOD_DECODER decoder(pILHeader);
7670 DisplayStartStructure( "IL",
7671 DataPtrToDisplay(pILTarget),
7672 PEDecoder::ComputeILMethodSize(pILTarget),
7675 DisplayWriteElementInt( "CodeSize", decoder.GetCodeSize(), ALWAYS );
7677 // Dump the disassembled IL code?
7679 DisplayEndStructure( ALWAYS );
7685 if( md->HasPrecode() )
7687 PTR_Precode precode( md->GetPrecode() );
7689 DumpPrecode( precode, module );
7691 if ( md->HasNonVtableSlot() )
7693 DisplayWriteElementInt( "Slot", (DWORD)(md->GetAddrOfSlot() - PTR_TO_TADDR(md)), ALWAYS);
7695 if (md->HasNativeCodeSlot())
7697 DisplayWriteElementInt( "NativeCode", DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)), ALWAYS);
7698 //m_display->WriteFieldPointer( "NativeCode",
7699 // DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)),
7701 // md->GetNativeCode() );
7703 if (md->HasMethodImplSlot())
7705 DisplayStartVStructure( "MethodImpl", METHODDESCS );
7706 PTR_MethodImpl impl(md->GetMethodImpl());
7707 PTR_DWORD slots = impl->GetSlots() - 1; // GetSlots returns the address of the first real slot (past the size)
7708 unsigned numSlots = impl->GetSize();
7709 _ASSERTE(!numSlots || numSlots == slots[0]);
7710 _ASSERTE(slots == NULL || isInRange(PTR_TO_TADDR(slots)));
7711 if ((slots != NULL) && isInRange(PTR_TO_TADDR(slots)))
7713 DisplayWriteFieldAddress(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7714 (numSlots + 1) * sizeof(*slots),
7715 MethodImpl, METHODDESCS);
7719 DisplayWriteFieldPointer(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7720 MethodImpl, METHODDESCS);
7723 _ASSERTE(impl->pImplementedMD.IsNull()
7724 || isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())));
7725 if (!impl->pImplementedMD.IsNull() &&
7726 isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())))
7728 DisplayWriteFieldAddress( pImplementedMD,
7729 DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDsNonNull())),
7730 numSlots * sizeof(RelativePointer <MethodDesc*>),
7731 MethodImpl, METHODDESCS );
7735 DisplayWriteFieldPointer( pImplementedMD,
7736 DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDs())),
7737 MethodImpl, METHODDESCS );
7739 DisplayEndVStructure( METHODDESCS );
7741 if (md->HasStoredSig())
7743 DisplayStartVStructure( "StoredSigMethodDesc", METHODDESCS );
7744 PTR_StoredSigMethodDesc ssmd(md);
7745 //display signature information.
7746 if( isInRange(ssmd->GetSigRVA()) )
7748 DisplayWriteFieldAddress(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7749 ssmd->m_cSig, StoredSigMethodDesc,
7754 DisplayWriteFieldPointer(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7755 StoredSigMethodDesc, METHODDESCS);
7758 CoverageRead(TO_TADDR(ssmd->GetSigRVA()), ssmd->m_cSig);
7759 DisplayWriteFieldInt( m_cSig, ssmd->m_cSig,
7760 StoredSigMethodDesc, METHODDESCS );
7762 DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7763 ssmd->m_dwExtendedFlags,
7764 StoredSigMethodDesc,
7765 s_SSMDExtendedFlags, W(", "),
7768 DisplayEndVStructure( METHODDESCS ); //StoredSigMethodDesc
7770 if( mc == mcDynamic )
7772 PTR_DynamicMethodDesc dmd(md);
7773 DisplayStartVStructure( "DynamicMethodDesc", METHODDESCS );
7774 WriteFieldStr( m_pszMethodName, PTR_BYTE(dmd->GetMethodName()),
7775 DynamicMethodDesc, METHODDESCS );
7776 if( !CHECK_OPT(METHODDESCS) )
7777 CoverageReadString( PTR_TO_TADDR(dmd->GetMethodName()) );
7778 DisplayWriteFieldPointer( m_pResolver,
7779 DPtrToPreferredAddr(dmd->m_pResolver),
7780 DynamicMethodDesc, METHODDESCS );
7782 DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7783 dmd->m_dwExtendedFlags,
7785 s_SSMDExtendedFlags, W(", "),
7788 DisplayEndVStructure( METHODDESCS );
7792 PTR_FCallMethodDesc fcmd(md);
7793 DisplayStartVStructure( "FCallMethodDesc", METHODDESCS );
7795 DisplayWriteFieldInt( m_dwECallID,
7800 DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7802 if( mc == mcNDirect )
7804 PTR_NDirectMethodDesc ndmd(md);
7805 DisplayStartVStructure( "NDirectMethodDesc", METHODDESCS );
7806 DPTR(NDirectMethodDesc::temp1) nd( PTR_HOST_MEMBER_TADDR(NDirectMethodDesc, ndmd, ndirect) );
7807 DisplayStartStructureWithOffset( ndirect,
7808 DPtrToPreferredAddr(nd),
7809 sizeof(*nd), NDirectMethodDesc,
7811 DisplayWriteFieldPointer( m_pNativeNDirectTarget,
7812 DataPtrToDisplay((TADDR)nd->m_pNativeNDirectTarget),
7813 NDirectMethodDesc::temp1,
7815 DisplayWriteFieldEnumerated( m_wFlags, nd->m_wFlags,
7816 NDirectMethodDesc::temp1,
7817 g_NDirectFlags, W(", "),
7820 WriteFieldStr( m_pszEntrypointName,
7821 PTR_BYTE(dac_cast<TADDR>(ndmd->GetEntrypointName())),
7822 NDirectMethodDesc::temp1, METHODDESCS );
7823 if( !CHECK_OPT(METHODDESCS) )
7824 CoverageReadString(dac_cast<TADDR>(ndmd->GetEntrypointName()));
7827 DisplayWriteFieldInt( m_dwECallID,
7829 NDirectMethodDesc::temp1,
7834 WriteFieldStr( m_pszLibName,
7835 PTR_BYTE(dac_cast<TADDR>(ndmd->GetLibNameRaw())),
7836 NDirectMethodDesc::temp1, METHODDESCS );
7838 if( !CHECK_OPT(METHODDESCS) )
7839 CoverageReadString( dac_cast<TADDR>(ndmd->GetLibNameRaw()) );
7841 PTR_NDirectWriteableData wnd( ndmd->GetWriteableData() );
7842 DisplayStartStructureWithOffset( m_pWriteableData,
7843 DPtrToPreferredAddr(wnd),
7845 NDirectMethodDesc::temp1,
7847 DisplayWriteFieldPointer( m_pNDirectTarget,
7848 DataPtrToDisplay((TADDR)wnd->m_pNDirectTarget), NDirectWriteableData, METHODDESCS );
7849 if( !CHECK_OPT(METHODDESCS) )
7850 CoverageRead( PTR_TO_TADDR(wnd), sizeof(*wnd) );
7851 DisplayEndStructure( METHODDESCS ); //m_pWriteableData
7853 PTR_NDirectImportThunkGlue glue(ndmd->GetNDirectImportThunkGlue());
7855 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7858 // import thunk glue is not needed for P/Invoke that is not inlinable
7859 DisplayWriteFieldPointer( m_pImportThunkGlue,
7861 NDirectMethodDesc::temp1,
7866 DisplayStartStructureWithOffset( m_pImportThunkGlue,
7867 DPtrToPreferredAddr(glue),
7869 NDirectMethodDesc::temp1,
7872 DisplayStartStructureWithOffset( m_ImportThunkGlue,
7873 DPtrToPreferredAddr(glue),
7875 NDirectMethodDesc::temp1,
7878 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7879 /* REVISIT_TODO Thu 01/05/2006
7880 * Dump this properly as a precode
7882 WriteFieldMethodDesc( m_pMethodDesc, glue->m_pMethodDesc,
7883 NDirectImportThunkGlue, METHODDESCS );
7885 PTR_Precode p(glue);
7886 DumpPrecode( p, module );
7888 if( !CHECK_OPT(METHODDESCS) )
7889 CoverageRead(PTR_TO_TADDR(glue), sizeof(*glue));
7890 /* REVISIT_TODO Fri 12/16/2005
7891 * Factor out this code into some shared precode dumping code
7893 #else //!HAS_NDIRECT_IMPORT_PRECODE
7894 /* REVISIT_TODO Fri 10/27/2006
7895 * For Whidbey AMD64 (!HAS_NDIRECT_IMPORT_PRECODE), I don't have this data structure in the output.
7897 #endif //HAS_NDIRECT_IMPORT_PRECODE
7899 DisplayEndStructure( METHODDESCS ); //m_pImportThunkGlue
7900 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7905 DisplayWriteFieldInt( m_cbStackArgumentSize,
7906 nd->m_cbStackArgumentSize,
7907 NDirectMethodDesc::temp1, METHODDESCS );
7910 WriteFieldMethodDesc( m_pStubMD,
7911 nd->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc::temp1, nd, m_pStubMD)),
7912 NDirectMethodDesc::temp1, METHODDESCS );
7914 DisplayEndStructure( METHODDESCS ); //ndirect
7917 DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7919 if( mc == mcEEImpl )
7921 DisplayStartVStructure( "EEImplMethodDesc", METHODDESCS );
7922 DisplayEndVStructure( METHODDESCS );
7924 #if defined(FEATURE_COMINTEROP)
7925 if( mc == mcComInterop )
7927 PTR_ComPlusCallMethodDesc cpmd(md);
7928 DisplayStartVStructure( "ComPlusCallMethodDesc", METHODDESCS );
7929 PTR_ComPlusCallInfo compluscall((TADDR)cpmd->m_pComPlusCallInfo);
7931 if (compluscall == NULL)
7933 DisplayWriteFieldPointer( m_pComPlusCallInfo,
7935 ComPlusCallMethodDesc,
7940 DumpComPlusCallInfo( compluscall, METHODDESCS );
7943 DisplayEndVStructure( METHODDESCS ); //ComPlusCallMethodDesc
7946 if( mc == mcInstantiated )
7948 PTR_InstantiatedMethodDesc imd(md);
7949 DisplayStartVStructure( "InstantiatedMethodDesc", METHODDESCS );
7950 unsigned kind = imd->m_wFlags2
7951 & InstantiatedMethodDesc::KindMask;
7952 if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
7954 PTR_DictionaryLayout layout(dac_cast<TADDR>(imd->GetDictLayoutRaw()));
7957 WriteFieldDictionaryLayout( "m_pDictLayout",
7958 offsetof(InstantiatedMethodDesc, m_pDictLayout ),
7959 fieldsize(InstantiatedMethodDesc, m_pDictLayout),
7961 GetDependencyFromMD(md)->pImport );
7965 while( layout != NULL )
7967 CoverageRead( PTR_TO_TADDR(layout),
7968 sizeof(DictionaryLayout)
7969 + sizeof(DictionaryEntryLayout)
7970 * (layout->m_numSlots - 1) );
7971 layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
7976 InstantiatedMethodDesc::WrapperStubWithInstantiations )
7978 PTR_MethodDesc wimd(imd->IMD_GetWrappedMethodDesc());
7979 if( wimd == NULL || !DoWriteFieldAsFixup( "m_pWrappedMethodDesc",
7980 offsetof(InstantiatedMethodDesc, m_pWrappedMethodDesc),
7981 fieldsize(InstantiatedMethodDesc, m_pWrappedMethodDesc),
7982 PTR_TO_TADDR(wimd) ) )
7984 WriteFieldMethodDesc( m_pWrappedMethodDesc, wimd,
7985 InstantiatedMethodDesc, METHODDESCS );
7990 _ASSERTE(imd->m_pDictLayout.IsNull());
7991 DisplayWriteFieldPointer( m_pDictLayout, NULL,
7992 InstantiatedMethodDesc,
7995 //now handle the contents of the m_pMethInst/m_pPerInstInfo union.
7996 unsigned numSlots = imd->m_wNumGenericArgs;
7997 PTR_Dictionary inst(imd->IMD_GetMethodDictionary());
7999 if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
8001 dictSize = sizeof(TypeHandle);
8003 else if( kind == InstantiatedMethodDesc::WrapperStubWithInstantiations )
8005 PTR_InstantiatedMethodDesc wrapped =
8006 PTR_InstantiatedMethodDesc(imd->IMD_GetWrappedMethodDesc());
8007 if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(wrapped)) )
8009 /* XXX Mon 03/27/2006
8010 * Note that 4 is the correct answer for all IMDs at this time.
8013 MethodDescToString( md, buf );
8014 //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 );
8015 dictSize = (imd->GetNumGenericMethodArgs() + 4) * sizeof(void*);
8019 PTR_DictionaryLayout layout(wrapped->IsSharedByGenericMethodInstantiations()
8020 ? dac_cast<TADDR>(wrapped->GetDictLayoutRaw()) : NULL );
8021 dictSize = DictionaryLayout::GetFirstDictionaryBucketSize(imd->GetNumGenericMethodArgs(),
8027 dictSize = sizeof(TypeHandle);
8029 //instantiations has the number of slots of
8030 //GetNumGenericMethodArgs.
8033 m_display->WriteFieldPointer( "m_pPerInstInfo",
8034 offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8035 fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8043 m_display->StartStructureWithOffset( "m_pPerInstInfo",
8044 offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8045 fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8046 DPtrToPreferredAddr(inst),
8049 DisplayStartArray( "InstantiationInfo", W("[%-2s]: %s"),
8051 /* REVISIT_TODO Thu 03/23/2006
8052 * This doesn't dump the contents of the dictionary which are
8053 * hanging around after the real slots. Get around to doing that.
8055 for( unsigned i = 0; i < numSlots
8056 && CHECK_OPT(METHODDESCS); ++i )
8058 DisplayStartElement( "Handle", METHODDESCS );
8059 DisplayWriteElementInt( "Index", i, METHODDESCS );
8061 TypeHandle thArg = inst->GetInstantiation()[i].GetValue();
8063 WriteElementTypeHandle( "TypeHandle", thArg);
8065 /* XXX Fri 03/24/2006
8066 * There is no really good home for TypeDescs, so I gotta check
8067 * lots of places for them.
8069 if( !CORCOMPILE_IS_POINTER_TAGGED(thArg.AsTAddr()) &&
8070 thArg.IsTypeDesc() )
8072 PTR_TypeDesc td(thArg.AsTypeDesc());
8073 if( isInRange(PTR_TO_TADDR(td)) )
8075 m_discoveredTypeDescs.AppendEx(td);
8078 DisplayEndElement( METHODDESCS ); //Handle
8080 //Instantiation Info
8081 DisplayEndArray( "Total TypeHandles", METHODDESCS );
8083 DisplayEndVStructure(METHODDESCS); //m_pPerInstInfo;
8084 if( !CHECK_OPT(METHODDESCS) )
8085 CoverageRead(PTR_TO_TADDR(inst), numSlots * sizeof(*inst));
8088 DisplayWriteFieldEnumerated( m_wFlags2, imd->m_wFlags2,
8089 InstantiatedMethodDesc, s_IMDFlags,
8090 W(", "), METHODDESCS );
8091 DisplayWriteFieldInt( m_wNumGenericArgs, imd->m_wNumGenericArgs,
8092 InstantiatedMethodDesc, METHODDESCS );
8094 #ifdef FEATURE_COMINTEROP
8095 if (imd->IMD_HasComPlusCallInfo())
8097 PTR_ComPlusCallInfo compluscall = imd->IMD_GetComPlusCallInfo();
8098 DumpComPlusCallInfo( compluscall, METHODDESCS );
8100 #endif // FEATURE_COMINTEROP
8102 DisplayEndStructure( METHODDESCS );
8105 DisplayEndStructure( METHODDESCS ); //MethodDesc (mdTypeName)
8106 if( !CHECK_OPT(METHODDESCS) )
8107 CoverageRead( PTR_TO_TADDR(md), mdSize );
8111 #pragma warning(pop)
8114 NativeImageDumper::EnumMnemonics NativeImageDumper::s_EECLIFlags[] =
8116 #define EECLI_FLAGS_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClassLayoutInfo:: x, W(#x) )
8117 EECLI_FLAGS_ENTRY(e_BLITTABLE),
8118 EECLI_FLAGS_ENTRY(e_MANAGED_SEQUENTIAL),
8119 EECLI_FLAGS_ENTRY(e_ZERO_SIZED),
8120 EECLI_FLAGS_ENTRY(e_HAS_EXPLICIT_SIZE),
8121 #undef EECLI_FLAGS_ENTRY
8126 #pragma warning(push)
8127 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
8130 NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
8132 PTR_EEClass clazz = mt->GetClass();
8134 _ASSERTE(CHECK_OPT(EECLASSES));
8135 _ASSERTE(clazz != NULL);
8136 _ASSERTE(isInRange(PTR_TO_TADDR(clazz)));
8138 const char * eeClassType;
8140 if( clazz->HasLayout() )
8141 eeClassType = "LayoutEEClass";
8142 else if( mt->IsArray() )
8143 eeClassType = "ArrayClass";
8144 else if( clazz->IsDelegate() )
8145 eeClassType = "DelegateEEClass";
8147 eeClassType = "EEClass";
8149 DisplayStartStructure( eeClassType, DPtrToPreferredAddr(clazz), clazz->GetSize(),
8153 MethodTableToString( mt, buf );
8154 DisplayWriteElementStringW( "Name", (const WCHAR *)buf, EECLASSES );
8157 PTR_GuidInfo guidInfo = clazz->GetGuidInfo();
8158 if(guidInfo != NULL)
8160 DisplayStartStructureWithOffset( m_pGuidInfo,
8161 DPtrToPreferredAddr(guidInfo),
8162 sizeof(*guidInfo), EEClass,
8165 GuidToString( guidInfo->m_Guid, buf );
8166 DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
8168 DisplayWriteFieldFlag( m_bGeneratedFromName,
8169 guidInfo->m_bGeneratedFromName,
8170 GuidInfo, EECLASSES );
8171 DisplayEndStructure( EECLASSES ); //guidinfo
8175 /* XXX Fri 10/14/2005
8176 * if Clazz isn't an interface, m_pGuidInfo is undefined.
8178 DisplayWriteFieldPointerAnnotated( m_pGuidInfo, PTR_TO_TADDR(guidInfo),
8179 W("Invalid"), EEClass, EECLASSES );
8184 WriteFieldStr( m_szDebugClassName,
8185 PTR_BYTE(TO_TADDR(clazz->m_szDebugClassName)),
8186 EEClass, EECLASSES );
8187 DisplayWriteFieldFlag( m_fDebuggingClass, clazz->m_fDebuggingClass,
8188 EEClass, EECLASSES );
8191 WriteFieldMethodTable( m_pMethodTable, clazz->GetMethodTable(), EEClass,
8194 WriteFieldCorElementType( m_NormType, (CorElementType)clazz->m_NormType,
8195 EEClass, EECLASSES );
8197 PTR_FieldDesc fdList = clazz->GetFieldDescList();
8199 ULONG fieldCount = (ULONG)CountFields(mt);
8200 _ASSERTE((fdList == NULL) == (fieldCount == 0));
8204 m_display->StartStructureWithOffset( "m_pFieldDescList",
8205 offsetof(EEClass, m_pFieldDescList),
8206 fieldsize(EEClass, m_pFieldDescList),
8207 DPtrToPreferredAddr(fdList),
8209 sizeof(*fdList) * fieldCount :
8212 IF_OPT(VERBOSE_TYPES)
8214 if( fdList != NULL )
8216 DisplayStartArray( "FieldDescs", NULL, EECLASSES );
8217 for( SIZE_T i = 0; i < fieldCount; ++i )
8219 PTR_FieldDesc fd = fdList + i;
8221 DumpFieldDesc( fd, "FieldDesc" );
8223 DisplayEndArray( "Total FieldDescs", EECLASSES ); //FieldDescs
8226 else if( (fdList != NULL) && CHECK_OPT(DEBUG_COVERAGE) )
8228 for( SIZE_T i = 0; i < fieldCount; ++i )
8230 PTR_FieldDesc fd = fdList + i;
8232 if( fd != NULL && fd->m_debugName != NULL )
8233 CoverageReadString( fd->m_debugName );
8236 CoverageRead( PTR_TO_TADDR(fdList), sizeof(*fdList) * fieldCount );
8239 DisplayEndStructure( EECLASSES ); //FieldDescList
8241 DisplayWriteFieldEnumerated( m_dwAttrClass, clazz->GetAttrClass(),
8242 EEClass, s_CorTypeAttr, W(" "), EECLASSES );
8243 DisplayWriteFieldEnumerated( m_VMFlags, clazz->m_VMFlags, EEClass,
8244 s_VMFlags, W(", "), EECLASSES );
8246 PTR_MethodDescChunk chunk = clazz->GetChunks();
8248 DisplayStartArrayWithOffset( m_pChunks, NULL, EEClass, EECLASSES );
8249 while( chunk != NULL )
8251 DisplayStartStructure( "MethodDescChunk",
8252 DPtrToPreferredAddr(chunk),
8253 chunk->SizeOf(), EECLASSES );
8254 _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(chunk->GetMethodTable())));
8255 PTR_MethodTable chunkMT = chunk->GetMethodTable();
8256 DisplayWriteFieldPointer( m_methodTable,
8257 DPtrToPreferredAddr(chunkMT),
8258 MethodDescChunk, EECLASSES );
8259 PTR_MethodDescChunk chunkNext = chunk->GetNextChunk();
8260 DisplayWriteFieldPointer( m_next,
8261 DPtrToPreferredAddr(chunkNext),
8262 MethodDescChunk, EECLASSES );
8263 DisplayWriteFieldInt( m_size, chunk->m_size, MethodDescChunk,
8265 DisplayWriteFieldInt( m_count, chunk->m_count, MethodDescChunk,
8267 DisplayWriteFieldInt( m_flagsAndTokenRange, chunk->m_flagsAndTokenRange, MethodDescChunk,
8269 /* XXX Wed 12/14/2005
8270 * Don't skip walking this array. I need to make sure I touch the
8273 DisplayStartArray( "MethodDescs", NULL, METHODDESCS );
8274 PTR_MethodDesc md(chunk->GetFirstMethodDesc());
8277 IF_OPT_OR(METHODDESCS, DEBUG_COVERAGE)
8279 PTR_Module module = mt->GetModule();
8280 if(CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module) ))
8281 DumpMethodDesc( md, PTR_Module((TADDR)0) );
8283 DumpMethodDesc( md, module );
8286 // Check whether the next MethodDesc is within the bounds of the current chunks
8287 TADDR pNext = PTR_HOST_TO_TADDR(md) + md->SizeOf();
8288 TADDR pEnd = PTR_HOST_TO_TADDR(chunk) + chunk->SizeOf();
8290 md = (pNext < pEnd) ? PTR_MethodDesc(pNext) : NULL;
8293 DisplayEndArray( "Total MethodDescs", METHODDESCS); //MethodDescs
8295 chunk = chunk->GetNextChunk();
8297 DisplayEndStructure( EECLASSES ); //MethodDescChunk
8300 DisplayEndArray( "Total MethodDescChunks", EECLASSES );
8301 /* REVISIT_TODO Fri 10/14/2005
8302 * Dump the class dependencies
8304 //_ASSERTE(!clazz->m_classDependencies.TestAnyBit());
8306 /* REVISIT_TODO Mon 10/24/2005
8307 * Create vstructure for union?
8310 #ifdef FEATURE_COMINTEROP
8311 if( clazz->IsBlittable() || clazz->HasLayout() )
8313 DisplayWriteFieldInt(m_cbNativeSize, clazz->m_cbNativeSize, EEClass,
8316 else if( clazz->IsInterface() )
8318 DisplayWriteFieldPointer( m_ohDelegate,
8319 DataPtrToDisplay(clazz->m_ohDelegate),
8320 EEClass, EECLASSES );
8324 static const WCHAR * ifnames[] ={W("Dual"),W("Vtable"),W("Dispatch")};
8325 m_display->WriteFieldEnumerated( "ComInterfaceType",
8327 m_ComInterfaceType),
8329 m_ComInterfaceType),
8330 (int)clazz->m_ComInterfaceType,
8331 ifnames[(int)clazz->m_ComInterfaceType] );
8334 DisplayWriteFieldInt( m_cbNativeSize, clazz->m_cbNativeSize,
8335 EEClass, EECLASSES );
8338 #if defined(FEATURE_COMINTEROP)
8339 PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(clazz->m_pccwTemplate));
8340 if( ccwTemplate != NULL )
8342 DisplayWriteFieldPointer( m_pccwTemplate, NULL, EEClass,
8347 /* REVISIT_TODO Fri 10/14/2005
8350 DisplayWriteFieldPointer( m_pccwTemplate,
8351 DPtrToPreferredAddr(ccwTemplate), EEClass,
8354 #endif // defined(FEATURE_COMINTEROP)
8356 //fields for classes that aren't just EEClasses.
8357 if( clazz->HasLayout() )
8359 PTR_LayoutEEClass layoutClass(PTR_TO_TADDR(clazz));
8360 DisplayStartVStructure("LayoutEEClass", EECLASSES );
8362 PTR_EEClassLayoutInfo eecli( PTR_HOST_MEMBER_TADDR( LayoutEEClass,
8365 DisplayStartStructureWithOffset( m_LayoutInfo,
8366 DPtrToPreferredAddr(eecli),
8367 sizeof(EEClassLayoutInfo),
8368 LayoutEEClass, EECLASSES );
8369 /* REVISIT_TODO Fri 10/14/2005
8370 * Dump EEClassLayoutInfo
8372 DisplayWriteFieldInt( m_cbNativeSize, eecli->m_cbNativeSize,
8373 EEClassLayoutInfo, VERBOSE_TYPES );
8374 DisplayWriteFieldInt( m_cbManagedSize, eecli->m_cbManagedSize,
8375 EEClassLayoutInfo, VERBOSE_TYPES );
8376 DisplayWriteFieldInt( m_LargestAlignmentRequirementOfAllMembers,
8377 eecli->m_LargestAlignmentRequirementOfAllMembers,
8378 EEClassLayoutInfo, VERBOSE_TYPES );
8379 DisplayWriteFieldInt( m_ManagedLargestAlignmentRequirementOfAllMembers,
8380 eecli->m_ManagedLargestAlignmentRequirementOfAllMembers,
8381 EEClassLayoutInfo, VERBOSE_TYPES );
8382 DisplayWriteFieldEnumerated( m_bFlags, eecli->m_bFlags,
8383 EEClassLayoutInfo, s_EECLIFlags, W(", "),
8385 DisplayWriteFieldInt( m_numCTMFields, eecli->m_numCTMFields,
8386 EEClassLayoutInfo, VERBOSE_TYPES );
8387 PTR_FieldMarshaler fmArray = eecli->GetFieldMarshalers();
8388 DisplayWriteFieldAddress( m_pFieldMarshalers,
8389 DPtrToPreferredAddr(fmArray),
8390 eecli->m_numCTMFields
8391 * MAXFIELDMARSHALERSIZE,
8392 EEClassLayoutInfo, VERBOSE_TYPES );
8393 /* REVISIT_TODO Wed 03/22/2006
8394 * Dump the various types of FieldMarshalers.
8397 DisplayStartArrayWithOffset( m_pFieldMarshalers, NULL,
8398 EEClassLayoutInfo, VERBOSE_TYPES );
8399 for( unsigned i = 0; i < eecli->m_numCTMFields; ++i )
8401 /* REVISIT_TODO Wed 03/22/2006
8402 * Try to display the type of the field marshaler in the future.
8404 PTR_FieldMarshaler current = fmArray + i;
8405 DisplayStartStructure( "FieldMarshaler",
8406 DPtrToPreferredAddr(current),
8407 sizeof(*current), VERBOSE_TYPES );
8408 WriteFieldFieldDesc( m_pFD, PTR_FieldDesc(TO_TADDR(current->m_pFD)),
8409 FieldMarshaler, VERBOSE_TYPES );
8410 DisplayWriteFieldInt( m_dwExternalOffset,
8411 current->m_dwExternalOffset, FieldMarshaler,
8413 DisplayEndStructure( VERBOSE_TYPES ); //FieldMarshaler
8416 DisplayEndArray( "Number of FieldMarshalers", VERBOSE_TYPES ); //m_pFieldMarshalers
8419 DisplayEndStructure( EECLASSES ); //LayoutInfo
8421 DisplayEndVStructure( EECLASSES ); //LayoutEEClass
8423 else if( mt->IsArray() )
8425 PTR_ArrayClass arrayClass(PTR_TO_TADDR(clazz));
8426 DisplayStartVStructure( "ArrayClass", EECLASSES);
8429 m_display->WriteFieldInt( "m_rank", offsetof(ArrayClass, m_rank),
8430 fieldsize(ArrayClass, m_rank),
8431 arrayClass->GetRank() );
8433 DoWriteFieldCorElementType( "m_ElementType",
8434 offsetof(ArrayClass, m_ElementType),
8435 fieldsize(ArrayClass, m_ElementType),
8436 arrayClass->GetArrayElementType() );
8438 DisplayEndVStructure( EECLASSES ); //ArrayClass
8440 else if( clazz->IsDelegate() )
8442 PTR_DelegateEEClass delegateClass(PTR_TO_TADDR(clazz));
8443 DisplayStartVStructure( "DelegateEEClass", EECLASSES );
8445 DumpFieldStub( m_pStaticCallStub, delegateClass->m_pStaticCallStub,
8446 DelegateEEClass, EECLASSES );
8447 DumpFieldStub( m_pInstRetBuffCallStub,
8448 delegateClass->m_pInstRetBuffCallStub,
8449 DelegateEEClass, EECLASSES );
8451 WriteFieldMethodDesc( m_pInvokeMethod,
8452 delegateClass->GetInvokeMethod(),
8453 DelegateEEClass, EECLASSES );
8454 DumpFieldStub( m_pMultiCastInvokeStub,
8455 delegateClass->m_pMultiCastInvokeStub,
8456 DelegateEEClass, EECLASSES );
8458 DPTR(UMThunkMarshInfo)
8459 umInfo(TO_TADDR(delegateClass->m_pUMThunkMarshInfo));
8461 if( umInfo == NULL )
8463 DisplayWriteFieldPointer( m_pUMThunkMarshInfo, NULL,
8464 DelegateEEClass, EECLASSES );
8468 DisplayStartStructureWithOffset( m_pUMThunkMarshInfo,
8469 DPtrToPreferredAddr(umInfo),
8471 DelegateEEClass, EECLASSES );
8472 /* REVISIT_TODO Fri 10/14/2005
8473 * DumpUMThunkMarshInfo
8475 DisplayEndStructure( EECLASSES ); //UMThunkMarshInfo
8478 WriteFieldMethodDesc( m_pBeginInvokeMethod,
8479 delegateClass->GetBeginInvokeMethod(),
8480 DelegateEEClass, EECLASSES );
8481 WriteFieldMethodDesc( m_pEndInvokeMethod,
8482 delegateClass->GetEndInvokeMethod(),
8483 DelegateEEClass, EECLASSES );
8484 DisplayWriteFieldPointer( m_pMarshalStub, delegateClass->m_pMarshalStub,
8485 DelegateEEClass, EECLASSES );
8487 WriteFieldMethodDesc( m_pForwardStubMD,
8488 PTR_MethodDesc(TO_TADDR(delegateClass->m_pForwardStubMD)),
8489 DelegateEEClass, EECLASSES );
8490 WriteFieldMethodDesc( m_pReverseStubMD,
8491 PTR_MethodDesc(TO_TADDR(delegateClass->m_pReverseStubMD)),
8492 DelegateEEClass, EECLASSES );
8494 #ifdef FEATURE_COMINTEROP
8495 DPTR(ComPlusCallInfo) compluscall((TADDR)delegateClass->m_pComPlusCallInfo);
8496 if (compluscall == NULL)
8498 DisplayWriteFieldPointer( m_pComPlusCallInfo,
8505 DumpComPlusCallInfo( compluscall, EECLASSES );
8507 #endif // FEATURE_COMINTEROP
8509 DisplayEndVStructure( EECLASSES ); //DelegateEEClass
8512 DisplayEndStructure( EECLASSES ); //eeClassType
8514 PTR_EEClassOptionalFields pClassOptional = clazz->GetOptionalFields();
8517 DisplayStartStructure( "EEClassOptionalFields", DPtrToPreferredAddr(pClassOptional), sizeof(EEClassOptionalFields),
8520 #ifdef FEATURE_COMINTEROP
8521 PTR_SparseVTableMap sparseVTMap(TO_TADDR(pClassOptional->m_pSparseVTableMap));
8522 if( sparseVTMap == NULL )
8524 DisplayWriteFieldPointer( m_pSparseVTableMap, NULL, EEClassOptionalFields,
8529 _ASSERTE( !"Untested code" );
8532 m_display->StartStructure( "m_SparseVTableMap",
8533 DPtrToPreferredAddr(sparseVTMap),
8534 sizeof(*sparseVTMap) );
8536 _ASSERTE(sparseVTMap->m_MapList != NULL);
8537 PTR_SparseVTableMap_Entry mapList(TO_TADDR(sparseVTMap->m_MapList));
8538 DisplayStartArray( "m_MapList", NULL, EECLASSES );
8539 for( WORD i = 0; i < sparseVTMap->m_MapEntries; ++i )
8541 DisplayWriteFieldInt( m_Start, mapList[i].m_Start,
8542 SparseVTableMap::Entry, EECLASSES );
8543 DisplayWriteFieldInt( m_Span, mapList[i].m_Span,
8544 SparseVTableMap::Entry, EECLASSES );
8545 DisplayWriteFieldInt( m_Span, mapList[i].m_MapTo,
8546 SparseVTableMap::Entry, EECLASSES );
8549 DisplayEndArray( "Total Entries", EECLASSES ); //m_MapList
8551 DisplayWriteFieldInt( m_MapEntries, sparseVTMap->m_MapEntries,
8552 SparseVTableMap, EECLASSES );
8553 DisplayWriteFieldInt( m_Allocated, sparseVTMap->m_Allocated,
8554 SparseVTableMap, EECLASSES );
8555 DisplayWriteFieldInt( m_LastUsed, sparseVTMap->m_LastUsed,
8556 SparseVTableMap, EECLASSES );
8557 DisplayWriteFieldInt( m_VTSlot, sparseVTMap->m_VTSlot,
8558 SparseVTableMap, EECLASSES );
8559 DisplayWriteFieldInt( m_MTSlot, sparseVTMap->m_MTSlot,
8560 SparseVTableMap, EECLASSES );
8562 DisplayEndStructure( EECLASSES ); //SparseVTableMap
8565 WriteFieldTypeHandle( m_pCoClassForIntf, pClassOptional->m_pCoClassForIntf,
8566 EEClassOptionalFields, EECLASSES );
8568 PTR_ClassFactoryBase classFactory(TO_TADDR(pClassOptional->m_pClassFactory));
8569 if( classFactory != NULL )
8571 DisplayWriteFieldPointer( m_pClassFactory, NULL, EEClassOptionalFields,
8576 /* REVISIT_TODO Fri 10/14/2005
8577 * Dump ComClassFactory
8579 DisplayWriteFieldPointer( m_pClassFactory,
8580 DPtrToPreferredAddr(classFactory),
8581 EEClassOptionalFields, EECLASSES );
8583 #endif // FEATURE_COMINTEROP
8585 PTR_DictionaryLayout layout = pClassOptional->m_pDictLayout;
8586 if( layout == NULL )
8588 DisplayWriteFieldPointer( m_pDictLayout, NULL, EEClassOptionalFields, EECLASSES );
8592 IF_OPT(VERBOSE_TYPES)
8594 WriteFieldDictionaryLayout( "m_pDictLayout",
8595 offsetof(EEClassOptionalFields, m_pDictLayout),
8596 fieldsize(EEClassOptionalFields, m_pDictLayout),
8597 layout, GetDependencyFromMT(mt)->pImport );
8601 while( layout != NULL )
8603 CoverageRead( PTR_TO_TADDR(layout),
8604 sizeof(DictionaryLayout)
8605 + sizeof(DictionaryEntryLayout)
8606 * (layout->m_numSlots - 1) );
8607 layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
8611 PTR_BYTE varianceInfo = pClassOptional->GetVarianceInfo();
8612 if( varianceInfo == NULL )
8614 DisplayWriteFieldPointer( m_pVarianceInfo, NULL,
8615 EEClassOptionalFields, EECLASSES );
8619 /* REVISIT_TODO Fri 10/14/2005
8620 * Dump variance info
8622 DisplayWriteFieldPointer( m_pVarianceInfo,
8623 DPtrToPreferredAddr(varianceInfo), EEClassOptionalFields,
8627 DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID,
8628 EEClassOptionalFields, EECLASSES );
8630 DisplayEndStructure( EECLASSES ); // EEClassOptionalFields
8632 } // NativeImageDumper::DumpEEClassForMethodTable
8634 #pragma warning(pop)
8640 TDT_IsParamTypeDesc,
8641 TDT_IsArrayTypeDesc,
8642 TDT_IsTypeVarTypeDesc,
8645 const char * const g_typeDescTypeNames[] =
8653 int g_typeDescSizes[] =
8656 sizeof(ParamTypeDesc),
8657 sizeof(ArrayTypeDesc),
8658 sizeof(TypeVarTypeDesc),
8659 -1//sizeof(FnPtrTypeDesc) -- variable size
8661 TypeDescType getTypeDescType( PTR_TypeDesc td )
8663 _ASSERTE(td != NULL);
8665 return TDT_IsArrayTypeDesc;
8666 if( td->HasTypeParam() )
8667 return TDT_IsParamTypeDesc;
8668 if( td->IsGenericVariable() )
8669 return TDT_IsTypeVarTypeDesc;
8670 if( td->GetInternalCorElementType() == ELEMENT_TYPE_FNPTR )
8671 return TDT_IsFnPtrTypeDesc;
8672 return TDT_IsTypeDesc;
8674 NativeImageDumper::EnumMnemonics NativeImageDumper::s_TDFlags[] =
8677 #define TDF_ENTRY(x) NativeImageDumper::EnumMnemonics(TypeDesc:: x, W(#x) )
8678 TDF_ENTRY(enum_flag_NeedsRestore),
8679 TDF_ENTRY(enum_flag_PreRestored),
8680 TDF_ENTRY(enum_flag_Unrestored),
8681 TDF_ENTRY(enum_flag_UnrestoredTypeKey),
8682 TDF_ENTRY(enum_flag_IsNotFullyLoaded),
8683 TDF_ENTRY(enum_flag_DependenciesLoaded),
8687 NativeImageDumper::EnumMnemonics s_CConv[] =
8689 #define CC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
8691 #define CC_CALLCONV_ENTRY(x) NativeImageDumper::EnumMnemonics( x, IMAGE_CEE_CS_CALLCONV_MASK, W(#x) )
8692 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_VARARG),
8693 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_FIELD),
8694 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG),
8695 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_PROPERTY),
8696 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_UNMGD),
8697 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERICINST),
8698 CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_NATIVEVARARG),
8699 #undef CC_CALLCONV_ENTRY
8701 CC_ENTRY(IMAGE_CEE_CS_CALLCONV_HASTHIS),
8702 CC_ENTRY(IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS),
8703 CC_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERIC)
8707 void NativeImageDumper::DumpTypeDesc( PTR_TypeDesc td )
8709 _ASSERTE(CHECK_OPT(TYPEDESCS));
8710 TypeDescType tdt = getTypeDescType(td);
8711 int size = g_typeDescSizes[(int)tdt];
8714 _ASSERTE(tdt == TDT_IsFnPtrTypeDesc);
8715 size = FnPtrTypeDesc::DacSize(PTR_TO_TADDR(td));
8717 DisplayStartStructure( g_typeDescTypeNames[(int)tdt],
8718 DPtrToPreferredAddr(td), size, TYPEDESCS );
8720 //first handle the fields of typedesc
8721 WriteFieldCorElementType( m_typeAndFlags, td->GetInternalCorElementType(),
8722 TypeDesc, TYPEDESCS );
8723 DisplayWriteFieldEnumerated( m_typeAndFlags, td->m_typeAndFlags, TypeDesc,
8724 s_TDFlags, W(", "), TYPEDESCS );
8725 if( tdt == TDT_IsParamTypeDesc || tdt == TDT_IsArrayTypeDesc )
8727 PTR_ParamTypeDesc ptd(td);
8728 DisplayStartVStructure( "ParamTypeDesc", TYPEDESCS );
8729 WriteFieldMethodTable( m_TemplateMT, ptd->GetTemplateMethodTableInternal(),
8730 ParamTypeDesc, TYPEDESCS );
8731 WriteFieldTypeHandle( m_Arg, ptd->m_Arg,
8732 ParamTypeDesc, TYPEDESCS );
8733 DisplayWriteFieldPointer( m_hExposedClassObject,
8734 DataPtrToDisplay(ptd->m_hExposedClassObject),
8735 ParamTypeDesc, TYPEDESCS );
8737 DisplayEndVStructure( TYPEDESCS ); //ParamTypeDesc
8739 else if( tdt == TDT_IsFnPtrTypeDesc )
8741 PTR_FnPtrTypeDesc ftd(td);
8742 DisplayStartVStructure( "FnPtrTypeDesc", TYPEDESCS );
8743 DisplayWriteFieldInt( m_NumArgs, ftd->m_NumArgs, FnPtrTypeDesc,
8745 DisplayWriteFieldEnumerated( m_CallConv, ftd->m_CallConv,
8746 FnPtrTypeDesc, s_CConv, W(", "),
8748 DisplayStartArrayWithOffset( m_RetAndArgTypes, W("[%-4s]: %s"),
8749 FnPtrTypeDesc, TYPEDESCS );
8750 PTR_TypeHandle args( PTR_HOST_MEMBER_TADDR(FnPtrTypeDesc, ftd,
8751 m_RetAndArgTypes) );
8752 for( unsigned i = 0; i < ftd->m_NumArgs; ++i )
8754 DisplayStartElement( "Argument", TYPEDESCS );
8755 DisplayWriteElementInt( "Index", i, TYPEDESCS );
8757 WriteElementTypeHandle( "TypeHandle", args[i] );
8758 DisplayEndElement( TYPEDESCS );
8760 DisplayEndArray( "Total Arguments", TYPEDESCS );
8761 DisplayEndVStructure( TYPEDESCS );
8763 else if( tdt == TDT_IsTypeVarTypeDesc )
8765 PTR_TypeVarTypeDesc tvtd(td);
8766 DisplayStartVStructure( "TypeVarTypeDesc", TYPEDESCS );
8767 DisplayWriteFieldPointer( m_pModule,
8768 DPtrToPreferredAddr(tvtd->GetModule()),
8769 TypeVarTypeDesc, TYPEDESCS );
8770 DisplayWriteFieldUInt( m_typeOrMethodDef,
8771 tvtd->m_typeOrMethodDef,
8772 TypeVarTypeDesc, TYPEDESCS );
8773 DisplayWriteFieldInt( m_numConstraints, tvtd->m_numConstraints,
8774 TypeVarTypeDesc, TYPEDESCS );
8775 if( tvtd->m_constraints == NULL )
8777 DisplayWriteFieldPointer( m_constraints, NULL, TypeVarTypeDesc,
8782 DisplayStartStructureWithOffset( m_constraints,
8783 DPtrToPreferredAddr(tvtd->m_constraints),
8784 sizeof(*tvtd->m_constraints) *
8785 tvtd->m_numConstraints,
8786 TypeVarTypeDesc, TYPEDESCS );
8787 DisplayStartArray( "Constraints", NULL, TYPEDESCS );
8788 for( unsigned i = 0; i < tvtd->m_numConstraints; ++i )
8790 WriteElementTypeHandle( "TypeHandle", tvtd->m_constraints[i] );
8792 DisplayEndArray( "Total Constraints", TYPEDESCS ); //Constraints
8793 DisplayEndStructure( TYPEDESCS ); //m_constraints
8795 DisplayWriteFieldPointer( m_hExposedClassObject,
8796 DataPtrToDisplay(tvtd->m_hExposedClassObject),
8797 TypeVarTypeDesc, TYPEDESCS );
8798 DisplayWriteFieldUInt( m_token, tvtd->m_token, TypeVarTypeDesc,
8800 DisplayWriteFieldInt( m_index, tvtd->m_index, TypeVarTypeDesc,
8803 DisplayEndVStructure( TYPEDESCS ); //TypeVarTypeDesc
8807 DisplayEndStructure( TYPEDESCS ); // g_typeDescTypeNames
8811 void NativeImageDumper::DumpDictionaryEntry( const char * elementName,
8812 DictionaryEntryKind kind,
8813 PTR_DictionaryEntry entry )
8815 m_display->StartElement( elementName );
8816 const char * name = NULL;
8820 m_display->WriteEmptyElement("EmptySlot");
8822 case TypeHandleSlot:
8824 TypeHandle th = dac_cast<DPTR(FixupPointer<TypeHandle>)>(entry)->GetValue();
8825 WriteElementTypeHandle( "TypeHandle", th );
8826 /* XXX Fri 03/24/2006
8827 * There is no straightforward home for these, so make sure to
8830 if( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc() )
8832 PTR_TypeDesc td(th.AsTypeDesc());
8833 if( isInRange(PTR_TO_TADDR(td)) )
8835 m_discoveredTypeDescs.AppendEx(td);
8840 case MethodDescSlot:
8843 PTR_MethodDesc md(TO_TADDR(*entry));
8844 WriteElementMethodDesc( "MethodDesc", md );
8847 case MethodEntrySlot:
8848 name = "MethodEntry";
8849 goto StandardEntryDisplay;
8850 case ConstrainedMethodEntrySlot:
8851 name = "ConstrainedMethodEntry";
8852 goto StandardEntryDisplay;
8853 case DispatchStubAddrSlot:
8854 name = "DispatchStubAddr";
8855 goto StandardEntryDisplay;
8856 /* REVISIT_TODO Tue 10/11/2005
8857 * Print out name information here
8860 name = "FieldDescSlot";
8861 StandardEntryDisplay:
8862 m_display->WriteElementPointer(name, DataPtrToDisplay((TADDR)*entry));
8865 _ASSERTE( !"unreachable" );
8867 m_display->EndElement(); //elementName
8870 #ifdef FEATURE_READYTORUN
8871 IMAGE_DATA_DIRECTORY * NativeImageDumper::FindReadyToRunSection(DWORD type)
8873 PTR_READYTORUN_SECTION pSections = dac_cast<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(m_pReadyToRunHeader) + sizeof(READYTORUN_HEADER));
8874 for (DWORD i = 0; i < m_pReadyToRunHeader->NumberOfSections; i++)
8876 // Verify that section types are sorted
8877 _ASSERTE(i == 0 || (pSections[i - 1].Type < pSections[i].Type));
8879 READYTORUN_SECTION * pSection = pSections + i;
8880 if (pSection->Type == type)
8881 return &pSection->Section;
8887 // Ready to Run specific dumping methods
8889 void NativeImageDumper::DumpReadyToRun()
8891 m_pReadyToRunHeader = m_decoder.GetReadyToRunHeader();
8893 m_nativeReader = NativeFormat::NativeReader(dac_cast<PTR_BYTE>(m_decoder.GetBase()), m_decoder.GetVirtualSize());
8895 IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindReadyToRunSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS);
8896 if (pRuntimeFunctionsDir != NULL)
8898 m_pRuntimeFunctions = dac_cast<PTR_RUNTIME_FUNCTION>(m_decoder.GetDirectoryData(pRuntimeFunctionsDir));
8899 m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION);
8903 m_nRuntimeFunctions = 0;
8906 IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindReadyToRunSection(READYTORUN_SECTION_METHODDEF_ENTRYPOINTS);
8907 if (pEntryPointsDir != NULL)
8908 m_methodDefEntryPoints = NativeFormat::NativeArray((TADDR)&m_nativeReader, pEntryPointsDir->VirtualAddress);
8910 DisplayStartCategory("NativeInfo", NATIVE_INFO);
8913 DumpReadyToRunHeader();
8915 DisplayEndCategory(NATIVE_INFO); //NativeInfo
8917 IF_OPT_OR3(METHODS, GC_INFO, DISASSEMBLE_CODE)
8918 DumpReadyToRunMethods();
8924 const NativeImageDumper::EnumMnemonics s_ReadyToRunFlags[] =
8926 #define RTR_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
8927 RTR_FLAGS(READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE),
8931 void NativeImageDumper::DumpReadyToRunHeader()
8935 m_display->StartStructure( "READYTORUN_HEADER",
8936 DPtrToPreferredAddr(dac_cast<PTR_READYTORUN_HEADER>(m_pReadyToRunHeader)),
8937 sizeof(*m_pReadyToRunHeader) );
8939 DisplayWriteFieldUInt( Signature, m_pReadyToRunHeader->Signature, READYTORUN_HEADER, ALWAYS );
8940 DisplayWriteFieldUInt( MajorVersion, m_pReadyToRunHeader->MajorVersion, READYTORUN_HEADER, ALWAYS );
8941 DisplayWriteFieldUInt( MinorVersion, m_pReadyToRunHeader->MinorVersion, READYTORUN_HEADER, ALWAYS );
8943 DisplayWriteFieldEnumerated( Flags, m_pReadyToRunHeader->Flags,
8944 READYTORUN_HEADER, s_ReadyToRunFlags, W(", "),
8947 m_display->EndStructure(); //READYTORUN_HEADER
8951 void NativeImageDumper::DumpReadyToRunMethods()
8953 DisplayStartArray("Methods", NULL, METHODS);
8955 for (uint rid = 1; rid <= m_methodDefEntryPoints.GetCount(); rid++)
8958 if (!m_methodDefEntryPoints.TryGetAt(rid - 1, &offset))
8962 offset = m_nativeReader.DecodeUnsigned(offset, &id);
8969 m_nativeReader.DecodeUnsigned(offset, &val);
8973 // TODO: Dump fixups from dac_cast<TADDR>(m_pLayout->GetBase()) + offset
8982 _ASSERTE(id < m_nRuntimeFunctions);
8983 PTR_RUNTIME_FUNCTION pRuntimeFunction = m_pRuntimeFunctions + id;
8984 PCODE pEntryPoint = dac_cast<TADDR>(m_decoder.GetBase()) + pRuntimeFunction->BeginAddress;
8987 AppendTokenName(TokenFromRid(rid, mdtMethodDef), buf, m_import);
8989 DumpReadyToRunMethod(pEntryPoint, pRuntimeFunction, buf);
8992 DisplayEndArray("Total Methods", METHODS); //Methods
8995 extern PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntimeFunction, /* out */ SIZE_T * pSize);
8997 void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNCTION pRuntimeFunction, SString& name)
8999 //Read the GCInfo to get the total method size.
9000 unsigned methodSize = 0;
9001 unsigned gcInfoSize = UINT_MAX;
9003 SIZE_T nUnwindDataSize;
9004 PTR_VOID pUnwindData = GetUnwindDataBlob(dac_cast<TADDR>(m_decoder.GetBase()), pRuntimeFunction, &nUnwindDataSize);
9006 // GCInfo immediatelly follows unwind data
9007 PTR_CBYTE gcInfo = dac_cast<PTR_CBYTE>(pUnwindData) + nUnwindDataSize;
9009 void(*stringOutFn)(const char *, ...);
9012 stringOutFn = stringOut;
9016 stringOutFn = nullStringOut;
9020 PTR_CBYTE curGCInfoPtr = gcInfo;
9021 g_holdStringOutData.Clear();
9022 GCDump gcDump(GCINFO_VERSION);
9023 gcDump.gcPrintf = stringOutFn;
9024 UINT32 r2rversion = m_pReadyToRunHeader->MajorVersion;
9025 UINT32 gcInfoVersion = GCInfoToken::ReadyToRunVersionToGcInfoVersion(r2rversion);
9026 GCInfoToken gcInfoToken = { curGCInfoPtr, gcInfoVersion };
9028 #if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
9029 GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
9030 methodSize = gcInfoDecoder.GetCodeLength();
9033 //dump the data to a string first so we can get the gcinfo size.
9036 stringOutFn("method info Block:\n");
9037 curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0);
9044 stringOutFn("PointerTable:\n");
9045 curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9048 gcInfoSize = curGCInfoPtr - gcInfo;
9049 #elif defined(USE_GC_INFO_DECODER)
9050 stringOutFn("PointerTable:\n");
9051 curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9053 gcInfoSize = (unsigned)(curGCInfoPtr - gcInfo);
9057 //data is output below.
9060 DisplayStartElement("Method", METHODS);
9061 DisplayWriteElementStringW("Name", (const WCHAR *)name, METHODS);
9063 DisplayStartStructure("GCInfo",
9064 DPtrToPreferredAddr(gcInfo),
9068 DisplayStartTextElement("Contents", GC_INFO);
9069 DisplayWriteXmlTextBlock(("%S", (const WCHAR *)g_holdStringOutData), GC_INFO);
9070 DisplayEndTextElement(GC_INFO); //Contents
9072 DisplayEndStructure(METHODS); //GCInfo
9074 DisplayStartStructure("Code", DataPtrToDisplay(pEntryPoint), methodSize,
9077 IF_OPT(DISASSEMBLE_CODE)
9079 // Disassemble hot code. Read the code into the host process.
9080 /* REVISIT_TODO Mon 10/24/2005
9081 * Is this align up right?
9083 BYTE * codeStartHost =
9084 reinterpret_cast<BYTE*>(PTR_READ(pEntryPoint,
9085 (ULONG32)ALIGN_UP(methodSize,
9087 DisassembleMethod(codeStartHost, methodSize);
9090 DisplayEndStructure(METHODS); //Code
9092 DisplayEndElement(METHODS); //Method
9094 #endif // FEATURE_READYTORUN
9097 void NativeImageDumper::RecordTypeRef( mdTypeRef token, PTR_MethodTable mt )
9100 m_mtToTypeRefMap.Add( mt, token );
9102 mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt )
9104 return m_mtToTypeRefMap.Find(mt);
9108 #else //!FEATURE_PREJIT
9109 //dummy implementation for dac
9110 HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase,
9112 IXCLRDataDisplay* display,
9113 IXCLRLibrarySupport* support,
9114 IXCLRDisassemblySupport* dis)
9118 #endif //FEATURE_PREJIT
9120 /* REVISIT_TODO Mon 10/10/2005
9121 * Here is where it gets bad. There is no DAC build of gcdump, so instead
9122 * build it directly into the the dac. That's what all these ugly defines
9126 #pragma warning(disable:4244) // conversion from 'unsigned int' to 'unsigned short', possible loss of data
9127 #pragma warning(disable:4189) // local variable is initialized but not referenced
9133 #define GC_NOTRIGGER
9134 #include <gcdecoder.cpp>
9138 #if defined _DEBUG && defined _TARGET_X86_
9140 // disable FPO for checked build
9141 #pragma optimize("y", off)
9146 #define _ASSERTE(a) do {} while (0)
9148 #include <gcdump.cpp>
9151 #undef LIMITED_METHOD_CONTRACT
9152 #undef WRAPPER_NO_CONTRACT
9154 #include <i386/gcdumpx86.cpp>
9155 #else // !_TARGET_X86_
9157 #include <gcdumpnonx86.cpp>
9158 #endif // !_TARGET_X86_
9161 #pragma warning(default:4244)
9162 #pragma warning(default:4189)