c7509691720803c8f84775021655797ca3234f6b
[platform/upstream/coreclr.git] / src / debug / daccess / nidump.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5
6 // 
7  /*vim: set foldmethod=marker: */
8 #include <stdafx.h>
9
10 #if defined(FEATURE_PREJIT)
11 #include "nidump.h"
12
13 #include <metadataexports.h>
14
15 #include <comcallablewrapper.h>
16 #include <gcdump.h>
17
18 #if !defined(FEATURE_CORESYSTEM)
19 #include <algorithm>
20 #endif
21
22
23 #include <formattype.h>
24
25 #include <pedecoder.h>
26
27
28 #include <mdfileformat.h>
29
30 #if !defined(FEATURE_CORESYSTEM)
31 #include <cassert>
32 #undef _ASSERTE
33 #define _ASSERTE(x) assert(x)
34 #endif
35
36 #include <compile.h>
37
38 #ifdef USE_GC_INFO_DECODER
39 #include <gcinfodecoder.h>
40 #endif
41
42 #include <ngenhash.inl>
43
44 #define FEATURE_MSDIS
45
46 //----------------------------------------------------------------------------
47 //
48 // ClrDump functionality
49 //
50 //----------------------------------------------------------------------------
51
52 /////////////////////////////////////////////////////////////////////////////////////////////
53 //
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.
57 //
58 // This function returns -1 if pass in with an incorrectly compressed data, such as
59 // (*pBytes & 0xE0) == 0XE0.
60 /////////////////////////////////////////////////////////////////////////////////////////////
61 /* XXX Wed 09/14/2005
62  * copied from cor.h.  Modified to operate on PTR_PCCOR_SIGNATUREs
63  */
64 inline ULONG DacSigUncompressBigData(
65     PTR_CCOR_SIGNATURE &pData)             // [IN,OUT] compressed data 
66 {
67     ULONG res;
68
69     // 1 byte data is handled in DacSigUncompressData   
70     //  _ASSERTE(*pData & 0x80);    
71
72     // Medium.  
73     if ((*pData & 0xC0) == 0x80)  // 10?? ????  
74     {   
75         res = (ULONG)((*pData++ & 0x3f) << 8);
76         res |= *pData++;
77     }   
78     else // 110? ???? 
79     {
80         res = (*pData++ & 0x1f) << 24;
81         res |= *pData++ << 16;
82         res |= *pData++ << 8;
83         res |= *pData++;
84     }
85     return res; 
86 }
87 FORCEINLINE ULONG DacSigUncompressData(
88     PTR_CCOR_SIGNATURE &pData)             // [IN,OUT] compressed data 
89 {
90     // Handle smallest data inline. 
91     if ((*pData & 0x80) == 0x00)        // 0??? ????    
92         return *pData++;    
93     return DacSigUncompressBigData(pData);  
94 }
95 //const static mdToken g_tkCorEncodeToken[4] ={mdtTypeDef, mdtTypeRef, mdtTypeSpec, mdtBaseType};
96
97 // uncompress a token
98 inline mdToken DacSigUncompressToken(   // return the token.    
99     PTR_CCOR_SIGNATURE &pData)             // [IN,OUT] compressed data 
100 {
101     mdToken     tk; 
102     mdToken     tkType; 
103
104     tk = DacSigUncompressData(pData);   
105     tkType = g_tkCorEncodeToken[tk & 0x3];  
106     tk = TokenFromRid(tk >> 2, tkType); 
107     return tk;  
108 }
109 // uncompress encoded element type
110 FORCEINLINE CorElementType DacSigUncompressElementType(//Element type
111     PTR_CCOR_SIGNATURE &pData)             // [IN,OUT] compressed data 
112 {
113     return (CorElementType)*pData++;    
114 }
115
116
117
118 const char * g_helperNames[] =
119 {
120 #define JITHELPER(val, fn, sig) # val,
121 #include <jithelpers.h>
122 #undef JITHELPER
123 };
124
125
126
127 #define dim(x) (sizeof(x)/sizeof((x)[0]))
128
129 void EnumFlagsToString( DWORD value,
130                         const NativeImageDumper::EnumMnemonics * table,
131                         int count, const WCHAR * sep, SString& output )
132 {
133     bool firstValue = true;
134     for( int i = 0; i < count; ++i )
135     {
136         bool match = false;
137         const NativeImageDumper::EnumMnemonics& entry = table[i];
138         if( entry.mask != 0 )
139             match = ((entry.mask & value) == entry.value);
140         else
141             match = (entry.value == value);
142
143         if( match )
144         {
145             if( !firstValue )
146                 output.Append(sep);
147             firstValue = false;
148
149             output.Append( table[i].mnemonic );
150
151             value &= ~entry.value;
152         }
153     }
154 }
155
156 const NativeImageDumper::EnumMnemonics s_ImageSections[] =
157 {
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")),
165 #undef IS_ENTRY
166 };
167 inline int CheckFlags( DWORD source, DWORD flags )
168 {
169     return (source & flags) == flags;
170 }
171
172 HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase,
173                                        LPCWSTR name,
174                                        IXCLRDataDisplay * display,
175                                        IXCLRLibrarySupport * support,
176                                        IXCLRDisassemblySupport *dis)
177 {
178     DAC_ENTER();
179     /* REVISIT_TODO Fri 09/09/2005
180      * catch exceptions
181      */
182     NativeImageDumper dump(dac_cast<PTR_VOID>(CLRDATA_ADDRESS_TO_TADDR(loadedBase)), name, display,
183                            support, dis);
184     dump.DumpNativeImage();
185     DAC_LEAVE();
186     return S_OK;
187 }
188
189
190
191 static ULONG bigBufferSize = 8192;
192 static WCHAR bigBuffer[8192];
193 static BYTE bigByteBuffer[1024];
194
195 //----------------------------------------------------------------------------
196 //
197 // NativeImageDumper
198 //
199 //----------------------------------------------------------------------------
200 template<typename T>
201 inline T combine(T a, T b)
202 {
203     return (T)(((DWORD)a) | ((DWORD)b));
204 }
205 template<typename T>
206 inline T combine(T a, T b, T c)
207 {
208     return (T)(((DWORD)a) | ((DWORD)b) | ((DWORD)c));
209 }
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) )
218
219 #define fieldsize(type, field) (sizeof(((type*)NULL)->field))
220
221
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)
231
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)
238
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)
245
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)
252
253 #define DisplayEndElement(filter) \
254     do { IF_OPT(filter) m_display->EndElement(); } while(0)
255
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)
260
261 #define DisplayWriteElementStringW(name, value, filter) \
262     do { IF_OPT(filter) m_display->WriteElementStringW(name, value); } while(0)
263
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)
278
279 #define DisplayWriteElementEnumerated(name, value, mnemonics, sep, filter) \
280     do { \
281     IF_OPT(filter) { \
282         TempBuffer buf; \
283         EnumFlagsToString(value, mnemonics, _countof(mnemonics), sep, buf);\
284         m_display->WriteElementEnumerated( name, value, (const WCHAR*)buf ); \
285     }\
286     }while(0)
287 #define DisplayWriteFieldEnumerated(field, value, type, mnemonics, sep, filter)\
288     do { \
289     IF_OPT(filter) { \
290         TempBuffer buf; \
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 ); \
295     }\
296     }while(0)
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)
303
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)
354
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)
359
360 void AppendNilToken( mdToken token, SString& buf )
361 {
362     _ASSERTE(RidFromToken(token) == mdTokenNil);
363
364     const WCHAR * id = NULL;
365     switch(token)
366     {
367 #define mdNilEnt(x) case x: \
368         id = W(#x); \
369         break
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);
387         mdNilEnt(mdFileNil);
388         mdNilEnt(mdExportedTypeNil);
389         mdNilEnt(mdManifestResourceNil);
390
391         mdNilEnt(mdGenericParamNil);
392         mdNilEnt(mdGenericParamConstraintNil);
393         mdNilEnt(mdMethodSpecNil);
394
395         mdNilEnt(mdStringNil);
396 #undef mdNilEnt
397     }
398     buf.Append( id );
399 }
400 void appendByteArray(SString& buf, const BYTE * bytes, ULONG cbBytes)
401 {
402     for( COUNT_T i = 0; i < cbBytes; ++i )
403     {
404         buf.AppendPrintf(W("%02x"), bytes[i]);
405     }
406 }
407 /*}}}*/
408
409
410
411
412 struct OptionDependencies
413 {
414     OptionDependencies(CLRNativeImageDumpOptions value,
415                        CLRNativeImageDumpOptions dep) : m_value(value),
416                                                         m_dep(dep)
417     {
418
419     }
420     CLRNativeImageDumpOptions m_value;
421     CLRNativeImageDumpOptions m_dep;
422 };
423
424 static OptionDependencies g_dependencies[] = 
425 {
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),
438
439     OPT_DEP(FIXUP_HISTOGRAM, FIXUP_TABLES),
440     OPT_DEP(FIXUP_THUNKS, FIXUP_TABLES),
441
442 #undef OPT_DEP
443 };
444
445 // Metadata helpers for DAC
446 // This is mostly copied from mscoree.cpp which isn't available in mscordacwks.dll.
447 // 
448
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.
454 {
455     _ASSERTE(rclsid == CLSID_CorMetaDataDispenser);
456     
457     return InternalCreateMetaDataDispenser(riid, ppv);
458 }
459
460
461 NativeImageDumper::NativeImageDumper(PTR_VOID loadedBase,
462                                      const WCHAR * const name,
463                                      IXCLRDataDisplay * display,
464                                      IXCLRLibrarySupport * support,
465                                      IXCLRDisassemblySupport *dis)
466     :
467     m_decoder(loadedBase),
468     m_name(name),
469     m_baseAddress(loadedBase),
470     m_display(display),
471     m_librarySupport(support),
472     m_import(NULL),
473     m_assemblyImport(NULL),
474     m_manifestAssemblyImport(NULL),
475     m_dependencies(NULL),
476     m_imports(NULL),
477     m_dis(dis),
478     m_MetadataSize(0),
479     m_ILHostCopy(NULL),
480     m_isMscorlibHardBound(false),
481     m_sectionAlignment(0)
482 {
483     IfFailThrow(m_display->GetDumpOptions(&m_dumpOptions));
484
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;
494     do
495     {
496         current = m_dumpOptions;
497         for( unsigned i = 0; i < _countof(g_dependencies); ++i )
498         {
499             if( m_dumpOptions & g_dependencies[i].m_value )
500                 m_dumpOptions |= g_dependencies[i].m_dep;
501         }
502     }while( current != m_dumpOptions );
503     IF_OPT(DISASSEMBLE_CODE)
504     {
505         //configure the disassembler
506         m_dis->SetTranslateAddrCallback(TranslateAddressCallback);
507         m_dis->SetTranslateFixupCallback(TranslateFixupCallback);
508         m_dis->PvClientSet(this);
509     }
510 }
511
512 void GuidToString( GUID& guid, SString& s )
513 {
514     WCHAR guidString[64];
515     GuidToLPWSTR(guid, guidString, sizeof(guidString) / sizeof(WCHAR));
516     //prune the { and }
517     _ASSERTE(guidString[0] == W('{')
518              && guidString[wcslen(guidString) - 1] == W('}'));
519     guidString[wcslen(guidString) - 1] = W('\0');
520     s.Append( guidString + 1 );
521 }
522
523 NativeImageDumper::~NativeImageDumper()
524 {
525 }
526
527 inline const void * ptr_add(const void * ptr, COUNT_T size)
528 {
529     return reinterpret_cast<const BYTE *>(ptr) + size;
530 }
531
532 //This does pointer arithmetic on a DPtr.
533 template<typename T>
534 inline const DPTR(T) dptr_add(T* ptr, COUNT_T offset)
535 {
536     return DPTR(T)(PTR_HOST_TO_TADDR(ptr) + (offset * sizeof(T)));
537 }
538
539 template<typename T>
540 inline const DPTR(T) dptr_sub(T* ptr, COUNT_T offset)
541 {
542     return DPTR(T)(PTR_HOST_TO_TADDR(ptr) - (offset * sizeof(T)));
543 }
544 template<typename T>
545 inline const DPTR(T) dptr_sub(DPTR(T)* ptr, COUNT_T offset)
546 {
547     return DPTR(T)(PTR_HOST_TO_TADDR(ptr) - (offset * sizeof(T)));
548 }
549
550 struct MDTableType
551 {
552     MDTableType(unsigned t, const char * n) : m_token(t), m_name(n)  { }
553     unsigned m_token;
554     const char * m_name;
555 };
556
557 static unsigned s_tableTypes[] =
558 {
559     /*
560 #ifdef MiniMdTable
561 #undef MiniMdTable
562 #endif
563 #define MiniMdTable(x) TBL_##x << 24,
564     MiniMdTables()
565 #undef MiniMdTable
566     mdtName
567     */
568     mdtModule,
569     mdtTypeRef,
570     mdtTypeDef,
571     mdtFieldDef,
572     mdtMethodDef,
573     mdtParamDef,
574     mdtInterfaceImpl,
575     mdtMemberRef,
576     mdtCustomAttribute,
577     mdtPermission,
578     mdtSignature,
579     mdtEvent,
580     mdtProperty,
581     mdtModuleRef,
582     mdtTypeSpec,
583     mdtAssembly,
584     mdtAssemblyRef,
585     mdtFile,
586     mdtExportedType,
587     mdtManifestResource,
588     mdtGenericParam,
589     mdtMethodSpec,
590     mdtGenericParamConstraint,
591 };
592
593 const NativeImageDumper::EnumMnemonics s_CorHdrFlags[] =
594 {
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"))
603 #undef CHF_ENTRY
604 };
605
606 void NativeImageDumper::DumpAssemblySignature(CORCOMPILE_ASSEMBLY_SIGNATURE & assemblySignature)
607 {
608     {
609         TempBuffer buf;
610         GuidToString(assemblySignature.mvid, buf);
611         DisplayWriteFieldStringW( mvid, (const WCHAR*)buf,
612                                   CORCOMPILE_ASSEMBLY_SIGNATURE,
613                                   COR_INFO );
614     }
615     DisplayWriteFieldInt( timeStamp, assemblySignature.timeStamp,
616                           CORCOMPILE_ASSEMBLY_SIGNATURE, COR_INFO );
617     DisplayWriteFieldInt( ilImageSize,
618                           assemblySignature.ilImageSize,
619                           CORCOMPILE_ASSEMBLY_SIGNATURE, COR_INFO );
620 }
621
622
623 //error code return?
624 void
625 NativeImageDumper::DumpNativeImage()
626 {
627     COUNT_T size;
628     const void *data;
629
630     m_display->StartDocument();
631
632     DisplayStartCategory( "File", PE_INFO );
633     DisplayWriteElementStringW( "path", m_name, PE_INFO );
634     
635     DisplayWriteElementInt( "diskSize", m_decoder.GetSize(), PE_INFO );
636     _ASSERTE(sizeof(IMAGE_DOS_HEADER) < m_decoder.GetSize());
637
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 );
643
644     // NT headers
645
646     if (!m_decoder.HasNTHeaders())
647     {
648         IF_OPT(PE_INFO)
649         {
650             DisplayWriteElementString("isPEFile", "false", PE_INFO);
651             DisplayEndCategory(PE_INFO);
652         }
653         else
654             m_display->ErrorPrintF("Non-PE file");
655
656         m_display->EndDocument();
657         return;
658     }
659
660     CONSISTENCY_CHECK(m_decoder.CheckNTHeaders());
661     if (!m_decoder.CheckNTHeaders())
662     {
663         m_display->ErrorPrintF("*** NT headers are not valid ***");
664         return;
665     }
666
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(),
672                             PE_INFO );
673
674     if( m_decoder.Has32BitNTHeaders() )
675     {
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?
687          */
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 );
695
696     }
697     else
698     {
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 );
714     }
715     DisplayEndCategory(PE_INFO);
716
717     // PE Section info
718
719     DisplayStartArray("Sections", W("%-8s%s\t(disk %s)  %s"), PE_INFO);
720
721     for (COUNT_T i = 0; i < m_decoder.GetNumberOfSections(); i++)
722     {
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 );
734
735         DisplayWriteElementEnumerated( "access", section->Characteristics,
736                                        s_ImageSections, W(", "), PE_INFO );
737         DisplayEndStructure( PE_INFO ); //Section
738     }
739     DisplayEndArray("Total Sections", PE_INFO);
740
741     // Image directory info
742
743     DisplayStartArray( "Directories", W("%-40s%s"), PE_INFO );
744
745     for ( COUNT_T i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
746     {
747         static const char *directoryNames[] = 
748         {
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",
764             /* 2*/"",
765         };
766
767         IMAGE_DATA_DIRECTORY *entry = m_decoder.GetDirectoryEntry(i);
768
769         if (entry->VirtualAddress != 0)
770         {
771             DisplayStartElement("Directory", PE_INFO);
772             DisplayWriteElementString("name", directoryNames[i], PE_INFO);
773             DisplayWriteElementAddress("address",
774                                        RvaToDisplay(entry->VirtualAddress),
775                                        entry->Size, PE_INFO);
776
777             DisplayEndElement( PE_INFO ); //Directory
778         }
779     }
780     DisplayEndArray("Total Directories", PE_INFO); //Directories
781
782     // COM+ info
783
784     if (!m_decoder.HasCorHeader())
785     {
786         IF_OPT(COR_INFO)
787             DisplayWriteElementString("CLRInfo", "<none>", COR_INFO);
788         else
789             m_display->ErrorPrintF("Non-CLR image\n");
790
791         m_display->EndDocument();
792         return;
793     }
794
795     CONSISTENCY_CHECK(m_decoder.CheckCorHeader());
796     if (!m_decoder.CheckCorHeader())
797     {
798         m_display->ErrorPrintF("*** INVALID CLR Header ***");
799         m_display->EndDocument();
800         return;
801     }
802
803     DisplayStartCategory("CLRInfo", COR_INFO);
804     PTR_IMAGE_COR20_HEADER pCor(m_decoder.GetCorHeader());
805     {
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 ),       \
810             pCor-> name . Size  )
811
812         m_display->StartStructure( "IMAGE_COR20_HEADER",
813                                    DPtrToPreferredAddr(pCor),
814                                    sizeof(*pCor) );
815
816         DisplayWriteFieldUInt( MajorRuntimeVersion, pCor->MajorRuntimeVersion, IMAGE_COR20_HEADER, COR_INFO );
817         DisplayWriteFieldUInt( MinorRuntimeVersion, pCor->MinorRuntimeVersion, IMAGE_COR20_HEADER, COR_INFO );
818
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 );
823
824         // Binding information
825         WRITE_COR20_FIELD(Resources); 
826         WRITE_COR20_FIELD(StrongNameSignature); 
827
828         // Regular fixup and binding information
829         WRITE_COR20_FIELD(CodeManagerTable); 
830         WRITE_COR20_FIELD(VTableFixups);
831         WRITE_COR20_FIELD(ExportAddressTableJumps);  
832
833         // Precompiled image info
834         WRITE_COR20_FIELD(ManagedNativeHeader);  
835         
836         m_display->EndStructure(); //IMAGE_COR20_HEADER
837 #undef WRITE_COR20_FIELD
838     }
839
840     //make sure to touch the strong name signature even if we won't print it.
841     if (m_decoder.HasStrongNameSignature())
842     {
843         if (m_decoder.IsStrongNameSigned())
844         {
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)));
847
848             IF_OPT(COR_INFO)
849             {
850                 TempBuffer sig;
851
852                 appendByteArray(sig, (BYTE*)data, size);
853
854                 DisplayWriteElementStringW( "StrongName", (const WCHAR *)sig,
855                                             COR_INFO );
856             }
857         }
858         else
859         {
860             DisplayWriteEmptyElement("DelaySigned", COR_INFO);
861         }
862     }
863
864 #ifdef FEATURE_READYTORUN
865     if (m_decoder.HasReadyToRunHeader())
866         DisplayWriteElementString( "imageType", "ReadyToRun image", COR_INFO);
867     else
868 #endif
869     if (m_decoder.IsILOnly())
870         DisplayWriteElementString( "imageType", "IL only image", COR_INFO);
871     else
872     if (m_decoder.HasNativeHeader())
873         DisplayWriteElementString( "imageType", "Native image", COR_INFO);
874     else
875         DisplayWriteElementString( "imageType", "Mixed image", COR_INFO);
876
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)));
879     OpenMetadata();
880     IF_OPT(METADATA)
881     {
882         DWORD dwAssemblyFlags = 0;
883         IfFailThrow(m_manifestAssemblyImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL,
884                                                           NULL, NULL,
885                                                           NULL, NULL,
886                                                           NULL, &dwAssemblyFlags));
887         if ((afContentType_WindowsRuntime & dwAssemblyFlags) == afContentType_WindowsRuntime)
888         {
889             // The WinMD adapter doesn't implement the IID_IMetaDataTables interface so we can't dump
890             // the raw metadata.
891             DisplayWriteElementString ("Metadata", "Not supported by WinRT", COR_INFO);
892         }
893         else
894         {
895             WriteElementsMetadata( "Metadata", TO_TADDR(data), size );
896         }
897     }
898
899     CoverageRead(TO_TADDR(data), size);
900
901     if (m_decoder.HasNativeHeader())
902     {
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)));
905
906         IF_OPT(METADATA)
907         {
908             WriteElementsMetadata( "NativeManifestMetadata", TO_TADDR(data), size );
909         }
910         else
911         {
912             DisplayWriteElementAddress( "NativeManifestMetadata",
913                                         DataPtrToDisplay((TADDR)data), size,
914                                         COR_INFO );
915         }
916
917
918         /* REVISIT_TODO Tue 09/20/2005
919          * Anything to display in the native metadata?
920          */
921         CoverageRead(TO_TADDR(data), size);
922
923         /* REVISIT_TODO Tue 09/20/2005
924          * Dump the debug map?  Indexed by method RID... probably a good idea
925          */
926         data = reinterpret_cast<void*>(m_decoder.GetNativeDebugMap(&size));
927
928         DisplayWriteElementAddress( "debugMap", DataPtrToDisplay((TADDR)data), size,
929                                     COR_INFO);
930         CoverageRead(TO_TADDR(data), size);
931
932         //also read the entire debug map section
933         IMAGE_SECTION_HEADER * dbgmap = FindSection( ".dbgmap" );
934         if (dbgmap != NULL)
935         {
936             CoverageRead(TO_TADDR(dbgmap->VirtualAddress)
937                          + PTR_TO_TADDR(m_decoder.GetBase()),
938                          (ULONG32)ALIGN_UP(dbgmap->Misc.VirtualSize, GetSectionAlignment()));
939         }
940
941         //read the .il and .rsrc sections in their entirety
942         IF_OPT(DEBUG_COVERAGE)
943         {
944             IMAGE_SECTION_HEADER *hdr;
945             hdr = FindSection( ".rsrc" );
946             if( hdr != NULL )
947             {
948                 CoverageRead( m_decoder.GetRvaData(hdr->VirtualAddress),
949                               (ULONG32)hdr->Misc.VirtualSize );
950             }
951         }
952         IF_OPT_OR(DEBUG_COVERAGE, IL)
953         {
954             IMAGE_SECTION_HEADER *hdr = FindSection( ".text" );
955
956             if( hdr != NULL )
957             {
958                 m_ILSectionStart = hdr->VirtualAddress;
959                 m_ILHostCopy = (BYTE*)PTR_READ(m_decoder.GetRvaData(hdr->VirtualAddress), hdr->Misc.VirtualSize);
960 #ifdef _DEBUG
961                 m_ILSectionSize = hdr->Misc.VirtualSize;
962 #endif
963             }
964             else
965             {
966                 m_ILSectionStart = 0;
967                 m_ILHostCopy = NULL;
968 #ifdef _DEBUG
969                 m_ILSectionSize = 0;
970 #endif
971             }
972             _ASSERTE( (((TADDR)m_ILHostCopy) & 3) == 0 );
973             _ASSERTE((m_ILSectionStart & 3) == 0);
974
975         }
976     }
977
978     data = m_decoder.GetResources(&size);
979     IF_OPT(RESOURCES)
980     {
981         DisplayStartStructure( "resource", DataPtrToDisplay((TADDR)data), size,
982                                COR_INFO );
983         DisplayStartArray( "Resources", NULL, COR_INFO );
984         HCORENUM hEnum = NULL;
985         for(;;)
986         {
987             mdManifestResource resTokens[1];
988             ULONG numTokens = 0;
989             IfFailThrow(m_assemblyImport->EnumManifestResources(&hEnum,
990                                                                 resTokens,
991                                                                 1,
992                                                                 &numTokens));
993             if( numTokens == 0 )
994                 break;
995
996             WCHAR resourceName[256];
997             ULONG nameLen;
998             mdToken impl;
999             DWORD offset, flags;
1000             IfFailThrow(m_assemblyImport->GetManifestResourceProps(resTokens[0],
1001                                                            resourceName,
1002                                                            _countof(resourceName),
1003                                                            &nameLen,
1004                                                            &impl,
1005                                                            &offset,
1006                                                            &flags));
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),
1015                                               RESOURCES );            
1016         }
1017         DisplayEndArray( "Total Resources", COR_INFO ); //Resources
1018         DisplayEndStructure( COR_INFO ); //resource
1019     }
1020     else
1021     {
1022         DisplayWriteElementAddress( "resource", DataPtrToDisplay((TADDR)data), size,
1023                                     COR_INFO );
1024     }
1025
1026     ULONG resultSize;
1027     GUID mvid;
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?
1031      */
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 );
1037
1038     if (m_decoder.HasManagedEntryPoint())
1039     {
1040         DisplayStartVStructure( "ManagedEntryPoint", COR_INFO );
1041         unsigned token = m_decoder.GetEntryPointToken();
1042         DisplayWriteElementUInt( "Token", token, COR_INFO );
1043         TempBuffer buf;
1044         AppendTokenName( token, buf );
1045         DisplayWriteElementStringW( "TokenName", (const WCHAR *)buf, COR_INFO );
1046         DisplayEndVStructure( COR_INFO );
1047     }
1048     else if (m_decoder.HasNativeEntryPoint())
1049     {
1050         DisplayWriteElementPointer( "NativeEntryPoint", (SIZE_T)m_decoder.GetNativeEntryPoint(),
1051                                     COR_INFO );
1052     }
1053
1054     /* REVISIT_TODO Mon 11/21/2005
1055      * Dump the version info completely
1056      */
1057     if( m_decoder.HasNativeHeader() )
1058     {
1059         PTR_CORCOMPILE_VERSION_INFO versionInfo( m_decoder.GetNativeVersionInfo() );
1060
1061         DisplayStartStructure("CORCOMPILE_VERSION_INFO",
1062                               DPtrToPreferredAddr(versionInfo),
1063                               sizeof(*versionInfo), COR_INFO);
1064
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
1071
1072         COUNT_T numDeps;
1073         PTR_CORCOMPILE_DEPENDENCY deps(TO_TADDR(m_decoder.GetNativeDependencies(&numDeps)));
1074
1075         DisplayStartArray( "Dependencies", NULL, COR_INFO );
1076
1077         for( COUNT_T i = 0; i < numDeps; ++i )
1078         {
1079             DisplayStartStructure("CORCOMPILE_DEPENDENCY", DPtrToPreferredAddr(deps + i),
1080                                   sizeof(deps[i]), COR_INFO );
1081             WriteFieldMDTokenImport( dwAssemblyRef, deps[i].dwAssemblyRef,
1082                                      CORCOMPILE_DEPENDENCY, COR_INFO, 
1083                                      m_manifestImport );
1084             WriteFieldMDTokenImport( dwAssemblyDef, deps[i].dwAssemblyDef,
1085                                      CORCOMPILE_DEPENDENCY, COR_INFO,
1086                                      m_manifestImport );
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
1093
1094             {
1095                 TempBuffer buf;
1096                 if( deps[i].signNativeImage == INVALID_NGEN_SIGNATURE )
1097                 {
1098                     buf.Append( W("INVALID_NGEN_SIGNATURE") );
1099                 }
1100                 else
1101                 {
1102                     GuidToString(deps[i].signNativeImage, buf);
1103                 }
1104                 DisplayWriteFieldStringW( signNativeImage, (const WCHAR*)buf,
1105                                           CORCOMPILE_DEPENDENCY, COR_INFO );
1106 #if 0
1107                 if( m_librarySupport
1108                     && deps[i].signNativeImage != INVALID_NGEN_SIGNATURE )
1109                 {
1110                     buf.Clear();
1111                     AppendTokenName(deps[i].dwAssemblyRef, buf, m_import );
1112                     IfFailThrow(m_librarySupport->LoadDependency( (const WCHAR*)buf,
1113                                                                   deps[i].signNativeImage ));
1114                 }
1115 #endif
1116
1117             }
1118
1119
1120             DisplayEndStructure(COR_INFO); //CORCOMPILE_DEPENDENCY
1121         }
1122         DisplayEndArray( "Total Dependencies", COR_INFO );
1123         DisplayEndStructure(COR_INFO); //CORCOMPILE_VERSION_INFO
1124
1125         NativeImageDumper::Dependency * traceDependency = OpenDependency(0);
1126         TraceDumpDependency( 0, traceDependency );
1127
1128         for( COUNT_T i = 0; i < numDeps; ++i )
1129         {
1130             traceDependency = OpenDependency( i + 1 );
1131             TraceDumpDependency( i + 1, traceDependency );
1132         }
1133         _ASSERTE(m_dependencies[0].pModule != NULL);
1134
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"
1140          * is mscorlib.
1141          */
1142         Dependency * mscorlib = NULL;
1143         for( COUNT_T i = 0; i < m_numDependencies; ++i )
1144         {
1145             if( m_dependencies[i].fIsMscorlib )
1146             {
1147                 mscorlib = &m_dependencies[i];
1148                 break;
1149             }
1150         }
1151         
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))
1154         {
1155             mscorlib = GetDependency(0);
1156             mscorlib->fIsMscorlib = TRUE;
1157             _ASSERTE(mscorlib->fIsHardbound);
1158         }
1159
1160         _ASSERTE(mscorlib != NULL);
1161         if( mscorlib->fIsHardbound )
1162         {
1163             m_isMscorlibHardBound = true;
1164         }
1165         if( m_isMscorlibHardBound )
1166         {
1167             //go through the module to the binder.
1168             PTR_Module mscorlibModule = mscorlib->pModule;
1169
1170             PTR_MscorlibBinder binder = mscorlibModule->m_pBinder;
1171             g_Mscorlib = *binder;
1172
1173             PTR_MethodTable mt = MscorlibBinder::GetExistingClass(CLASS__OBJECT);
1174             g_pObjectClass = mt;
1175         }
1176
1177
1178         if (g_pObjectClass == NULL)
1179         {
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;
1185
1186         }
1187     }
1188     
1189
1190     // @todo: VTable Fixups
1191
1192     // @todo: EAT Jumps
1193
1194     DisplayEndCategory(COR_INFO); //CLRInfo
1195
1196 #ifdef FEATURE_READYTORUN
1197     if (m_decoder.HasReadyToRunHeader())
1198     {
1199         DumpReadyToRun();
1200     }
1201     else
1202 #endif
1203     if (m_decoder.HasNativeHeader())
1204     {
1205         DumpNative();
1206     }
1207
1208     m_display->EndDocument();
1209 }
1210
1211 void NativeImageDumper::DumpNative()
1212 {
1213     DisplayStartCategory("NativeInfo", NATIVE_INFO);
1214
1215     CONSISTENCY_CHECK(m_decoder.CheckNativeHeader());
1216     if (!m_decoder.CheckNativeHeader())
1217     {
1218         m_display->ErrorPrintF("*** INVALID NATIVE HEADER ***\n");
1219         return;
1220     }
1221
1222     IF_OPT(NATIVE_INFO)
1223         DumpNativeHeader();
1224
1225     //host pointer
1226     CORCOMPILE_EE_INFO_TABLE * infoTable = m_decoder.GetNativeEEInfoTable();
1227
1228     DisplayStartStructure( "CORCOMPILE_EE_INFO_TABLE",
1229                            DataPtrToDisplay(PTR_HOST_TO_TADDR(infoTable)),
1230                            sizeof(*infoTable), NATIVE_INFO );
1231
1232     /* REVISIT_TODO Mon 09/26/2005
1233      * Move this further down to include the dumping of the module, and
1234      * other things.
1235      */
1236     DisplayEndStructure(NATIVE_INFO); //NativeInfoTable
1237     DisplayEndCategory(NATIVE_INFO); //NativeInfo
1238 #if LATER
1239     //come back here and dump all the fields of the CORCOMPILE_EE_INFO_TABLE
1240 #endif
1241
1242     IF_OPT(RELOCATIONS)
1243         DumpBaseRelocs();
1244
1245     IF_OPT(NATIVE_TABLES)
1246         DumpHelperTable();
1247     
1248     PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
1249
1250     //this needs to run for precodes to load the tables that identify precode ranges
1251     IF_OPT_OR5(MODULE, METHODTABLES, EECLASSES, TYPEDESCS, PRECODES)
1252         DumpModule(module);
1253
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 );
1260 }
1261
1262 void NativeImageDumper::TraceDumpDependency(int idx, NativeImageDumper::Dependency * dependency)
1263 {
1264     IF_OPT(DEBUG_TRACE)
1265     {
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);
1276     }
1277 }
1278
1279 void NativeImageDumper::WriteElementsMetadata( const char * elementName,
1280                                                TADDR data, SIZE_T size )
1281 {
1282     DisplayStartStructure( elementName,
1283                            DataPtrToDisplay(data), size, ALWAYS );
1284
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.
1289      */
1290     ReleaseHolder<IMetaDataTables> tables;
1291     ReleaseHolder<IMetaDataDispenserEx> pDispenser;
1292     IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
1293                                      IID_IMetaDataDispenserEx, (void **) &pDispenser));
1294
1295     VARIANT opt;
1296
1297     TADDR hostCopyStart = TO_TADDR(PTR_READ(data, (ULONG32)size));
1298     TADDR rebasedPointer;
1299
1300     IfFailThrow(pDispenser->GetOption(MetaDataCheckDuplicatesFor, &opt));
1301     V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile;
1302     IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &opt));
1303
1304     IfFailThrow(pDispenser->OpenScopeOnMemory((const void *)hostCopyStart, (DWORD)size,
1305                                               ofRead, IID_IMetaDataTables,
1306                                               (IUnknown **) &tables));
1307     DisplayStartArray( "Tables", W("%s"), ALWAYS );
1308
1309     for( unsigned i = 0; i < _countof(s_tableTypes); ++i )
1310     {
1311         HRESULT hr = S_OK;
1312         ULONG idx = 0;
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;
1317         BYTE * ptr = NULL;
1318         hr = tables->GetTableInfo(idx, &cbRow, &cRows, &cCols,
1319                                   &iKey, &name);
1320         _ASSERTE(SUCCEEDED(hr) || hr == E_INVALIDARG);
1321         if( hr == E_INVALIDARG || cRows == 0 )
1322         {
1323             continue; //no such table.
1324         }
1325
1326         hr = tables->GetRow(idx, 1, (void**)&ptr);
1327         IfFailThrow(hr);
1328         _ASSERTE(SUCCEEDED(hr));
1329         //compute address
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 );
1335 #if 0
1336         DisplayStartElement( "table", ALWAYS );
1337         DisplayWriteElementString( "name", name, ALWAYS );
1338         //compute address
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
1344 #endif
1345     }
1346     DisplayEndArray( "Total Tables",  ALWAYS );
1347
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 );
1355     
1356     //now check the pools
1357
1358     //start of stream headers
1359     PTR_STORAGESTREAM streamHeader( PTR_TO_TADDR(sHdr) + sizeof(*sHdr) );
1360     for( unsigned i = 0; i < sHdr->iStreams; ++i )
1361     {
1362         if( streamHeader->iSize > 0 )
1363         {
1364             DisplayWriteElementAddressNamed( "heap", streamHeader->rcName,
1365                                              DataPtrToDisplay( data + streamHeader->iOffset ),
1366                                              streamHeader->iSize, ALWAYS );
1367         }
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));
1372     }
1373     
1374     DisplayEndArray( "Total Pools", ALWAYS ); //Pools
1375     DisplayEndStructure( ALWAYS ); //nativeMetadata
1376 }
1377 void NativeImageDumper::OpenMetadata()
1378 {
1379     COUNT_T size;
1380
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)));
1383
1384     ReleaseHolder<IMetaDataDispenserEx> pDispenser;
1385     IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
1386                                      IID_IMetaDataDispenserEx, (void **) &pDispenser));
1387
1388     VARIANT opt;
1389     IfFailThrow(pDispenser->GetOption(MetaDataCheckDuplicatesFor, &opt));
1390     V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile;
1391     IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &opt));
1392
1393     data = PTR_READ(TO_TADDR(data), size);
1394     IfFailThrow(pDispenser->OpenScopeOnMemory(data, size, ofRead, 
1395                                               IID_IMetaDataImport2, (IUnknown **) &m_import));
1396     
1397     IfFailThrow(m_import->QueryInterface(IID_IMetaDataAssemblyImport,
1398                                           (void **)&m_assemblyImport));
1399
1400     m_MetadataStartTarget = TO_TADDR(data);
1401     m_MetadataSize = size;
1402     data = PTR_READ(TO_TADDR(data), size);
1403     m_MetadataStartHost = TO_TADDR(data);
1404
1405     if (m_decoder.HasNativeHeader())
1406     {
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)));
1409
1410         IfFailThrow(pDispenser->OpenScopeOnMemory(data, size, ofRead, 
1411                                                   IID_IMetaDataImport2, (IUnknown **) &m_manifestImport));
1412
1413         IfFailThrow(m_manifestImport->QueryInterface(IID_IMetaDataAssemblyImport,
1414                                               (void **)&m_manifestAssemblyImport));
1415     }
1416     else
1417     {
1418         m_manifestImport =  m_import;
1419         m_manifestImport->AddRef();
1420
1421         m_manifestAssemblyImport = m_assemblyImport;
1422         m_manifestAssemblyImport->AddRef();
1423     }
1424 }
1425 void
1426 NativeImageDumper::AppendTokenName(mdToken token, SString& buf)
1427 {
1428     AppendTokenName(token, buf, NULL);
1429 }
1430 void
1431 NativeImageDumper::AppendTokenName(mdToken token, SString& buf,
1432                                    IMetaDataImport2 *pImport,
1433                                    bool force)
1434 {
1435     mdToken parent;
1436     ULONG size;
1437     DWORD attr;
1438     PCCOR_SIGNATURE pSig;
1439     PTR_CCOR_SIGNATURE dacSig;
1440     ULONG cSig;
1441     DWORD flags;
1442     ULONG rva;
1443     CQuickBytes bytes;
1444
1445     if( CHECK_OPT(DISABLE_NAMES) && !force )
1446     {
1447         buf.Append( W("Disabled") );
1448         return;
1449     }
1450
1451     if (pImport == NULL)
1452         pImport = m_import;
1453     if( RidFromToken(token) == mdTokenNil )
1454     {
1455         AppendNilToken( token, buf );
1456     }
1457     else
1458     {
1459         switch (TypeFromToken(token))
1460         {
1461         case mdtTypeDef:
1462             IfFailThrow(pImport->GetTypeDefProps(token, bigBuffer, bigBufferSize, &size, &flags, &parent));
1463             buf.Append(bigBuffer);
1464             break;
1465
1466         case mdtTypeRef:
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 (?)"));
1471             else
1472                 buf.Append(bigBuffer);
1473             break;
1474
1475         case mdtTypeSpec:
1476             IfFailThrow(pImport->GetTypeSpecFromToken(token, &pSig, &cSig));
1477             dacSig = metadataToHostDAC(pSig, pImport);
1478             TypeToString(dacSig, buf, pImport);
1479             break;
1480
1481         case mdtFieldDef:
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 );
1488             break;
1489
1490         case mdtMethodDef:
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 );
1497             break;
1498
1499         case mdtMemberRef:
1500             IfFailThrow(pImport->GetMemberRefProps(token, &parent, bigBuffer, bigBufferSize, &size,
1501                                                    &pSig, &cSig));
1502             AppendTokenName(parent, buf, pImport);
1503             IfFailThrow(pImport->GetMemberRefProps(token, &parent, bigBuffer, bigBufferSize, &size,
1504                                                    &pSig, &cSig));
1505             buf.AppendPrintf( W("::%s"), bigBuffer );
1506             break;
1507
1508         case mdtSignature:
1509             IfFailThrow(pImport->GetSigFromToken(token, &pSig, &cSig));
1510 #if LATER
1511             PrettyPrintSig(pSig, cSig, W(""), &bytes, pImport);
1512             m_display->ErrorPrintF("%S", bytes.Ptr());
1513 #else
1514             _ASSERTE(!"Unimplemented");
1515             m_display->ErrorPrintF( "unimplemented" );
1516 #endif
1517             break;
1518
1519         case mdtString:
1520             IfFailThrow(pImport->GetUserString(token, bigBuffer, bigBufferSize, &size));
1521             bigBuffer[min(size, bigBufferSize-1)] = 0;
1522             buf.Append( bigBuffer );
1523             break;
1524
1525         case mdtAssembly:
1526         case mdtAssemblyRef:
1527         case mdtFile:
1528         case mdtExportedType:
1529             {
1530                 ReleaseHolder<IMetaDataAssemblyImport> pAssemblyImport;
1531                 IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
1532                                                     (void **)&pAssemblyImport));
1533                 PrintManifestTokenName(token, buf, pAssemblyImport, force);
1534             }
1535             break;
1536
1537         case mdtGenericParam:
1538             {
1539                 ULONG nameLen;
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 );
1544             }
1545             break;
1546
1547         default:
1548             _ASSERTE( !"Unknown token type in AppendToken" );
1549             buf.AppendPrintf( W("token 0x%x"), token );
1550         }
1551     }
1552 }
1553 void NativeImageDumper::PrintManifestTokenName(mdToken token, SString& str)
1554 {
1555     PrintManifestTokenName(token, str, NULL);
1556 }
1557 void
1558 NativeImageDumper::PrintManifestTokenName(mdToken token,
1559                                           SString& buf,
1560                                           IMetaDataAssemblyImport *pAssemblyImport,
1561                                           bool force)
1562 {
1563     ULONG size;
1564     const void *pSig;
1565     ULONG cSig;
1566     DWORD flags;
1567     CQuickBytes bytes;
1568     ULONG hash;
1569
1570     if( CHECK_OPT(DISABLE_NAMES) && !force )
1571     {
1572         buf.Append( W("Disabled") );
1573         return;
1574     }
1575
1576     if (pAssemblyImport == NULL)
1577         pAssemblyImport = m_manifestAssemblyImport;
1578
1579     if( RidFromToken(token) == mdTokenNil )
1580     {
1581         AppendNilToken( token, buf );
1582     }
1583     else
1584     {
1585         switch (TypeFromToken(token))
1586         {
1587         case mdtAssembly:
1588             IfFailThrow(pAssemblyImport->GetAssemblyProps(token, &pSig, &cSig,
1589                                                           &hash, bigBuffer,
1590                                                           bigBufferSize, &size,
1591                                                           NULL, &flags));
1592
1593             buf.Append(bigBuffer);
1594             break;
1595
1596         case mdtAssemblyRef:
1597             IfFailThrow(pAssemblyImport->GetAssemblyRefProps(token, &pSig,
1598                                                              &cSig, bigBuffer,
1599                                                              bigBufferSize,
1600                                                              &size, NULL, NULL,
1601                                                              NULL, &flags));
1602             buf.Append(bigBuffer);
1603             break;
1604
1605         case mdtFile:
1606             IfFailThrow(pAssemblyImport->GetFileProps(token, bigBuffer,
1607                                                       bigBufferSize, &size,
1608                                                       NULL, NULL, &flags));
1609
1610             buf.Append(bigBuffer);
1611             break;
1612
1613         case mdtExportedType:
1614             IfFailThrow(pAssemblyImport->GetExportedTypeProps(token, bigBuffer,
1615                                                       bigBufferSize, &size,
1616                                                       NULL, NULL, &flags));
1617
1618             buf.Append(bigBuffer);
1619             break;
1620
1621         default:
1622             buf.AppendPrintf(W("token %x"), token);
1623         }
1624     }
1625 }
1626
1627 BOOL NativeImageDumper::HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection,
1628                                                 SIZE_T fixupIndex,
1629                                                 SIZE_T *fixupCell)
1630 {
1631     COUNT_T nImportSections;
1632     PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1633
1634     COUNT_T tableSize;
1635     TADDR tableBase = m_decoder.GetDirectoryData(&pSection->Section, &tableSize);
1636
1637     COUNT_T table = (COUNT_T)(pSection - pImportSections);
1638     _ASSERTE(table < nImportSections);
1639
1640     SIZE_T offset = dac_cast<TADDR>(fixupCell) - tableBase;
1641     _ASSERTE( offset < tableSize );
1642
1643     COUNT_T entry = (COUNT_T)(offset / sizeof(TADDR));
1644     m_fixupHistogram[table][entry]++;
1645
1646     return TRUE;
1647 }
1648
1649 void NativeImageDumper::ComputeMethodFixupHistogram( PTR_Module module )
1650 {
1651     COUNT_T nImportSections;
1652     PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1653
1654     m_fixupHistogram = new COUNT_T * [nImportSections];
1655
1656     for (COUNT_T i=0; i < nImportSections; i++)
1657     {
1658         PTR_CORCOMPILE_IMPORT_SECTION pSection = m_decoder.GetNativeImportSectionFromIndex(i);
1659
1660         COUNT_T count = pSection->Section.Size / sizeof(TADDR);
1661
1662         m_fixupHistogram[i] = new COUNT_T [count];
1663         ZeroMemory(m_fixupHistogram[i], count * sizeof(COUNT_T));
1664     }
1665
1666     ZeroMemory(&m_fixupCountHistogram, sizeof(m_fixupCountHistogram));
1667     // profiled hot code
1668
1669     MethodIterator mi(module, &m_decoder, MethodIterator::Hot);
1670     while (mi.Next())
1671     {
1672         m_fixupCount = 0;
1673
1674         TADDR pFixupList = mi.GetMethodDesc()->GetFixupList();
1675
1676         if (pFixupList != NULL)
1677         {
1678             COUNT_T nImportSections;
1679             PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1680
1681             module->FixupDelayListAux(pFixupList, this,
1682                 &NativeImageDumper::HandleFixupForHistogram,
1683                 pImportSections, nImportSections,
1684                 &m_decoder);
1685         }
1686
1687         if (m_fixupCount < COUNT_HISTOGRAM_SIZE)
1688             m_fixupCountHistogram[m_fixupCount]++;
1689         else
1690             m_fixupCountHistogram[COUNT_HISTOGRAM_SIZE-1]++;
1691     }
1692
1693     // unprofiled code
1694     MethodIterator miUnprofiled(module, &m_decoder, MethodIterator::Unprofiled);
1695
1696     while(miUnprofiled.Next())
1697     {
1698         m_fixupCount = 0;
1699
1700         TADDR pFixupList = miUnprofiled.GetMethodDesc()->GetFixupList();
1701
1702         if (pFixupList != NULL)
1703         {
1704             COUNT_T nImportSections;
1705             PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1706
1707             module->FixupDelayListAux(pFixupList, this,
1708                 &NativeImageDumper::HandleFixupForHistogram,
1709                 pImportSections, nImportSections,
1710                 &m_decoder);
1711         }
1712
1713         if (m_fixupCount < COUNT_HISTOGRAM_SIZE)
1714             m_fixupCountHistogram[m_fixupCount]++;
1715         else
1716             m_fixupCountHistogram[COUNT_HISTOGRAM_SIZE-1]++;
1717     }
1718 }
1719
1720 void NativeImageDumper::DumpFixupTables( PTR_Module module )
1721 {
1722     IF_OPT(FIXUP_HISTOGRAM)
1723         ComputeMethodFixupHistogram( module );
1724
1725     DisplayStartCategory( "Imports", FIXUP_TABLES );
1726
1727     COUNT_T nImportSections;
1728     PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
1729
1730     for (COUNT_T iImportSections = 0; iImportSections < nImportSections; iImportSections++)
1731     {
1732         PTR_CORCOMPILE_IMPORT_SECTION pImportSection = pImportSections + iImportSections;
1733
1734         COUNT_T size;
1735         TADDR pTable(m_decoder.GetDirectoryData(&pImportSection->Section, &size));
1736         TADDR pTableEnd = pTable + size;
1737
1738         TADDR pDataTable(NULL);
1739         
1740         if (pImportSection->Signatures != 0)
1741             pDataTable = m_decoder.GetRvaData(pImportSection->Signatures);
1742
1743         switch (pImportSection->Type)
1744         {
1745         case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
1746             {
1747                 COUNT_T entrySize = pImportSection->EntrySize;
1748                 COUNT_T count = size / entrySize;
1749                 _ASSERTE(entrySize == sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK));
1750
1751                 for (TADDR pEntry = pTable; pEntry < pTableEnd; pEntry += entrySize)
1752                 {
1753                     PTR_CORCOMPILE_VIRTUAL_IMPORT_THUNK pThunk = pEntry;
1754
1755                     DisplayStartStructure("VirtualImportThunk", DPtrToPreferredAddr(pThunk),
1756                                           entrySize, FIXUP_THUNKS );
1757
1758                     DisplayWriteElementInt( "Slot", pThunk->slotNum, FIXUP_THUNKS);
1759
1760                     DisplayEndStructure( FIXUP_THUNKS );
1761                 }
1762             }
1763             break;
1764
1765         case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
1766             {
1767                 COUNT_T entrySize = pImportSection->EntrySize;
1768                 COUNT_T count = size / entrySize;
1769                 _ASSERTE(entrySize == sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK));
1770
1771                 for (TADDR pEntry = pTable; pEntry < pTableEnd; pEntry += entrySize)
1772                 {
1773                     PTR_CORCOMPILE_EXTERNAL_METHOD_THUNK      pThunk = pEntry;
1774
1775                     DisplayStartStructure("ExternalImportThunk", DPtrToPreferredAddr(pThunk),
1776                                           entrySize, FIXUP_THUNKS );
1777
1778                     TADDR pDataAddr  = pDataTable + ((pEntry - pTable) / entrySize) * sizeof(DWORD);
1779                     PTR_DWORD                                 pData  = pDataAddr;
1780
1781                     DisplayWriteElementPointer( "DataAddress ",  pDataAddr,  FIXUP_THUNKS );
1782
1783                     TADDR blobSigAddr = RvaToDisplay(*pData);
1784                     DisplayWriteElementPointer( "TargetSigAddress",  blobSigAddr, FIXUP_THUNKS );
1785                     TempBuffer buf;
1786                     FixupBlobToString(*pData, buf);
1787                     DisplayWriteElementStringW( "TargetName", (const WCHAR*)buf, FIXUP_THUNKS );
1788
1789                     DisplayEndStructure( FIXUP_THUNKS );
1790                 }
1791             }
1792             break;
1793
1794         default:
1795             {
1796                 COUNT_T count = size / sizeof(TADDR);
1797
1798                 for (COUNT_T j = 0; j < count; j++)
1799                 {
1800                     if (dac_cast<PTR_TADDR>(pTable)[j] == 0)
1801                         continue;
1802
1803                     SIZE_T nNextEntry = j + 1;
1804                     while (nNextEntry < count && dac_cast<PTR_TADDR>(pTable)[nNextEntry] == 0)
1805                         nNextEntry++;
1806
1807                     DisplayStartStructure("ImportEntry", DPtrToPreferredAddr(dac_cast<PTR_TADDR>(pTable) + j),
1808                                           (nNextEntry - j) * sizeof(TADDR), FIXUP_TABLES );
1809
1810                     if (pDataTable != NULL)
1811                     {
1812                         DWORD rva = dac_cast<PTR_DWORD>(pDataTable)[j];
1813                         WriteElementsFixupTargetAndName(rva);
1814                     }
1815                     else
1816                     {
1817                         SIZE_T token = dac_cast<PTR_TADDR>(pTable)[j];
1818                         DisplayWriteElementPointer( "TaggedValue", token, FIXUP_TABLES );
1819                         WriteElementsFixupBlob(pImportSection, token);
1820                     }
1821
1822                     DisplayWriteElementInt( "index", j, FIXUP_HISTOGRAM);
1823                     DisplayWriteElementInt( "ReferenceCount", m_fixupHistogram[iImportSections][j], FIXUP_HISTOGRAM );
1824
1825                     DisplayEndStructure( FIXUP_TABLES );
1826                 }
1827             }
1828         }
1829     }
1830     DisplayEndCategory( FIXUP_TABLES );
1831 }
1832
1833 void NativeImageDumper::FixupThunkToString(PTR_CORCOMPILE_IMPORT_SECTION pImportSection, TADDR addr, SString& buf)
1834 {
1835     switch (pImportSection->Type)
1836     {
1837     case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
1838         {
1839             PTR_CORCOMPILE_VIRTUAL_IMPORT_THUNK pThunk = addr;
1840             buf.AppendPrintf( W("slot %d"), pThunk->slotNum );
1841         }
1842         break;
1843
1844     case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
1845     case CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH:
1846         {
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);
1853         }
1854         break;
1855
1856     default:
1857         _ASSERTE(!"Unknown import type");
1858     }
1859 }
1860
1861 void NativeImageDumper::WriteElementsFixupBlob(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixup)
1862 {
1863     if (pSection != NULL && !CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
1864     {
1865         TempBuffer buf;
1866         if (pSection->Type == CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE)
1867         {
1868             TypeHandleToString(TypeHandle::FromTAddr((TADDR)fixup), buf);
1869         }
1870         else
1871         if (pSection->Type == CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE)
1872         {
1873             MethodDescToString(PTR_MethodDesc((TADDR)fixup), buf);
1874         }
1875         else
1876         {
1877             _ASSERTE(!"Unknown Type");
1878             IfFailThrow(E_FAIL);
1879         }
1880         m_display->WriteElementStringW( "FixupTargetName", (const WCHAR*)buf );
1881         return;
1882     }
1883
1884     RVA rva = CORCOMPILE_UNTAG_TOKEN(fixup);
1885
1886     WriteElementsFixupTargetAndName(rva);
1887 }
1888
1889 const NativeImageDumper::EnumMnemonics s_EncodeMethodSigFlags[] =
1890 {
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),
1899 #undef EMS_ENTRY
1900 };
1901
1902 void NativeImageDumper::FixupBlobToString(RVA rva, SString& buf)
1903 {
1904     PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
1905     BYTE kind = *sig++;
1906
1907     CorTokenType tkType = (CorTokenType)0;
1908
1909     IMetaDataImport2 * pImport = m_import;
1910
1911     if (kind & ENCODE_MODULE_OVERRIDE)
1912     {
1913         Import *import = OpenImport(DacSigUncompressData(sig));
1914         kind &= ~ENCODE_MODULE_OVERRIDE;
1915
1916         Dependency *pDep = import->dependency;
1917         if (pDep == NULL)
1918         {
1919             return;
1920         }
1921
1922         pImport = pDep->pImport;
1923
1924         _ASSERTE(pImport != NULL);
1925
1926         // print assembly/module info
1927
1928         mdToken realRef =
1929             MapAssemblyRefToManifest(TokenFromRid(import->index,
1930                                                     mdtAssemblyRef),
1931                                         m_assemblyImport);
1932         AppendToken(realRef, buf, m_manifestImport);
1933         buf.Append( W(" ") );
1934     }
1935
1936     // print further info
1937
1938     mdToken token;
1939
1940     switch (kind)
1941     {
1942     case ENCODE_MODULE_HANDLE:
1943         // No further info
1944         break;
1945
1946     case ENCODE_TYPE_HANDLE:
1947     EncodeType:
1948         if (pImport != NULL)
1949             TypeToString(sig, buf, pImport);
1950         else
1951             buf.Append( W("<unresolved type> ") );
1952
1953         break;
1954
1955     case ENCODE_METHOD_HANDLE:
1956     EncodeMethod:
1957         {
1958             //Flags are first
1959             DWORD methodFlags = DacSigUncompressData(sig);
1960
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.
1965             //
1966             IMetaDataImport2 * pMethodImport = pImport;
1967             if (pImport != NULL)
1968             {
1969                 if (methodFlags & ENCODE_METHOD_SIG_OwnerType)
1970                 {
1971                     pMethodImport = TypeToString(sig, buf, pImport);
1972                 }
1973             }
1974             else
1975             {
1976                 buf.Append( W("<unresolved method signature>") );
1977                 break;
1978             }   
1979
1980             //If we have SlotInsteadOfToken set then this is a slot number (i.e. for an array)
1981             if( methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken )
1982             {
1983                 buf.AppendPrintf( W(" method slot %d"), DacSigUncompressData(sig) );
1984             }
1985             else
1986             {
1987                 // decode the methodToken (a rid is encoded)
1988                 RID rid = DacSigUncompressData(sig);
1989                
1990                 mdMethodDef methodToken = ((methodFlags & ENCODE_METHOD_SIG_MemberRefToken) ? mdtMemberRef : mdtMethodDef) | rid;
1991
1992                 buf.Append( W(" ") );
1993
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
1997
1998                 TempBuffer tempName;
1999
2000                 AppendTokenName( methodToken, tempName, pMethodImport );
2001
2002                 if( methodFlags & ENCODE_METHOD_SIG_MethodInstantiation )
2003                 {
2004                     //for each generic arg, there is a type handle.
2005                     ULONG numParams = DacSigUncompressData(sig);
2006
2007                     tempName.Append( W("<") );
2008                     for( unsigned i = 0;i < numParams; ++i )
2009                     {
2010                         if( i != 0 )
2011                             tempName.Append( W(", ") );
2012
2013                         // switch back to using pImport to resolve tokens
2014                         TypeToString(sig, tempName, pImport);
2015                     }
2016                     tempName.Append( W(">") );
2017                 }
2018
2019                 PCCOR_SIGNATURE pvSigBlob;
2020                 ULONG cbSigBlob;
2021
2022                 if (methodFlags & ENCODE_METHOD_SIG_MemberRefToken)
2023                 {
2024                     IfFailThrow(pMethodImport->GetMemberRefProps(methodToken,
2025                         NULL,
2026                         NULL,
2027                         0,
2028                         NULL,
2029                         &pvSigBlob,
2030                         &cbSigBlob));
2031                 }
2032                 else
2033                 {
2034                     IfFailThrow(pMethodImport->GetMethodProps(methodToken,
2035                         NULL,
2036                         NULL,
2037                         0,
2038                         NULL,
2039                         NULL,
2040                         &pvSigBlob,
2041                         &cbSigBlob,
2042                         NULL,
2043                         NULL));
2044                 }
2045
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);
2055             }
2056
2057             buf.Append( W(" flags=(") );
2058             EnumFlagsToString( methodFlags, s_EncodeMethodSigFlags, _countof(s_EncodeMethodSigFlags),
2059                                W(", "), buf );
2060             buf.Append( W(")") );
2061         }
2062         break;
2063
2064     case ENCODE_FIELD_HANDLE:
2065     EncodeField:
2066         {
2067             //Flags are first
2068             DWORD fieldFlags = DacSigUncompressData(sig);
2069
2070             IMetaDataImport2 * pFieldImport = pImport;
2071             if (pImport != NULL)
2072             {
2073                 if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
2074                 {
2075                     pFieldImport = TypeToString(sig, buf, pImport);
2076                 }
2077             }
2078             else
2079                 buf.Append( W("<unresolved type>") );
2080
2081             if (fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken)
2082             {
2083                 buf.AppendPrintf( W(" field index %d"), DacSigUncompressData(sig) );
2084             }
2085             else
2086             {
2087                 // decode the methodToken (a rid is encoded)
2088                 RID rid = DacSigUncompressData(sig);
2089                
2090                 mdMethodDef fieldToken = ((fieldFlags & ENCODE_FIELD_SIG_MemberRefToken) ? mdtMemberRef : mdtFieldDef) | rid;
2091
2092                 buf.Append( W(" ") );
2093
2094                 AppendTokenName( fieldToken, buf, pFieldImport );
2095             }
2096         }
2097         break;
2098
2099     case ENCODE_STRING_HANDLE:
2100         token = TokenFromRid(DacSigUncompressData(sig), mdtString);
2101         if (pImport != NULL)
2102             AppendToken(token, buf, pImport);
2103         else
2104             buf.AppendPrintf( W("<unresolved token %d>"), token );
2105         break;
2106
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;
2116 DataToTokenCore:
2117         token = TokenFromRid(DacSigUncompressData(sig), tkType);
2118         if (pImport != NULL)
2119             AppendToken(token, buf, pImport);
2120         else
2121             buf.AppendPrintf( "<unresolved token %d>", token );
2122         break;
2123
2124     case ENCODE_METHOD_ENTRY:
2125         buf.Append( W("Entrypoint for ") );
2126         goto EncodeMethod;
2127
2128     case ENCODE_METHOD_ENTRY_DEF_TOKEN:
2129         {
2130             buf.Append( W("Entrypoint for ") );
2131             token = TokenFromRid(DacSigUncompressData(sig), mdtMethodDef);
2132             AppendTokenName(token, buf, pImport);
2133         }
2134         break;
2135
2136     case ENCODE_METHOD_ENTRY_REF_TOKEN:
2137         {
2138             buf.Append( W("Entrypoint for ref ") );
2139             token = TokenFromRid(DacSigUncompressData(sig), mdtMemberRef);
2140             AppendTokenName(token, buf, pImport);
2141         }
2142         break;
2143
2144     case ENCODE_VIRTUAL_ENTRY:
2145         buf.Append( W("Entrypoint for ") );
2146         goto EncodeMethod;
2147
2148     case ENCODE_VIRTUAL_ENTRY_DEF_TOKEN:
2149         {
2150             buf.Append( W("Virtual call for ") );
2151             token = TokenFromRid(DacSigUncompressData(sig), mdtMethodDef);
2152             AppendTokenName(token, buf, pImport);
2153         }
2154         break;
2155
2156     case ENCODE_VIRTUAL_ENTRY_REF_TOKEN:
2157         {
2158             buf.Append( W("Virtual call for ref ") );
2159             token = TokenFromRid(DacSigUncompressData(sig), mdtMemberRef);
2160             AppendTokenName(token, buf, pImport);
2161         }
2162         break;
2163
2164     case ENCODE_VIRTUAL_ENTRY_SLOT:
2165         {
2166             buf.Append( W("Virtual call for ") );
2167             int slot = DacSigUncompressData(sig);
2168             buf.AppendPrintf( W("slot %d "), slot );
2169             goto EncodeType;
2170         }
2171
2172     case ENCODE_MODULE_ID_FOR_STATICS:
2173         buf.Append( W("Module For Statics") );
2174         // No further info
2175         break;
2176
2177     case ENCODE_MODULE_ID_FOR_GENERIC_STATICS:
2178         buf.Append( W("Module For Statics for ") );
2179         goto EncodeType;
2180
2181     case ENCODE_CLASS_ID_FOR_STATICS:
2182         buf.Append( W("Statics ID for ") );
2183         goto EncodeType;
2184
2185     case ENCODE_STATIC_FIELD_ADDRESS:
2186         buf.Append( W("Static field address for ") );
2187         goto EncodeField;
2188
2189     case ENCODE_SYNC_LOCK:
2190         buf.Append( W("Synchronization handle for ") );
2191         break;
2192
2193     case ENCODE_INDIRECT_PINVOKE_TARGET:
2194         buf.Append( W("Indirect P/Invoke target for ") );
2195         break;
2196
2197     case ENCODE_PROFILING_HANDLE:
2198         buf.Append( W("Profiling handle for ") );
2199         goto EncodeMethod;
2200
2201     case ENCODE_ACTIVE_DEPENDENCY:
2202         {
2203             buf.Append( W("Active dependency for  ") );
2204
2205             int targetModuleIndex = DacSigUncompressData(sig);
2206             Import *targetImport = OpenImport(targetModuleIndex);
2207
2208             mdToken realRef =
2209                 MapAssemblyRefToManifest(TokenFromRid(targetImport->index,
2210                                                         mdtAssemblyRef),
2211                                             m_assemblyImport);
2212             AppendToken(realRef, buf, m_manifestImport);
2213             buf.Append( W(" ") );
2214         }
2215         break;
2216
2217     default:
2218         buf.Append( W("Unknown fixup kind") );
2219         _ASSERTE(!"Unknown fixup kind");
2220     }
2221 }
2222
2223 void NativeImageDumper::WriteElementsFixupTargetAndName(RVA rva)
2224 {
2225     if( rva == NULL )
2226     {
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.
2230          */
2231         m_display->WriteElementPointer( "FixupTargetValue", NULL );
2232         m_display->WriteElementStringW( "FixupTargetName", W("NULL") );
2233         return;
2234     }
2235
2236     m_display->WriteElementPointer( "FixupTargetValue", RvaToDisplay(rva) );
2237
2238     TempBuffer buf;
2239     FixupBlobToString(rva, buf);
2240
2241     m_display->WriteElementStringW( "FixupTargetName", (const WCHAR*)buf );
2242 }
2243  
2244 NativeImageDumper::Dependency * NativeImageDumper::GetDependency(mdAssemblyRef token, IMetaDataAssemblyImport *pImport)
2245 {
2246     if (RidFromToken(token) == 0)
2247         return OpenDependency(0);
2248
2249     if (pImport == NULL)
2250         pImport = m_assemblyImport;
2251
2252     // Need to map from IL token to manifest token
2253     mdAssemblyRef manifestToken = MapAssemblyRefToManifest(token, pImport);
2254
2255     if( manifestToken == mdAssemblyNil )
2256     {
2257         //this is "self"
2258         return OpenDependency(0);
2259     }
2260
2261     COUNT_T count;
2262     PTR_CORCOMPILE_DEPENDENCY deps(TO_TADDR(m_decoder.GetNativeDependencies(&count)));
2263
2264     for (COUNT_T i = 0; i < count; i++)
2265     {
2266         if (deps[i].dwAssemblyRef == manifestToken)
2267             return OpenDependency(i+1);
2268     }
2269
2270     TempBuffer buf;
2271     AppendTokenName(manifestToken, buf, m_manifestImport);
2272     m_display->ErrorPrintF("Error: unlisted assembly dependency %S\n", (const WCHAR*)buf);
2273
2274     return NULL;
2275 }
2276
2277 mdAssemblyRef NativeImageDumper::MapAssemblyRefToManifest(mdAssemblyRef token, IMetaDataAssemblyImport *pAssemblyImport)
2278 {
2279     // Reference may be to self
2280     if (TypeFromToken(token) == mdtAssembly)
2281         return token;
2282
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
2286      * exactly thes same
2287      */
2288     //count the assembly refs.
2289     ULONG count = 0;
2290
2291     HCORENUM iter = NULL;
2292     for (;;)
2293     {
2294         ULONG tokens = 0;
2295         mdAssemblyRef tmp;
2296         IfFailThrow(pAssemblyImport->EnumAssemblyRefs(&iter, &tmp, 1,
2297                                                       &tokens));
2298         if (tokens == 0)
2299             break;
2300         count ++;
2301     }
2302     pAssemblyImport->CloseEnum(iter);
2303
2304     if( RidFromToken(token) > count )
2305     {
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
2308         //token.
2309         return token - (count + 1);
2310     }
2311
2312     ULONG cchName;
2313     ASSEMBLYMETADATA metadata;
2314
2315     ZeroMemory(&metadata, sizeof(metadata));
2316
2317     IfFailThrow(pAssemblyImport->GetAssemblyRefProps(token, NULL, NULL,
2318                                                      NULL, 0, &cchName,
2319                                                      &metadata, NULL, NULL,
2320                                                      NULL));
2321
2322     LPWSTR szAssemblyName           = NULL;
2323
2324     if (cchName > 0)
2325         szAssemblyName = (LPWSTR) _alloca(cchName * sizeof(WCHAR));
2326
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));
2333
2334     const void *pbPublicKey;
2335     ULONG cbPublicKey;
2336     DWORD flags;
2337     const void *pbHashValue;
2338     ULONG cbHashValue;
2339
2340
2341     IfFailThrow(pAssemblyImport->GetAssemblyRefProps(token, &pbPublicKey, &cbPublicKey, 
2342                                                      szAssemblyName, cchName, NULL,
2343                                                      &metadata, &pbHashValue, &cbHashValue,
2344                                                      &flags));
2345
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.
2348     //
2349     //Also, sometimes we find "self" in these searches.  If so, return mdAssemblyDefNil as a canary value.
2350
2351     if( !wcscmp(szAssemblyName, m_name) )
2352     {
2353         //we need "self".
2354         return mdAssemblyNil;
2355     }
2356     
2357     mdAssemblyRef ret = mdAssemblyRefNil;
2358     /*HCORENUM*/ iter = NULL;
2359     for(;;)
2360     {
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;
2365         //ULONG count;
2366         IfFailThrow(m_manifestAssemblyImport->EnumAssemblyRefs(&iter, &currentRef, 1, &count));
2367         if( 0 == count )
2368             break;
2369
2370         //get the information about the assembly ref and compare.
2371         const void * publicKeyToken;
2372         ULONG pktSize = 0;
2373         WCHAR name[128];
2374         /*ULONG*/ cchName = _countof(name);
2375         ASSEMBLYMETADATA curMD = {0};
2376
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) )
2382         {
2383             if( cbPublicKey == pktSize && !memcmp(pbPublicKey, publicKeyToken, pktSize)
2384                 && curMD.usMajorVersion == metadata.usMajorVersion
2385                 && curMD.usMinorVersion == metadata.usMinorVersion)
2386             {
2387                 ret = currentRef;
2388                 break;
2389             }
2390             else if (wcscmp(szAssemblyName, CoreLibName_W) == 0)
2391             {
2392                 // Mscorlib is special - version number and public key token are ignored.
2393                 ret = currentRef;
2394                 break;
2395             }
2396             else if (metadata.usMajorVersion == 255 &&
2397                      metadata.usMinorVersion == 255 &&
2398                      metadata.usBuildNumber == 255 &&
2399                      metadata.usRevisionNumber == 255)
2400             {
2401                 // WinMDs encode all assemblyrefs with version 255.255.255.255 including CLR assembly dependencies (mscorlib, System).
2402                 ret = currentRef;
2403             }
2404             else
2405             {
2406                 //there was an assembly with the correct name, but with the wrong version number.  Let the
2407                 //user know.
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);
2409                 // TritonTODO: why?
2410                 ret = currentRef;
2411                 break;
2412             }
2413
2414         }
2415     }
2416     pAssemblyImport->CloseEnum(iter);
2417     if( ret == mdAssemblyRefNil )
2418     {
2419         TempBuffer pkt;
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");
2423     }
2424
2425     return ret;
2426 }
2427
2428 NativeImageDumper::Import * NativeImageDumper::OpenImport(int i)
2429 {
2430     if (m_imports == NULL)
2431     {
2432         COUNT_T count;
2433         m_decoder.GetNativeDependencies(&count);
2434         m_numImports = count;
2435         m_imports = new Import [count];
2436         ZeroMemory(m_imports, count * sizeof(m_imports[0]));
2437     }
2438
2439     if (m_imports[i].index == 0)
2440     {
2441         //GetNativeImportFromIndex returns a host pointer.
2442         m_imports[i].index = i;
2443
2444         /*
2445         mdToken tok = TokenFromRid(entry->index, mdtAssemblyRef);
2446         Dependency * dependency = GetDependency( MapAssemblyRefToManifest(tok, 
2447         */
2448         Dependency *dependency = GetDependency(TokenFromRid(i, mdtAssemblyRef));
2449         m_imports[i].dependency = dependency;
2450         _ASSERTE(dependency); //Why can this be null?
2451
2452     }
2453
2454     return &m_imports[i];
2455 }
2456
2457
2458 const NativeImageDumper::Dependency *NativeImageDumper::GetDependencyForFixup(RVA rva)
2459 {
2460     PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
2461     if (*sig++ & ENCODE_MODULE_OVERRIDE)
2462     {
2463         unsigned idx = DacSigUncompressData(sig);
2464
2465         _ASSERTE(idx >= 0 && idx < m_numImports);
2466         return OpenImport(idx)->dependency;
2467     }
2468
2469     return &m_dependencies[0];
2470 }
2471
2472
2473 void NativeImageDumper::AppendToken(mdToken token, SString& buf)
2474 {
2475     return NativeImageDumper::AppendToken(token, buf, NULL);
2476 }
2477 void NativeImageDumper::AppendToken(mdToken token, SString& buf,
2478                                     IMetaDataImport2 *pImport)
2479 {
2480     IF_OPT(DISABLE_NAMES)
2481     {
2482         buf.Append( W("Disabled") );
2483         return;
2484     }
2485     switch (TypeFromToken(token))
2486     {
2487     case mdtTypeDef:
2488         buf.Append( W("TypeDef ") );
2489         break;
2490
2491     case mdtTypeRef:
2492         buf.Append( W("TypeRef ") );
2493         break;
2494
2495     case mdtTypeSpec:
2496         buf.Append( W("TypeRef ") );
2497         break;
2498
2499     case mdtFieldDef:
2500         buf.Append( W("FieldDef "));
2501         break;
2502
2503     case mdtMethodDef:
2504         buf.Append( W("MethodDef ") );
2505         break;
2506
2507     case mdtMemberRef:
2508         buf.Append( W("MemberRef ") );
2509         break;
2510
2511     case mdtAssemblyRef:
2512         buf.Append( W("AssemblyRef ") );
2513         break;
2514
2515     case mdtFile:
2516         buf.Append( W("File ") );
2517         break;
2518
2519     case mdtString:
2520         buf.Append( W("String ") );
2521         break;
2522
2523     case mdtSignature:
2524         buf.Append( W("Signature ") );
2525         break;
2526
2527     }
2528     if( RidFromToken(token) == mdTokenNil )
2529         buf.Append( W("Nil") );
2530     else
2531         AppendTokenName(token, buf, pImport);
2532 }
2533
2534 NativeImageDumper::Dependency *NativeImageDumper::OpenDependency(int index)
2535 {
2536     CORCOMPILE_VERSION_INFO *info = m_decoder.GetNativeVersionInfo();
2537
2538     if (m_dependencies == NULL)
2539     {
2540         COUNT_T count;
2541         m_decoder.GetNativeDependencies(&count);
2542
2543         // Add one for self
2544         count++;
2545
2546         m_numDependencies = count;
2547         m_dependencies = new Dependency [count];
2548         ZeroMemory(m_dependencies, count * sizeof (Dependency));
2549     }
2550
2551     if (m_dependencies[index].entry == NULL)
2552     {
2553         CORCOMPILE_DEPENDENCY *entry;
2554
2555         if (index == 0)
2556         {
2557             //  Make dummy entry for self
2558             entry = &m_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 );
2584         }
2585         else
2586         {
2587             COUNT_T numDeps;
2588             PTR_CORCOMPILE_DEPENDENCY deps(TO_TADDR(m_decoder.GetNativeDependencies(&numDeps)));
2589
2590             entry = deps + (index-1);
2591
2592             //load the dependency, get the pointer, and use the PEDecoder
2593             //to open the metadata.
2594
2595             TempBuffer buf;
2596             TADDR loadedBase;
2597             /* REVISIT_TODO Tue 11/22/2005
2598              * Is this the right name?
2599              */
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),
2607                      (const WCHAR*)buf);
2608             if( isHardBound )
2609             {
2610                 IfFailThrow(m_librarySupport->LoadHardboundDependency((const WCHAR*)buf,
2611                                                                       entry->signNativeImage, &loadedBase));
2612
2613                 dependency.pLoadedAddress = loadedBase;
2614             }
2615             else
2616             {
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));
2621
2622
2623                 HRESULT hr =
2624                     m_librarySupport->LoadSoftboundDependency((const WCHAR*)buf,
2625                                                               (const BYTE*)&asmData, (const BYTE*)hashValue, hashLength,
2626                                                               &loadedBase);
2627                 if( FAILED(hr) )
2628                 {
2629                     TempBuffer pkt;
2630                     if( hashLength > 0 )
2631                     {
2632                         appendByteArray(pkt, (BYTE*)hashValue, hashLength);
2633                     }
2634                     else
2635                     {
2636                         pkt.Set( W("<No Hash>") );
2637                     }
2638                     //try to continue without loading this softbound
2639                     //dependency.
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];
2645
2646                 }
2647                 //save this off to the side so OpenImport can find the metadata.
2648                 m_dependencies[index].pLoadedAddress = loadedBase;
2649             }
2650             /* REVISIT_TODO Wed 11/23/2005
2651              * Refactor this with OpenMetadata from above.
2652              */
2653             //now load the metadata from the new image.
2654             PEDecoder decoder(dac_cast<PTR_VOID>(loadedBase));
2655             if( isHardBound )
2656             {
2657                 dependency.pPreferredBase =
2658                     TO_TADDR(decoder.GetNativePreferredBase());
2659                 dependency.size = decoder.Has32BitNTHeaders() ? 
2660                     decoder.GetNTHeaders32()->OptionalHeader.SizeOfImage :
2661                     decoder.GetNTHeaders64()->OptionalHeader.SizeOfImage;
2662             }
2663             ReleaseHolder<IMetaDataDispenserEx> pDispenser;
2664             IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
2665                                              IID_IMetaDataDispenserEx,
2666                                              (void **) &pDispenser));
2667
2668             VARIANT opt;
2669             IfFailThrow(pDispenser->GetOption(MetaDataCheckDuplicatesFor,
2670                                               &opt));
2671             V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile;
2672             IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor,
2673                                               &opt));
2674             if( decoder.HasNativeHeader() )
2675             {
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 );
2684             }
2685             else
2686             {
2687                 dependency.pModule = NULL;
2688             }
2689
2690             const void * data;
2691             COUNT_T size;
2692
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)));
2695
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,
2701                                                       ofRead, 
2702                                                       IID_IMetaDataImport2,
2703                                                       (IUnknown **) &dependency.pImport));
2704             dependency.fIsMscorlib = isMscorlib;
2705         }
2706
2707         m_dependencies[index].entry = entry;
2708
2709     }
2710
2711     return &m_dependencies[index];
2712 }
2713
2714 IMetaDataImport2* NativeImageDumper::TypeToString(PTR_CCOR_SIGNATURE &sig, SString& buf)
2715 {
2716     return TypeToString(sig, buf, NULL);
2717 }
2718 #if 0
2719 void NativeImageDumper::TypeToString(PTR_CCOR_SIGNATURE &sig,
2720                                   IMetaDataImport2 *pImport)
2721 {
2722     CQuickBytes tmp;
2723
2724     if (pImport == NULL)
2725         pImport = m_import;
2726
2727     LPCWSTR type = PrettyPrintSig( sig, INT_MAX, W(""), &tmp, pImport );
2728     _ASSERTE(type);
2729     m_display->ErrorPrintF( "%S", type );
2730 }
2731 #endif
2732
2733 IMetaDataImport2 * NativeImageDumper::TypeToString(PTR_CCOR_SIGNATURE &sig,
2734                                                    SString& buf, 
2735                                                    IMetaDataImport2 *pImport,
2736                                                    IMetaDataImport2 *pOrigImport /* =NULL */)
2737                                                    
2738 {
2739     IF_OPT(DISABLE_NAMES)
2740     {
2741         buf.Append( W("Disabled") );
2742         return pImport;
2743     }
2744
2745     if (pImport == NULL)
2746         pImport = m_import;
2747     if (pOrigImport == NULL)
2748         pOrigImport = pImport;
2749
2750     IMetaDataImport2 * pRet = pImport;
2751 #define TYPEINFO(enumName, classSpace, className, size, gcType, isArray, isPrim, isFloat, isModifier, isGenVar) \
2752      className,
2753     static const char *elementNames[] = {
2754 #include "cortypeinfo.h"
2755     };
2756 #undef TYPEINFO
2757
2758     CorElementType type = DacSigUncompressElementType(sig);
2759
2760     if (type == (CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG)
2761     {
2762         unsigned idx = DacSigUncompressData(sig);
2763         buf.AppendPrintf( W("module %d "), idx );
2764         //switch module
2765         const Import * import = OpenImport(idx);
2766         pImport = import->dependency->pImport;
2767
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.
2771         pRet = pImport;
2772
2773         type = DacSigUncompressElementType(sig);
2774     }
2775     if (type >= 0 && (size_t)type < _countof(elementNames)
2776              && elementNames[type] != NULL)
2777     {
2778         buf.AppendPrintf( "%s", elementNames[type] );
2779     }
2780     else switch ((DWORD)type)
2781     {
2782     case ELEMENT_TYPE_CANON_ZAPSIG:
2783         buf.Append( W("System.__Canon") );
2784         break;
2785
2786     case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
2787     case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
2788         {
2789             buf.Append( W("native ") );
2790             TypeToString(sig, buf, pImport);
2791         }
2792         break;
2793
2794     case ELEMENT_TYPE_VALUETYPE:
2795     case ELEMENT_TYPE_CLASS:
2796         {
2797             if (type == ELEMENT_TYPE_VALUETYPE)
2798                 buf.Append( W("struct ") );
2799
2800             mdToken token = DacSigUncompressToken(sig);
2801             AppendTokenName(token, buf, pImport);
2802         }
2803         break;  
2804
2805     case ELEMENT_TYPE_SZARRAY:   
2806         TypeToString(sig, buf, pImport);
2807         buf.Append( W("[]") );
2808         break;
2809
2810     case ELEMENT_TYPE_ARRAY:
2811         {
2812             TypeToString(sig, buf, pImport, pOrigImport);
2813             unsigned rank = DacSigUncompressData(sig);
2814             if (rank == 0)
2815                 buf.Append( W("[??]") );
2816             else 
2817             {
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); 
2824                 
2825                 unsigned numSizes = DacSigUncompressData(sig);
2826                 _ASSERTE(numSizes <= rank);
2827                 unsigned int i;
2828                 for(i =0; i < numSizes; i++)
2829                     sizes[i] = DacSigUncompressData(sig);   
2830                 
2831                 unsigned numLowBounds = DacSigUncompressData(sig);  
2832                 _ASSERTE(numLowBounds <= rank); 
2833                 for(i = 0; i < numLowBounds; i++)   
2834                     lowerBounds[i] = DacSigUncompressData(sig); 
2835                 
2836                 buf.Append(W("["));
2837                 for(i = 0; i < rank; i++)   
2838                 {   
2839                     if (sizes[i] != 0 && lowerBounds[i] != 0)   
2840                     {   
2841                         if (lowerBounds[i] == 0)    
2842                             buf.AppendPrintf( W("%s"), sizes[i] );
2843                         else    
2844                         {   
2845                             buf.AppendPrintf( W("%d ..."), lowerBounds[i] );
2846                             if (sizes[i] != 0)  
2847                                 buf.AppendPrintf( W("%d"),
2848                                                   lowerBounds[i] + sizes[i]
2849                                                   + 1 );
2850                         }   
2851                     }   
2852                     if (i < rank-1) 
2853                         buf.Append( W(",") );
2854                 }   
2855                 buf.Append( W("]") );
2856             }
2857         }
2858         break;
2859
2860     case ELEMENT_TYPE_MVAR:
2861         buf.Append( W("!") );
2862         // fall through
2863     case ELEMENT_TYPE_VAR:   
2864         buf.AppendPrintf( W("!%d"), DacSigUncompressData(sig));
2865         break;
2866
2867     case ELEMENT_TYPE_VAR_ZAPSIG:
2868         {
2869             buf.Append( W("var ") );
2870
2871             mdToken token = TokenFromRid(DacSigUncompressData(sig), mdtGenericParam);
2872             AppendTokenName(token, buf, pImport);
2873         }
2874         break;
2875
2876     case ELEMENT_TYPE_GENERICINST:
2877         {
2878             TypeToString(sig, buf, pImport, pOrigImport);
2879             unsigned ntypars = DacSigUncompressData(sig);
2880             buf.Append( W("<") );
2881             for (unsigned i = 0; i < ntypars; i++)
2882             {
2883                 if (i > 0) 
2884                     buf.Append( W(",") );
2885                 // switch pImport back to our original Metadata importer
2886                 TypeToString(sig, buf, pOrigImport, pOrigImport);
2887             }
2888             buf.Append( W(">") );
2889         }
2890         break;
2891                
2892     case ELEMENT_TYPE_FNPTR:
2893         buf.Append( W("(fnptr)") );
2894         break;
2895     
2896         // Modifiers or depedant types  
2897     case ELEMENT_TYPE_PINNED:
2898         TypeToString(sig, buf, pImport, pOrigImport);
2899         buf.Append( W(" pinned") );
2900         break;
2901
2902     case ELEMENT_TYPE_PTR:
2903         TypeToString(sig, buf, pImport, pOrigImport);
2904         buf.Append( W("*") );
2905         break;
2906
2907     case ELEMENT_TYPE_BYREF:
2908         TypeToString(sig, buf, pImport, pOrigImport);
2909         buf.Append( W("&") );
2910         break;
2911
2912     case ELEMENT_TYPE_SENTINEL:
2913     case ELEMENT_TYPE_END:
2914     default:
2915         _ASSERTE(!"Unknown Type");  
2916         IfFailThrow(E_FAIL);
2917         break;  
2918     }   
2919     return pRet;
2920 }
2921
2922 void NativeImageDumper::DumpMethods(PTR_Module module)
2923 {
2924     COUNT_T hotCodeSize;
2925     PCODE hotCode = m_decoder.GetNativeHotCode(&hotCodeSize);
2926
2927
2928     COUNT_T codeSize;
2929     PCODE code = m_decoder.GetNativeCode(&codeSize);
2930
2931     COUNT_T coldCodeSize;
2932     PCODE coldCode = m_decoder.GetNativeColdCode(&coldCodeSize);
2933
2934     DisplayStartCategory( "Code", METHODS );
2935     DisplayWriteElementAddress( "HotCode", DataPtrToDisplay(hotCode),
2936                                 hotCodeSize, METHODS );
2937
2938     DisplayWriteElementAddress( "UnprofiledCode",
2939                                 DataPtrToDisplay(code),
2940                                 codeSize, METHODS );
2941     DisplayWriteElementAddress( "ColdCode",
2942                                 DataPtrToDisplay(coldCode),
2943                                 coldCodeSize, METHODS );
2944
2945     PTR_CORCOMPILE_CODE_MANAGER_ENTRY codeEntry(m_decoder.GetNativeCodeManagerTable());
2946
2947     DisplayWriteElementAddress( "ROData",
2948                                 RvaToDisplay(codeEntry->ROData.VirtualAddress),
2949                                 codeEntry->ROData.Size, METHODS );
2950
2951     DisplayWriteElementAddress( "HotCommonCode",
2952                                 DataPtrToDisplay(hotCode),
2953                                 codeEntry->HotIBCMethodOffset, METHODS );
2954
2955     DisplayWriteElementAddress( "HotIBCMethodCode",
2956                                 DataPtrToDisplay(hotCode
2957                                     + codeEntry->HotIBCMethodOffset),
2958                                 codeEntry->HotGenericsMethodOffset
2959                                     - codeEntry->HotIBCMethodOffset,
2960                                 METHODS );
2961
2962     DisplayWriteElementAddress( "HotGenericsMethodCode",
2963                                 DataPtrToDisplay(hotCode
2964                                     + codeEntry->HotGenericsMethodOffset),
2965                                 hotCodeSize - codeEntry->HotGenericsMethodOffset,
2966                                 METHODS );
2967
2968     DisplayWriteElementAddress( "ColdIBCMethodCode",
2969                                 DataPtrToDisplay(coldCode),
2970                                 codeEntry->ColdUntrainedMethodOffset,
2971                                 METHODS );
2972
2973     MethodIterator mi(module, &m_decoder);
2974
2975     DisplayStartArray( "Methods", NULL, METHODS );
2976
2977     while( mi.Next() )
2978     {
2979         DumpCompleteMethod( module, mi );
2980     }
2981
2982     DisplayEndArray( "Total Methods", METHODS ); //Methods
2983
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.
2988      */
2989     CoverageRead( hotCode, hotCodeSize );
2990     CoverageRead( coldCode, coldCodeSize );
2991 #ifdef USE_CORCOMPILE_HEADER
2992     CoverageRead( hotCodeTable, hotCodeTableSize );
2993     CoverageRead( coldCodeTable, coldCodeTableSize );
2994 #endif 
2995
2996     DisplayEndCategory( METHODS ); //Code
2997
2998     //m_display->StartCategory( "Methods" );
2999 }
3000
3001 static SString g_holdStringOutData;
3002
3003 static void stringOut( const char* fmt, ... )
3004 {
3005     va_list args;
3006     va_start(args, fmt);
3007     g_holdStringOutData.AppendVPrintf(fmt, args);
3008     va_end(args);
3009 }
3010
3011 static void nullStringOut( const char * fmt, ... ) { }
3012
3013 const NativeImageDumper::EnumMnemonics s_CorExceptionFlags[] =
3014 {
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")),
3021 #undef CEF_ENTRY
3022 };
3023
3024 void NativeImageDumper::DumpCompleteMethod(PTR_Module module, MethodIterator& mi)
3025 {
3026     PTR_MethodDesc md = mi.GetMethodDesc();
3027
3028 #ifdef WIN64EXCEPTIONS
3029     PTR_RUNTIME_FUNCTION pRuntimeFunction = mi.GetRuntimeFunction();
3030 #endif 
3031
3032     //Read the GCInfo to get the total method size.
3033     unsigned methodSize = 0;
3034     unsigned gcInfoSize = UINT_MAX;
3035
3036     //parse GCInfo for size information.
3037     GCInfoToken gcInfoToken = mi.GetGCInfoToken();
3038     PTR_CBYTE gcInfo = dac_cast<PTR_CBYTE>(gcInfoToken.Info);
3039
3040     void (* stringOutFn)(const char *, ...);
3041     IF_OPT(GC_INFO)
3042     {
3043         stringOutFn = stringOut;
3044     }
3045     else
3046     {
3047         stringOutFn = nullStringOut;
3048     }
3049     if (gcInfo != NULL)
3050     {
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();
3058 #endif
3059
3060         //dump the data to a string first so we can get the gcinfo size.
3061 #ifdef _TARGET_X86_
3062         InfoHdr hdr;
3063         stringOutFn( "method info Block:\n" );
3064         curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0);
3065         stringOutFn( "\n" );
3066 #endif
3067
3068         IF_OPT(METHODS)
3069         {
3070 #ifdef _TARGET_X86_
3071             stringOutFn( "PointerTable:\n" );
3072             curGCInfoPtr += gcDump.DumpGCTable( curGCInfoPtr,
3073                                                 hdr,
3074                                                 methodSize, 0);
3075             gcInfoSize = curGCInfoPtr - gcInfo;
3076 #elif defined(USE_GC_INFO_DECODER)
3077             stringOutFn( "PointerTable:\n" );
3078             curGCInfoPtr += gcDump.DumpGCTable( curGCInfoPtr,
3079                                                 methodSize, 0);
3080             gcInfoSize = (unsigned)(curGCInfoPtr - gcInfo);
3081 #endif
3082         }
3083
3084         //data is output below.
3085     }
3086
3087     TADDR hotCodePtr = mi.GetMethodStartAddress();
3088     TADDR coldCodePtr = mi.GetMethodColdStartAddress();
3089
3090     size_t hotCodeSize = methodSize;
3091     size_t coldCodeSize = 0;
3092
3093     if (coldCodePtr != NULL)
3094     {
3095         hotCodeSize = mi.GetHotCodeSize();
3096         coldCodeSize = methodSize - hotCodeSize;
3097     }
3098
3099     _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(md)));
3100     const Dependency* mdDep = GetDependencyFromMD(md);
3101     TempBuffer buffer;
3102     _ASSERTE(mdDep->pImport);
3103     MethodDescToString(md, buffer);
3104
3105     DisplayStartElement( "Method", METHODS );
3106     DisplayWriteElementStringW( "Name", (const WCHAR *)buffer, METHODS );
3107
3108     /* REVISIT_TODO Mon 10/24/2005
3109      * Do I have to annotate this?
3110      */
3111     DisplayWriteElementPointer("m_methodDesc",
3112                             DPtrToPreferredAddr(md),
3113                             METHODS);
3114
3115     DisplayStartStructure( "m_gcInfo", 
3116                            DPtrToPreferredAddr(gcInfo),
3117                            gcInfoSize,
3118                            METHODS );
3119
3120     DisplayStartTextElement( "Contents", GC_INFO );
3121     DisplayWriteXmlTextBlock( ("%S", (const WCHAR *)g_holdStringOutData), GC_INFO );
3122     DisplayEndTextElement( GC_INFO ); //Contents
3123
3124     DisplayEndStructure( METHODS ); //GCInfo
3125
3126     PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE pExceptionInfoTable (PTR_TO_TADDR(module->GetNGenLayoutInfo()->m_ExceptionInfoLookupTable.StartAddress()));
3127     if (pExceptionInfoTable)
3128     {
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));
3131
3132         COUNT_T ehInfoSize = 0;
3133         DWORD exceptionInfoRVA = NativeExceptionInfoLookupTable::LookupExceptionInfoRVAForMethod(pExceptionInfoTable,
3134                                                                                                                       numLookupEntries,
3135                                                                                                                       methodStartRVA,
3136                                                                                                                       &ehInfoSize);
3137
3138         if( exceptionInfoRVA != 0 )
3139         {
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 )
3145             {
3146                 PTR_CORCOMPILE_EXCEPTION_CLAUSE host = pExceptionInfoArray + i;
3147
3148                 DisplayStartStructure( "Clause", DPtrToPreferredAddr(host), sizeof(PTR_CORCOMPILE_EXCEPTION_CLAUSE), METHODS);
3149                 DisplayWriteFieldEnumerated( Flags, host->Flags,
3150                     EE_ILEXCEPTION_CLAUSE,
3151                     s_CorExceptionFlags, W(", "),
3152                     METHODS );
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,
3161                     host->HandlerEndPC,
3162                     EE_ILEXCEPTION_CLAUSE, METHODS );
3163                 if( host->Flags & COR_ILEXCEPTION_CLAUSE_FILTER )
3164                 {
3165                     DisplayWriteFieldUInt( FilterOffset, host->FilterOffset,
3166                         EE_ILEXCEPTION_CLAUSE, METHODS );
3167                 }
3168                 else if( !(host->Flags & (COR_ILEXCEPTION_CLAUSE_FAULT | COR_ILEXCEPTION_CLAUSE_FINALLY)) )
3169                 {
3170                     WriteFieldMDTokenImport( ClassToken, host->ClassToken,
3171                         EE_ILEXCEPTION_CLAUSE, METHODS,
3172                         mdDep->pImport );
3173                 }
3174                 DisplayEndStructure( METHODS ); //Clause
3175             }
3176             DisplayEndArray("Total EHClauses", METHODS ); // Clauses
3177         }
3178     }
3179
3180     TADDR fixupList = md->GetFixupList();
3181     if (fixupList != NULL)
3182     {
3183         DisplayStartArray( "Fixups", NULL, METHODS );
3184         DumpMethodFixups(module, fixupList);
3185         DisplayEndArray(NULL, METHODS); //Fixups
3186     }
3187
3188     DisplayStartStructure( "Code", DataPtrToDisplay(hotCodePtr), hotCodeSize,
3189                            METHODS );
3190
3191     IF_OPT(DISASSEMBLE_CODE)
3192     {
3193         // Disassemble hot code.  Read the code into the host process.
3194         /* REVISIT_TODO Mon 10/24/2005
3195          * Is this align up right?
3196          */
3197         BYTE * codeStartHost =
3198             reinterpret_cast<BYTE*>(PTR_READ(hotCodePtr,
3199                                              (ULONG32)ALIGN_UP(hotCodeSize,
3200                                                       CODE_SIZE_ALIGN)));
3201         DisassembleMethod( codeStartHost, hotCodeSize );
3202     }
3203     else
3204     {
3205         CoverageRead(hotCodePtr,
3206                      (ULONG32)ALIGN_UP(hotCodeSize, CODE_SIZE_ALIGN));
3207     }
3208
3209     DisplayEndStructure(METHODS); //HotCode 
3210
3211     if( coldCodePtr != NULL )
3212     {
3213         DisplayStartStructure( "ColdCode", DataPtrToDisplay(coldCodePtr),
3214                                coldCodeSize, METHODS );
3215         IF_OPT(DISASSEMBLE_CODE)
3216         {
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,
3221                                                           CODE_SIZE_ALIGN)));
3222             DisassembleMethod( codeStartHost, coldCodeSize );
3223         }
3224         else
3225         {
3226             CoverageRead(coldCodePtr,
3227                          (ULONG32)ALIGN_UP(coldCodeSize, CODE_SIZE_ALIGN));
3228
3229         }
3230         DisplayEndStructure( METHODS ); //ColdCode
3231     }
3232     DisplayEndElement( METHODS ); //Method
3233 }
3234 #undef IDC_SWITCH
3235
3236
3237
3238 void NativeImageDumper::DisassembleMethod(BYTE *code, SIZE_T size)
3239 {
3240     _ASSERTE(CHECK_OPT(DISASSEMBLE_CODE));
3241
3242     m_display->StartTextElement( "NativeCode" );
3243
3244 #ifdef FEATURE_MSDIS
3245
3246     BYTE *codeStart = code;
3247
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.
3255      */
3256     EX_TRY
3257     {
3258         while (code < (codeStart + size))
3259         {
3260             const size_t count = m_dis->CbDisassemble(0, code, size);
3261
3262             if (count == 0)
3263             {
3264                 m_display->WriteXmlText( "%04x\tUnknown instruction (%02x)\n", code-codeStart, *code);
3265                 code++;
3266                 continue;
3267             }
3268
3269             /* XXX Fri 09/16/2005
3270              * PTR_HOST_TO_TADDR doesn't work on interior pointers.
3271              */
3272             m_currentAddress = m_decoder.GetDataRva(PTR_HOST_TO_TADDR(codeStart)
3273                                                     + (code - codeStart))
3274                 + PTR_TO_TADDR(m_decoder.GetBase());
3275
3276             const size_t cinstr = m_dis->Cinstruction();
3277             size_t inum = 0;
3278             while (true)
3279             {
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 );
3284
3285 NEXT_INSTR:
3286                 if (++inum >= cinstr)
3287                     break;
3288
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))
3292                 {
3293                     m_display->WriteXmlText( "%04x\tUnknown instruction within bundle\n", (code-codeStart) + (inum * 4));
3294                     goto NEXT_INSTR;
3295                 }
3296             }
3297
3298             code += count;
3299         }
3300     }
3301     EX_CATCH
3302     {
3303
3304     }
3305     EX_END_CATCH(SwallowAllExceptions);
3306
3307 #else // FEATURE_MSDIS
3308
3309     m_display->WriteXmlText( "Disassembly not supported\n" );
3310
3311 #endif // FEATURE_MSDIS
3312
3313     m_display->EndTextElement(); //NativeCode
3314 }
3315
3316 SIZE_T NativeImageDumper::TranslateAddressCallback(IXCLRDisassemblySupport *dis,
3317                                                    CLRDATA_ADDRESS addr,
3318                                                    __out_ecount(nameSize) WCHAR *name, SIZE_T nameSize,
3319                                                    DWORDLONG *offset)
3320 {
3321     NativeImageDumper *pThis = (NativeImageDumper *) dis->PvClient();
3322
3323     SIZE_T ret = pThis->TranslateSymbol(dis,
3324                                         addr+(SIZE_T)pThis->m_currentAddress,
3325                                         name, nameSize, offset);
3326 #ifdef _DEBUG
3327     if( ret == 0 )
3328     {
3329         _snwprintf_s(name, nameSize, _TRUNCATE, W("@TRANSLATED ADDRESS@ %p"),
3330                      (TADDR)(addr + (SIZE_T)pThis->m_currentAddress) );
3331         ret = wcslen(name);
3332         *offset = -1;
3333     }
3334 #endif
3335     return ret;
3336 }
3337 SIZE_T NativeImageDumper::TranslateFixupCallback(IXCLRDisassemblySupport *dis,
3338                                                  CLRDATA_ADDRESS addr,
3339                                                  SIZE_T size, __out_ecount(nameSize) WCHAR *name,
3340                                                  SIZE_T nameSize,
3341                                                  DWORDLONG *offset)
3342 {
3343     NativeImageDumper *pThis = (NativeImageDumper *) dis->PvClient();
3344     if( !dis->TargetIsAddress() )
3345         return 0;
3346
3347     TADDR taddr = TO_TADDR(pThis->m_currentAddress) + (TADDR)addr;
3348     SSIZE_T targetOffset;
3349     switch (size)
3350     {
3351     case sizeof(void*):
3352         targetOffset = *PTR_SIZE_T(taddr);
3353         break;
3354 #ifdef _WIN64
3355     case sizeof(INT32):
3356         targetOffset = *PTR_INT32(taddr);
3357         break;
3358 #endif
3359     case sizeof(short):
3360         targetOffset = *(short*)(WORD*)PTR_WORD(taddr);
3361         break;
3362     case sizeof(signed char):
3363         targetOffset = *PTR_SBYTE(taddr);
3364         break;
3365     default:
3366         return 0;
3367     }
3368
3369     CLRDATA_ADDRESS address = targetOffset + TO_TADDR(pThis->m_currentAddress) + addr + size;
3370
3371     SIZE_T ret = pThis->TranslateSymbol(dis, address, name, nameSize, offset);
3372     if( ret == 0 )
3373     {
3374         _snwprintf_s(name, nameSize, _TRUNCATE, W("@TRANSLATED FIXUP@ %p"), (TADDR)address);
3375         ret = wcslen(name);
3376         *offset = -1;
3377     }
3378     return ret;
3379 }
3380
3381 size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis,
3382                                           CLRDATA_ADDRESS addr, __out_ecount(nameSize) WCHAR *name,
3383                                           SIZE_T nameSize, DWORDLONG *offset)
3384 {
3385 #ifdef FEATURE_READYTORUN
3386     if (m_pReadyToRunHeader != NULL)
3387         return 0;
3388 #endif
3389
3390     if (isInRange((TADDR)addr))
3391     {
3392         COUNT_T rva = (COUNT_T)(addr - PTR_TO_TADDR(m_decoder.GetBase()));
3393
3394         COUNT_T helperTableSize;
3395         void *helperTable = m_decoder.GetNativeHelperTable(&helperTableSize);
3396
3397         if (rva >= m_decoder.GetDataRva(TO_TADDR(helperTable)) 
3398             && rva < (m_decoder.GetDataRva(TO_TADDR(helperTable))
3399                       +helperTableSize))
3400         {
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]);
3406             else
3407                 _snwprintf_s(name, nameSize, _TRUNCATE, W("Illegal HelperIndex<%04X>"), helperIndex);
3408             *offset = 0;
3409             return wcslen(name);
3410         }
3411
3412         PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
3413         PTR_NGenLayoutInfo pNgenLayout = module->GetNGenLayoutInfo();
3414
3415         for (int iRange = 0; iRange < 2; iRange++)
3416         {
3417             if (pNgenLayout->m_CodeSections[iRange].IsInRange((TADDR)addr))
3418             {
3419                 int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1);
3420                 if (MethodIndex >= 0)
3421                 {
3422 #ifdef WIN64EXCEPTIONS
3423                     while (pNgenLayout->m_MethodDescs[iRange][MethodIndex] == 0)
3424                         MethodIndex--;
3425 #endif
3426
3427                     PTR_RUNTIME_FUNCTION pRuntimeFunction = pNgenLayout->m_pRuntimeFunctions[iRange] + MethodIndex;
3428
3429                     PTR_MethodDesc pMD = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase()));
3430                     TempBuffer buf;
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);
3435                 }
3436             }
3437         }
3438
3439         if (pNgenLayout->m_CodeSections[2].IsInRange((TADDR)addr))
3440         {
3441             int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[2], 0, pNgenLayout->m_nRuntimeFunctions[2] - 1);
3442             if (ColdMethodIndex >= 0)
3443             {
3444                 PTR_RUNTIME_FUNCTION pRuntimeFunction;
3445
3446                 PTR_CORCOMPILE_COLD_METHOD_ENTRY pColdCodeMap = pNgenLayout->m_ColdCodeMap;
3447
3448 #ifdef WIN64EXCEPTIONS
3449                 while (pColdCodeMap[ColdMethodIndex].mainFunctionEntryRVA == 0)
3450                     ColdMethodIndex--;
3451
3452                 pRuntimeFunction = dac_cast<PTR_RUNTIME_FUNCTION>(PTR_TO_TADDR(m_decoder.GetBase()) + pColdCodeMap[ColdMethodIndex].mainFunctionEntryRVA);
3453 #else
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));
3457 #endif
3458
3459                 PTR_MethodDesc pMD = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase()));
3460                 TempBuffer buf;
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);
3465             }
3466         }
3467
3468         //Dumping precodes by name requires some information from the module (the precode ranges).
3469         IF_OPT_OR(PRECODES, MODULE)
3470         {
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))
3476             {
3477                 switch(maybePrecode->GetType())
3478                 {
3479                 case PRECODE_INVALID:
3480                     precodeName = "InvalidPrecode"; break;
3481                 case PRECODE_STUB:
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
3488                 case PRECODE_FIXUP:
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
3495                 }
3496                 
3497                 if( precodeName )
3498                 {
3499                     //hot or cold?
3500                     precodeBuf.AppendPrintf( W("%S (0x%p)"), precodeName, addr );
3501                 }
3502                 //get MethodDesc from precode and dump the target
3503                 PTR_MethodDesc precodeMD(maybePrecode->GetMethodDesc());
3504                 precodeBuf.Append( W(" for ") );
3505                 MethodDescToString(precodeMD, precodeBuf);
3506
3507                 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)precodeBuf);
3508
3509                 *offset = 0;
3510                 return wcslen(name);
3511             }
3512         }
3513
3514         PTR_CORCOMPILE_IMPORT_SECTION pImportSection = m_decoder.GetNativeImportSectionForRVA(rva);
3515         if (pImportSection != NULL)
3516         {
3517             const char * wbRangeName = NULL;
3518             switch (pImportSection->Type)
3519             {
3520             case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
3521                 wbRangeName = "ExternalMethod";
3522                 break;
3523
3524 #if 0
3525             case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
3526                 wbRangeName = "VirtualMethod";
3527                 break;
3528
3529             case CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH:
3530                 wbRangeName = "StubDispatch";
3531                 break;
3532 #endif
3533
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.
3536             default:
3537                 return 0;
3538             }
3539
3540             TempBuffer fixupThunkBuf;
3541             fixupThunkBuf.AppendPrintf( W("%S (0x%p) for "), wbRangeName, addr );
3542             FixupThunkToString(pImportSection, (TADDR)addr, fixupThunkBuf);
3543
3544             _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)fixupThunkBuf);
3545
3546             *offset = 0;
3547             return wcslen(name);
3548         }
3549     }
3550     else if( g_dacImpl->GetJitHelperFunctionName(addr,
3551                                                  _countof(bigByteBuffer),
3552                                                  (char*)bigByteBuffer,
3553                                                  NULL ) == S_OK )
3554     {
3555         *offset = 0;
3556         _snwprintf_s( name, nameSize, _TRUNCATE, W("%S"), bigByteBuffer );
3557         return wcslen(name);
3558     }
3559     else
3560     {
3561         //check mscorwks
3562         if( m_mscorwksBase <= addr &&
3563             addr < (m_mscorwksBase + m_mscorwksSize) )
3564         {
3565             *offset = addr - m_mscorwksBase;
3566             _snwprintf_s( name, nameSize, _TRUNCATE, W("clr") );
3567             return wcslen(name);
3568         }
3569         for( COUNT_T i = 0; i < m_numDependencies; ++i )
3570         {
3571             const Dependency& dep = m_dependencies[i];
3572             if( dep.pLoadedAddress <= addr &&
3573                 addr < (dep.pLoadedAddress + dep.size) )
3574             {
3575                 *offset = addr - dep.pLoadedAddress;
3576                 _snwprintf_s( name, nameSize, _TRUNCATE, W("%s.ni"), dep.name );
3577                 return wcslen(name);
3578             }
3579         }
3580     }
3581
3582     return 0;
3583 }
3584
3585 BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
3586 {
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();
3594
3595     return TRUE;
3596 }
3597
3598 void NativeImageDumper::DumpMethodFixups(PTR_Module module,
3599                                          TADDR fixupList)
3600 {
3601     _ASSERTE( CHECK_OPT(METHODS) );
3602
3603     COUNT_T nImportSections;
3604     PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
3605
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,
3611                                &m_decoder );
3612 }
3613
3614 IMAGE_SECTION_HEADER * NativeImageDumper::FindSection( char const * name )
3615 {
3616     COUNT_T numberOfSections = m_decoder.GetNumberOfSections();
3617     PTR_IMAGE_SECTION_HEADER curSection( m_decoder.FindFirstSection() );
3618
3619     for ( ; numberOfSections > 0; --numberOfSections, ++curSection )
3620     {
3621         if ( ! strncmp( reinterpret_cast< char * >( curSection->Name ), name, 8 ) )
3622             break;
3623     }
3624
3625     if ( ! numberOfSections )
3626         return NULL;
3627
3628     return curSection;    
3629 }
3630
3631 NativeImageDumper::EnumMnemonics NativeImageDumper::s_ModulePersistedFlags[] =
3632 {
3633 #define MPF_ENTRY(f) NativeImageDumper::EnumMnemonics(Module::f, W(#f))
3634     MPF_ENTRY(COMPUTED_GLOBAL_CLASS),
3635
3636     MPF_ENTRY(COMPUTED_STRING_INTERNING),
3637     MPF_ENTRY(NO_STRING_INTERNING),
3638
3639     MPF_ENTRY(COMPUTED_WRAP_EXCEPTIONS),
3640     MPF_ENTRY(WRAP_EXCEPTIONS),
3641
3642     MPF_ENTRY(COMPUTED_RELIABILITY_CONTRACT),
3643
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),
3649
3650     MPF_ENTRY(COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP),
3651     MPF_ENTRY(LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME),    
3652 #undef MPF_ENTRY
3653 };
3654
3655 //VirtualSectionTypes.
3656 #define TEXTIFY(x) W(#x)
3657 static const NativeImageDumper::EnumMnemonics s_virtualSectionFlags [] = 
3658 {
3659
3660 #define CORCOMPILE_SECTION_IBCTYPE(ibcType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(ibcType)),
3661     CORCOMPILE_SECTION_IBCTYPES()
3662 #undef CORCOMPILE_SECTION_IBCTYPE
3663
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
3667 };
3668 const WCHAR * g_sectionNames[] = 
3669 {
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
3674
3675 };
3676 #undef TEXTIFY
3677
3678
3679 #ifdef _PREFAST_
3680 #pragma warning(push)
3681 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3682 #endif
3683
3684 void NativeImageDumper::DumpModule( PTR_Module module )
3685 {
3686
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 );
3691
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,
3697                               MODULE );
3698
3699     PTR_MethodDesc dllMain( TO_TADDR(module->m_pDllMain) );
3700     WriteFieldMethodDesc( m_pDllMain, dllMain, Module,
3701                           MODULE );
3702
3703     _ASSERTE(module->m_dwTransientFlags == 0U);
3704     DisplayWriteFieldUInt(m_dwTransientFlags, module->m_dwTransientFlags,
3705                           Module, MODULE );
3706                            
3707
3708
3709     DisplayWriteFieldEnumerated( m_dwPersistedFlags, module->m_dwPersistedFlags,
3710                                  Module, s_ModulePersistedFlags, W("|"), MODULE );
3711
3712     DisplayWriteFieldPointer( m_pAssembly,
3713                               DPtrToPreferredAddr(module->m_pAssembly),
3714                               Module, MODULE );
3715     _ASSERTE(module->m_pAssembly == NULL); //never appears in the image
3716
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
3721      * Dump the binder
3722      */
3723     PTR_MscorlibBinder binder = module->m_pBinder;
3724     if( NULL != binder )
3725     {
3726         DisplayStartStructureWithOffset( m_pBinder, DPtrToPreferredAddr(binder),
3727                                          sizeof(*binder), Module,
3728                                          MODULE );
3729
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 );
3743
3744         DisplayWriteFieldInt( m_cClasses, binder->m_cClasses, MscorlibBinder,
3745                               MODULE );
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,
3752                               MODULE );
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,
3759                               MODULE );
3760         DisplayWriteFieldAddress( m_pMethods,
3761                                   DPtrToPreferredAddr(binder->m_pMethods),
3762                                   sizeof(*binder->m_pMethods)
3763                                   * binder->m_cMethods,
3764                                   MscorlibBinder, MODULE );
3765
3766         DisplayEndStructure( MODULE ); //m_pBinder
3767     }
3768     else
3769     {
3770         DisplayWriteFieldPointer( m_pBinder, NULL, Module, MODULE );
3771     }
3772
3773
3774     /* REVISIT_TODO Tue 10/25/2005
3775      * unconditional dependencies, activations, class dependencies, thunktable
3776      */
3777
3778
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 );
3787
3788     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3789                                + offsetof(Module, m_TypeRefToMethodTableMap) );
3790
3791     TraverseMap( lookupMap, "m_TypeRefToMethodTableMap", 
3792                  offsetof(Module, m_TypeRefToMethodTableMap),
3793                  fieldsize(Module, m_TypeRefToMethodTableMap),
3794                  &NativeImageDumper::IterateTypeRefToMTCallback );
3795
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);
3802
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);
3809
3810     TraverseMemberRefToDescHash(module->m_pMemberRefToDescHashTable, "m_pMemberRefToDescHashTable", 
3811                                 offsetof(Module, m_pMemberRefToDescHashTable),
3812                                 fieldsize(Module, m_pMemberRefToDescHashTable),
3813                                 FALSE);
3814
3815     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3816                                + offsetof(Module, m_GenericParamToDescMap) );
3817
3818     TraverseMap( lookupMap, "m_GenericParamToDescMap",
3819                  offsetof(Module, m_GenericParamToDescMap),
3820                  fieldsize(Module, m_GenericParamToDescMap),
3821                  &NativeImageDumper::IterateGenericParamToDescCallback);
3822
3823     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3824                                + offsetof(Module, m_GenericTypeDefToCanonMethodTableMap) );
3825
3826     TraverseMap( lookupMap, "m_GenericTypeDefToCanonMethodTableMap",
3827                  offsetof(Module, m_GenericTypeDefToCanonMethodTableMap),
3828                  fieldsize(Module, m_GenericTypeDefToCanonMethodTableMap),
3829                  &NativeImageDumper::IterateTypeDefToMTCallback );
3830
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);
3837
3838     lookupMap = PTR_LookupMapBase(PTR_TO_TADDR(module)
3839                               + offsetof(Module,m_ManifestModuleReferencesMap));
3840
3841     TraverseMap( lookupMap, "m_ManifestModuleReferencesMap",
3842                  offsetof(Module, m_ManifestModuleReferencesMap),
3843                  fieldsize(Module, m_ManifestModuleReferencesMap),
3844                  &NativeImageDumper::IterateManifestModules);
3845
3846     TraverseClassHash( module->m_pAvailableClasses, "m_pAvailableClasses",
3847                        offsetof(Module, m_pAvailableClasses),
3848                        fieldsize(Module, m_pAvailableClasses), true );
3849
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),
3857                             module );
3858     TraverseStubMethodHash( module->m_pStubMethodHashTable,
3859                             "m_pStubMethodHashTable",
3860                             offsetof(Module, m_pStubMethodHashTable),
3861                             fieldsize(Module, m_pStubMethodHashTable),
3862                             module );
3863
3864     IF_OPT(MODULE)
3865     {
3866         TraverseClassHash( module->m_pAvailableClassesCaseIns,
3867                            "m_pAvailableClassesCaseIns",
3868                            offsetof(Module, m_pAvailableClassesCaseIns),
3869                            fieldsize(Module, m_pAvailableClassesCaseIns),
3870                            false );
3871     }
3872
3873 #ifdef FEATURE_COMINTEROP
3874     TraverseGuidToMethodTableHash( module->m_pGuidToTypeHash, 
3875                             "m_pGuidToTypeHash",
3876                             offsetof(Module, m_pGuidToTypeHash),
3877                             fieldsize(Module, m_pGuidToTypeHash),
3878                             true);
3879
3880 #endif // FEATURE_COMINTEROP
3881
3882     _ASSERTE(module->m_pProfilingBlobTable == NULL);
3883
3884     DisplayWriteFieldFlag( m_nativeImageProfiling,
3885                            module->m_nativeImageProfiling, Module, MODULE );
3886
3887     DisplayWriteFieldPointer( m_methodProfileList,
3888                               DataPtrToDisplay((TADDR)module->m_methodProfileList),
3889                               Module, MODULE );
3890     _ASSERTE(module->m_methodProfileList == NULL);
3891
3892     /* REVISIT_TODO Tue 10/04/2005
3893      * Dump module->m_moduleCtorInfo
3894      */
3895     PTR_ModuleCtorInfo ctorInfo( PTR_HOST_MEMBER_TADDR(Module, module,
3896                                                        m_ModuleCtorInfo) );
3897
3898     DisplayStartStructureWithOffset( m_ModuleCtorInfo,
3899                                      DPtrToPreferredAddr(ctorInfo), 
3900                                      sizeof(*ctorInfo),
3901                                      Module, SLIM_MODULE_TBLS );
3902     DisplayWriteFieldInt( numElements, ctorInfo->numElements, ModuleCtorInfo,
3903                           SLIM_MODULE_TBLS );
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
3913      * inside of them?
3914      */
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.
3928      */
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 );
3939
3940     DisplayWriteFieldInt( numHotHashes, ctorInfo->numHotHashes, ModuleCtorInfo,
3941                           SLIM_MODULE_TBLS );
3942     DisplayWriteFieldInt( numColdHashes, ctorInfo->numColdHashes,
3943                           ModuleCtorInfo, SLIM_MODULE_TBLS );
3944
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 );
3959
3960     DisplayEndStructure( SLIM_MODULE_TBLS ); //m_ModuleCtorInfo
3961
3962     _ASSERTE(module->m_pNgenStats == NULL);
3963
3964     DisplayWriteFieldPointer( m_pNgenStats,
3965                               DataPtrToDisplay((TADDR)module->m_pNgenStats),
3966                               Module, MODULE );
3967
3968     DisplayWriteFieldAddress(m_propertyNameSet,
3969                              DPtrToPreferredAddr(module->m_propertyNameSet),
3970                              sizeof(module->m_propertyNameSet[0]) *
3971                              module->m_nPropertyNameSet,
3972                              Module, MODULE);
3973
3974     DisplayWriteFieldPointer( m_ModuleID,
3975                               DataPtrToDisplay(dac_cast<TADDR>(module->m_ModuleID)),
3976                               Module, MODULE );
3977     _ASSERTE(module->m_ModuleID == NULL);
3978
3979     /* XXX Tue 04/11/2006
3980      * Value is either -1 or 0, so no need to rebase.
3981      */
3982     DisplayWriteFieldPointer( m_pRegularStaticOffsets,
3983                               PTR_TO_TADDR(module->m_pRegularStaticOffsets),
3984                               Module, MODULE );
3985     _ASSERTE(module->m_pRegularStaticOffsets == (void*)-1
3986              || module->m_pRegularStaticOffsets == 0 );
3987
3988     DisplayWriteFieldInt( m_dwMaxGCRegularStaticHandles,
3989                           module->m_dwMaxGCRegularStaticHandles, Module, MODULE );
3990     DisplayWriteFieldInt( m_dwRegularStaticsBlockSize, module->m_dwRegularStaticsBlockSize,
3991                           Module, MODULE );
3992     DisplayWriteFieldAddress( m_pDynamicStaticsInfo,
3993                               DataPtrToDisplay((TADDR)module->m_pDynamicStaticsInfo),
3994                               module->m_maxDynamicEntries
3995                                 * sizeof(*(module->m_pDynamicStaticsInfo)),
3996                               Module, MODULE );
3997
3998     DisplayWriteFieldInt( m_cDynamicEntries,
3999                           (int)module->m_cDynamicEntries, Module, MODULE );
4000
4001     CoverageRead(TO_TADDR(module->m_pDynamicStaticsInfo),
4002                  (int)(module->m_maxDynamicEntries
4003                  * sizeof(*(module->m_pDynamicStaticsInfo))));
4004
4005
4006
4007     _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL);
4008     DisplayWriteFieldPointer( m_debuggerSpecificData.m_pDynamicILCrst,
4009                               DataPtrToDisplay(dac_cast<TADDR>(module->m_debuggerSpecificData.m_pDynamicILCrst)),
4010                               Module, MODULE );
4011
4012
4013     /* REVISIT_TODO Wed 09/21/2005
4014      * Get me in the debugger and look at the activations and module/class
4015      * dependencies.
4016      * As well as the thunks.
4017      */
4018     
4019     /* REVISIT_TODO Wed 09/21/2005
4020      * Dump the following
4021      */
4022     //file
4023     //assembly
4024
4025     DisplayWriteFieldInt( m_DefaultDllImportSearchPathsAttributeValue,
4026                           module->m_DefaultDllImportSearchPathsAttributeValue, Module, MODULE );
4027
4028
4029     DisplayEndStructure(MODULE); //Module
4030 }
4031 #ifdef _PREFAST_
4032 #pragma warning(pop)
4033 #endif
4034
4035 bool NativeImageDumper::isPrecode(TADDR maybePrecode)
4036 {
4037     PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
4038
4039     return !!module->IsZappedPrecode(maybePrecode);
4040 }
4041
4042
4043 void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget,
4044                                                     TADDR flags,
4045                                                     PTR_LookupMapBase map,
4046                                                     DWORD rid )
4047 {
4048     DisplayStartElement( "Entry", MODULE_TABLES );
4049
4050     PTR_MethodTable mt(mtTarget);
4051
4052     DisplayWriteElementUInt( "Token", rid | mdtTypeDef, MODULE_TABLES );
4053     /* REVISIT_TODO Fri 10/21/2005
4054      * Can I use WriteElementMethodTable here?
4055      */
4056     DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4057                                 MODULE_TABLES );
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.
4061      */
4062     if( rid == 0 || ((rid != 1) && (mtTarget == NULL)) )
4063     {
4064         DisplayWriteElementString( "Name", "mdTypeDefNil", MODULE_TABLES );
4065     }
4066     else
4067     {
4068         TempBuffer buf;
4069         MethodTableToString( mt, buf );
4070         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4071     }
4072     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4073                              MODULE_TABLES );
4074     DisplayEndElement( MODULE_TABLES );
4075
4076     if( isInRange(PTR_TO_TADDR(mt)) )
4077     {
4078         m_discoveredMTs.AppendEx(mt);
4079         PTR_EEClass clazz = GetClassFromMT(mt);
4080         if( isInRange(PTR_TO_TADDR(clazz)) )
4081             m_discoveredClasses.AppendEx(mt);
4082     }
4083 }
4084
4085 void NativeImageDumper::IterateTypeRefToMTCallback( TADDR mtTarget,
4086                                                     TADDR flags,
4087                                                     PTR_LookupMapBase map,
4088                                                     DWORD rid )
4089 {
4090     DisplayStartElement( "Entry", MODULE_TABLES );
4091
4092     mtTarget = ((FixupPointer<TADDR>&)mtTarget).GetValue();
4093
4094     PTR_MethodTable mt(mtTarget);
4095
4096 #if 0
4097     RecordTypeRef(rid | mdtTypeRef, mt);
4098 #endif
4099
4100     DisplayWriteElementUInt( "Token", rid | mdtTypeRef, MODULE_TABLES );
4101
4102     DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4103                                 MODULE_TABLES );
4104
4105     if( rid == 0 )
4106     {
4107         DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4108         DisplayWriteElementString( "Name", "mdtTypeRefNil", MODULE_TABLES );
4109     }
4110     else if( mt == NULL )
4111     {
4112         DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4113         IF_OPT(MODULE_TABLES)
4114             WriteElementMDToken( "Name", mdtTypeRef | rid );
4115     }
4116     else if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
4117     {
4118         RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
4119         //
4120         // This guy writes two things FixupTargetValue and FixupTargetName
4121         //
4122         WriteElementsFixupBlob( NULL,PTR_TO_TADDR(mt));
4123     }
4124     else
4125     {
4126         TempBuffer buf;
4127         MethodTableToString( mt, buf ); 
4128         DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4129         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4130     }
4131     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4132                              MODULE_TABLES );
4133     DisplayEndElement( MODULE_TABLES );
4134     if( isInRange(mtTarget) )
4135     {
4136         m_discoveredMTs.AppendEx(mt);
4137         PTR_EEClass clazz = GetClassFromMT(mt);
4138         if( isInRange(PTR_TO_TADDR(clazz)) )
4139             m_discoveredClasses.AppendEx(mt);
4140     }
4141 }
4142
4143 void NativeImageDumper::IterateMethodDefToMDCallback( TADDR mdTarget,
4144                                                       TADDR flags,
4145                                                       PTR_LookupMapBase map,
4146                                                       DWORD rid )
4147 {
4148     DisplayStartElement( "Entry", MODULE_TABLES );
4149
4150     PTR_MethodDesc md(mdTarget);
4151
4152     DisplayWriteElementUInt( "Token", rid | mdtMethodDef, MODULE_TABLES );
4153
4154     DisplayWriteElementPointer( "MethodDesc", DPtrToPreferredAddr(md),
4155                                 MODULE_TABLES );
4156
4157     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4158     if( rid == 0 )
4159     {
4160         DisplayWriteElementString( "Name", "mdtMethodDefNil", MODULE_TABLES );
4161     }
4162     else
4163     {
4164         TempBuffer buf;
4165         MethodDescToString( md, buf );
4166         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4167     }
4168     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4169                              MODULE_TABLES );
4170     DisplayEndElement( MODULE_TABLES );
4171     //m_discoveredMDs.AppendEx(md);
4172 }
4173
4174 void NativeImageDumper::IterateFieldDefToFDCallback( TADDR fdTarget,
4175                                                      TADDR flags,
4176                                                      PTR_LookupMapBase map,
4177                                                      DWORD rid )
4178 {
4179     PTR_FieldDesc fd(fdTarget);
4180     DisplayStartElement( "Entry", MODULE_TABLES );
4181
4182
4183     DisplayWriteElementUInt( "Token", rid | mdtFieldDef, MODULE_TABLES );
4184
4185     DisplayWriteElementPointer( "FieldDef", DPtrToPreferredAddr(fd),
4186                                 MODULE_TABLES );
4187
4188     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4189     if( rid == 0 )
4190     {
4191         DisplayWriteElementString( "Name", "mdtFieldDefNil", MODULE_TABLES );
4192     }
4193     else
4194     {
4195         TempBuffer buf;
4196         FieldDescToString( fd, mdtFieldDef | rid, buf );
4197         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4198     }
4199     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4200                              MODULE_TABLES );
4201     DisplayEndElement( MODULE_TABLES );
4202     /* XXX Mon 10/17/2005
4203      * All FieldDescs are reachable from the EEClasses
4204      */
4205     //m_discoveredFDs.AppendEx(PTR_FieldDesc(fdTarget));
4206 }
4207
4208 void NativeImageDumper::IterateMemberRefToDescCallback( TADDR mrTarget,
4209                                                         TADDR flags,
4210                                                         PTR_LookupMapBase map,
4211                                                         DWORD rid )
4212 {
4213     DisplayStartElement( "Entry", MODULE_TABLES );
4214
4215
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 );
4222
4223     TempBuffer buf;
4224     if( rid == 0 )
4225     {
4226         buf.Append( W("mdtMemberDefNil") );
4227     }
4228     else if( CORCOMPILE_IS_POINTER_TAGGED(mrTarget) )
4229     {
4230         WriteElementsFixupBlob( NULL, mrTarget );
4231     }    
4232     else if( isFieldRef )
4233     {
4234         FieldDescToString( PTR_FieldDesc(mrTarget), buf );
4235     }
4236     else
4237     {
4238         MethodDescToString( PTR_MethodDesc(mrTarget), buf );
4239     }
4240     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4241     DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4242
4243     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4244                              MODULE_TABLES );
4245     DisplayEndElement(MODULE_TABLES);
4246     //m_discoveredMTs.AppendEx(mt);
4247 }
4248
4249 void NativeImageDumper::IterateGenericParamToDescCallback( TADDR tdTarget,
4250                                                      TADDR flags,
4251                                                      PTR_LookupMapBase map,
4252                                                      DWORD rid )
4253 {
4254     PTR_TypeDesc td(tdTarget);
4255     DisplayStartElement( "Entry", MODULE_TABLES );
4256
4257
4258     DisplayWriteElementUInt( "Token", rid | mdtGenericParam, MODULE_TABLES );
4259
4260     DisplayWriteElementPointer( "GenericParam", DPtrToPreferredAddr(td),
4261                                 MODULE_TABLES );
4262
4263     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4264     if( rid == 0 || td == NULL )
4265     {
4266         DisplayWriteElementString( "Name", "mdtGenericParamNil", MODULE_TABLES );
4267     }
4268     else
4269     {
4270         TempBuffer buf;
4271         TypeDescToString( td, buf );
4272         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4273     }
4274     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4275                              MODULE_TABLES );
4276     DisplayEndElement( MODULE_TABLES );
4277 }
4278
4279 #if 0
4280 void NativeImageDumper::IterateFileReferencesCallback(TADDR moduleTarget,
4281                                                       TADDR flags,
4282                                                       PTR_LookupMapBase map,
4283                                                       DWORD rid)
4284 {
4285     DisplayStartElement( "Entry", MODULE_TABLES );
4286
4287     PTR_Module module(moduleTarget);
4288
4289     DisplayWriteElementUInt( "Token", rid | mdtFile, MODULE_TABLES );
4290
4291     DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4292                                 MODULE_TABLES );
4293
4294     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4295     if( rid == 0 || (module == NULL) )
4296     {
4297         DisplayWriteElementString( "Name", "mdtFileNil", MODULE_TABLES );
4298     }
4299     else
4300     {
4301         TempBuffer buf;
4302         AppendTokenName(mdtFile | rid, buf);
4303         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4304     }
4305     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4306                              MODULE_TABLES );
4307     DisplayEndElement( MODULE_TABLES );
4308     //m_discoveredFDs.AppendEx(mt);
4309 }
4310 #endif
4311
4312 void NativeImageDumper::IterateManifestModules( TADDR moduleTarget,
4313                                                TADDR flags,
4314                                                PTR_LookupMapBase map, 
4315                                                DWORD rid )
4316 {
4317     DisplayStartElement( "Entry", MODULE_TABLES );
4318
4319     moduleTarget = ((FixupPointer<TADDR>&)moduleTarget).GetValue();
4320
4321     PTR_Module module(moduleTarget);
4322
4323     DisplayWriteElementUInt( "Token", rid | mdtAssemblyRef, MODULE_TABLES );
4324
4325     DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4326                                 MODULE_TABLES );
4327     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4328     if( rid == 0 || (module == NULL) )
4329     {
4330         DisplayWriteElementString( "Name", "mdtAssemblyRefNil", MODULE_TABLES );
4331     }
4332     else
4333     {
4334         TempBuffer buf;
4335         AppendTokenName(mdtAssemblyRef | rid, buf, m_import);
4336         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4337     }
4338     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4339                              MODULE_TABLES );
4340     DisplayEndElement( MODULE_TABLES );
4341     //m_discoveredFDs.AppendEx(mt);
4342 }
4343
4344 void NativeImageDumper::TraverseMap(PTR_LookupMapBase map, const char * name,
4345                                     unsigned offset, unsigned fieldSize,
4346                                     void(NativeImageDumper::*cb)(TADDR,
4347                                                                  TADDR,
4348                                                                  PTR_LookupMapBase,
4349                                                                  DWORD))
4350 {
4351     if( map == NULL )
4352     {
4353         IF_OPT(MODULE)
4354             m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
4355         return;
4356     }
4357     DisplayStartVStructure(name, MODULE);
4358
4359     DisplayStartArray( "Tables", W("%s"), MODULE );
4360     PTR_LookupMapBase current = map;
4361     do
4362     {
4363         DWORD cbTable = map->MapIsCompressed() ? map->cbTable : map->dwCount * sizeof(*map->pTable);
4364
4365         IF_OPT(MODULE)
4366         {
4367             DisplayWriteElementAddress( "Table",
4368                                         DPtrToPreferredAddr(map->pTable),
4369                                         cbTable,
4370                                         MODULE);
4371         }
4372
4373         CoverageRead( PTR_TO_TADDR(map->pTable), cbTable );
4374         _ASSERTE(current == map || current->hotItemList == NULL);
4375         current = current->pNext;
4376     }while( current != NULL );
4377     
4378     DisplayEndArray( "Total Tables", MODULE ); //Tables
4379
4380     DisplayWriteFieldAddress( hotItemList,
4381                               DPtrToPreferredAddr(map->hotItemList),
4382                               map->dwNumHotItems * sizeof(*map->hotItemList),
4383                               LookupMapBase, MODULE );
4384
4385     DisplayStartArray( "Map", W("[%s]: %s %s%s  %s %s %s"), MODULE_TABLES );
4386
4387     IF_OPT_OR3(MODULE_TABLES, EECLASSES, METHODTABLES)
4388     {
4389         LookupMap<TADDR>::Iterator iter(dac_cast<DPTR(LookupMap<TADDR>)>(map));
4390         DWORD rid = 0;
4391         while(iter.Next())
4392         {
4393             TADDR flags = 0;
4394             TADDR element = iter.GetElementAndFlags(&flags);
4395             (this->*cb)( element, flags, map, rid );
4396             rid++;                         
4397         }
4398
4399     }
4400     CoverageRead( PTR_TO_TADDR(map->hotItemList),
4401                   map->dwNumHotItems * sizeof(*map->hotItemList) );
4402     DisplayEndArray( "Total" , MODULE_TABLES );//Map
4403
4404     DisplayEndVStructure(MODULE); //name
4405 }
4406
4407 // Templated method containing the core code necessary to traverse hash tables based on NgenHash (see
4408 // vm\NgenHash.h).
4409 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4410 void NativeImageDumper::TraverseNgenHash(DPTR(HASH_CLASS) pTable,
4411                                          const char * name,
4412                                          unsigned offset,
4413                                          unsigned fieldSize,
4414                                          bool saveClasses,
4415                                          void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4416                                          void *pContext)
4417 {
4418     if (pTable == NULL)
4419     {
4420         IF_OPT(MODULE)
4421             m_display->WriteFieldPointer(name, offset, fieldSize, NULL);
4422         return;
4423     }
4424     IF_OPT(MODULE)
4425     {
4426         m_display->StartStructureWithOffset(name, offset, fieldSize,
4427                                             DPtrToPreferredAddr(pTable),
4428                                             sizeof(HASH_CLASS));
4429     }
4430
4431     DisplayWriteFieldPointer(m_pModule,
4432                              DPtrToPreferredAddr(pTable->GetModule()),
4433                              HASH_CLASS, MODULE);
4434
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);
4442
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
4450
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
4458
4459     DisplayEndStructure(MODULE); // pTable
4460 }
4461
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,
4467                                                      bool saveClasses,
4468                                                      void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4469                                                      void *pContext)
4470 {
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);
4482
4483     // Display entries (or maybe just the classes referenced by those entries).
4484     DisplayStartArray("Entries", NULL, SLIM_MODULE_TBLS);
4485
4486     // Enumerate bucket list.
4487     for (DWORD i = 0; i < pEntries->m_cBuckets; ++i)
4488     {
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);
4492
4493         // Loop over entries.
4494         while (cEntries && (CHECK_OPT(SLIM_MODULE_TBLS)
4495                             || CHECK_OPT(EECLASSES)
4496                             || CHECK_OPT(METHODTABLES)))
4497         {
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)));
4501
4502             IF_OPT(SLIM_MODULE_TBLS)
4503             {
4504                 DisplayStartStructure("PersistedEntry",
4505                                       DPtrToPreferredAddr(pEntry),
4506                                       sizeof(typename HASH_CLASS::PersistedEntry), SLIM_MODULE_TBLS);
4507             }
4508
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);
4514
4515             IF_OPT(SLIM_MODULE_TBLS)
4516             {
4517                 DisplayWriteFieldUInt(m_iHashValue, pEntry->m_iHashValue,
4518                                       typename HASH_CLASS::PersistedEntry, SLIM_MODULE_TBLS);
4519
4520                 DisplayEndStructure(SLIM_MODULE_TBLS); // Entry
4521             }
4522
4523             dwEntryId++;
4524             cEntries--;
4525         }
4526     }
4527
4528     DisplayEndArray("Total Entries", SLIM_MODULE_TBLS); // Entry array
4529 }
4530
4531 void NativeImageDumper::TraverseClassHashEntry(void *pContext, PTR_EEClassHashEntry pEntry, bool saveClasses)
4532 {
4533     IF_OPT(SLIM_MODULE_TBLS)
4534     {
4535         DisplayStartStructure("EEClassHashEntry",
4536                               DPtrToPreferredAddr(pEntry),
4537                               sizeof(EEClassHashEntry), SLIM_MODULE_TBLS);
4538     }
4539
4540     size_t datum = size_t(PTR_TO_TADDR(pEntry->GetData()));
4541
4542     if (datum & EECLASSHASH_TYPEHANDLE_DISCR)
4543     {
4544         IF_OPT(SLIM_MODULE_TBLS)
4545         {
4546             /* REVISIT_TODO Tue 10/25/2005
4547              * Raw data with annotation?
4548              */
4549             mdTypeDef tk;
4550             tk = EEClassHashTable::UncompressModuleAndClassDef(pEntry->GetData());
4551             DoWriteFieldMDToken("Token",
4552                                 offsetof(EEClassHashEntry, m_Data),
4553                                 fieldsize(EEClassHashEntry, m_Data),
4554                                 tk);
4555         }
4556     }
4557     else
4558     {
4559         PTR_MethodTable pMT(TO_TADDR(datum));
4560         IF_OPT(SLIM_MODULE_TBLS)
4561         {
4562             DoWriteFieldMethodTable("MethodTable",
4563                                     offsetof(EEClassHashEntry, m_Data),
4564                                     fieldsize(EEClassHashEntry, m_Data),
4565                                     pMT);
4566         }
4567
4568         if (saveClasses)
4569         {
4570             // These are MethodTables.  Get back to the EEClass from there.
4571             if (isInRange(PTR_TO_TADDR(pMT)))
4572                 m_discoveredMTs.AppendEx(pMT);
4573             if (pMT != NULL)
4574             {
4575                 PTR_EEClass pClass = GetClassFromMT(pMT);
4576                 if (isInRange(PTR_TO_TADDR(pClass)))
4577                     m_discoveredClasses.AppendEx(pMT);
4578             }
4579         }
4580     }
4581
4582     IF_OPT(SLIM_MODULE_TBLS)
4583     {
4584         DisplayWriteFieldPointer(m_pEncloser,
4585                                  DPtrToPreferredAddr(pEntry->GetEncloser()),
4586                                  EEClassHashEntry, SLIM_MODULE_TBLS);
4587         DisplayEndStructure(SLIM_MODULE_TBLS);
4588     }
4589 }
4590
4591 void NativeImageDumper::TraverseClassHash(PTR_EEClassHashTable pTable,
4592                                           const char * name,
4593                                           unsigned offset,
4594                                           unsigned fieldSize,
4595                                           bool saveClasses)
4596 {
4597     TraverseNgenHash<EEClassHashTable, EEClassHashEntry>(pTable,
4598                                                          name,
4599                                                          offset,
4600                                                          fieldSize,
4601                                                          saveClasses,
4602                                                          &NativeImageDumper::TraverseClassHashEntry,
4603                                                          NULL);
4604 }
4605
4606 #ifdef FEATURE_COMINTEROP
4607
4608 void NativeImageDumper::TraverseGuidToMethodTableEntry(void *pContext, PTR_GuidToMethodTableEntry pEntry, bool saveClasses)
4609 {
4610     IF_OPT(SLIM_MODULE_TBLS)
4611     {
4612         DisplayStartStructure("GuidToMethodTableEntry",
4613                               DPtrToPreferredAddr(pEntry),
4614                               sizeof(GuidToMethodTableEntry), SLIM_MODULE_TBLS);
4615     }
4616
4617     WriteFieldMethodTable(m_pMT, pEntry->m_pMT, GuidToMethodTableEntry, ALWAYS);
4618     
4619     TempBuffer buf;
4620     GuidToString( *(pEntry->m_Guid), buf );
4621     DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidToMethodTableEntry, ALWAYS );
4622
4623     DisplayEndStructure( SLIM_MODULE_TBLS );
4624 }
4625
4626 void NativeImageDumper::TraverseGuidToMethodTableHash(PTR_GuidToMethodTableHashTable pTable, 
4627                         const char * name,
4628                         unsigned offset,
4629                         unsigned fieldSize,
4630                         bool saveClasses)
4631 {
4632     TraverseNgenHash<GuidToMethodTableHashTable, GuidToMethodTableEntry>(pTable,
4633                         name,
4634                         offset,
4635                         fieldSize,
4636                         saveClasses,
4637                         &NativeImageDumper::TraverseGuidToMethodTableEntry,
4638                         NULL);
4639 }
4640
4641 #endif // FEATURE_COMINTEROP
4642
4643 void NativeImageDumper::TraverseMemberRefToDescHashEntry(void *pContext, PTR_MemberRefToDescHashEntry pEntry, bool saveClasses)
4644 {
4645     IF_OPT(SLIM_MODULE_TBLS)
4646     {
4647         DisplayStartStructure("MemberRefToDescHashEntry",
4648                               DPtrToPreferredAddr(pEntry),
4649                               sizeof(MemberRefToDescHashEntry), SLIM_MODULE_TBLS);
4650     }
4651
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);
4654     else
4655         WriteFieldMethodDesc(m_value, dac_cast<PTR_MethodDesc>(pEntry->m_value), MemberRefToDescHashEntry, MODULE_TABLES);
4656     
4657     DisplayEndStructure( SLIM_MODULE_TBLS );
4658 }
4659
4660 void NativeImageDumper::TraverseMemberRefToDescHash(PTR_MemberRefToDescHashTable pTable, 
4661                         const char * name,
4662                         unsigned offset,
4663                         unsigned fieldSize,
4664                         bool saveClasses)
4665 {
4666     TraverseNgenHash<MemberRefToDescHashTable, MemberRefToDescHashEntry>(pTable,
4667                         name,
4668                         offset,
4669                         fieldSize,
4670                         saveClasses,
4671                         &NativeImageDumper::TraverseMemberRefToDescHashEntry,
4672                         NULL);
4673 }
4674
4675
4676 void NativeImageDumper::TraverseTypeHashEntry(void *pContext, PTR_EETypeHashEntry pEntry, bool saveClasses)
4677 {
4678     TypeHandle th = pEntry->GetTypeHandle();
4679     IF_OPT(SLIM_MODULE_TBLS)
4680     {
4681         DisplayStartStructure("EETypeHashEntry",
4682                               DPtrToPreferredAddr(pEntry),
4683                               sizeof(EETypeHashEntry), SLIM_MODULE_TBLS);
4684
4685         DoWriteFieldTypeHandle("TypeHandle",
4686                                offsetof(EETypeHashEntry, m_data),
4687                                fieldsize(EETypeHashEntry, m_data),
4688                                th);
4689     }
4690             
4691     if (!CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc())
4692     {
4693         PTR_TypeDesc td(th.AsTypeDesc());
4694         if (isInRange(PTR_TO_TADDR(td)))
4695             m_discoveredTypeDescs.AppendEx(td);
4696         if (td->HasTypeParam())
4697         {
4698             PTR_ParamTypeDesc ptd(td);
4699
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.
4706              */
4707             PTR_MethodTable mt(ptd->GetTemplateMethodTableInternal());
4708             if (isInRange(PTR_TO_TADDR(mt)))
4709             {
4710                 m_discoveredMTs.AppendEx(mt);
4711                 if (mt->IsClassPointerValid())
4712                 {
4713                     PTR_EEClass pClass = mt->GetClass();
4714                     if (isInRange(PTR_TO_TADDR(pClass)))
4715                         m_discoveredClasses.AppendEx(mt);
4716                 }
4717             }
4718         }
4719     }
4720     else
4721     {
4722         PTR_MethodTable mt(th.AsTAddr());
4723
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())
4729         {
4730             PTR_EEClass pClass = mt->GetClass();
4731             if (isInRange(PTR_TO_TADDR(pClass)))
4732                 m_discoveredClasses.AppendEx(mt);
4733         }
4734     }
4735
4736     IF_OPT(SLIM_MODULE_TBLS)
4737     {
4738         DisplayEndStructure(SLIM_MODULE_TBLS);
4739     }
4740 }
4741
4742 void NativeImageDumper::TraverseTypeHash(PTR_EETypeHashTable pTable,
4743                                          const char * name,
4744                                          unsigned offset,
4745                                          unsigned fieldSize)
4746 {
4747     TraverseNgenHash<EETypeHashTable, EETypeHashEntry>(pTable,
4748                                                        name,
4749                                                        offset,
4750                                                        fieldSize,
4751                                                        true,
4752                                                        &NativeImageDumper::TraverseTypeHashEntry,
4753                                                        NULL);
4754 }
4755
4756 void NativeImageDumper::TraverseInstMethodHashEntry(void *pContext, PTR_InstMethodHashEntry pEntry, bool saveClasses)
4757 {
4758     PTR_Module pModule((TADDR)pContext);
4759
4760     IF_OPT(SLIM_MODULE_TBLS)
4761     {
4762         DisplayStartStructure("InstMethodHashEntry",
4763                               DPtrToPreferredAddr(pEntry),
4764                               sizeof(InstMethodHashEntry), SLIM_MODULE_TBLS);
4765     }
4766
4767     IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4768     {
4769         IF_OPT(METHODDESCS)
4770         {
4771             PTR_MethodDesc md = pEntry->GetMethod();
4772             _ASSERTE(md != NULL);
4773
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
4780         }
4781         else
4782         {
4783             PTR_MethodDesc md = pEntry->GetMethod();
4784             WriteFieldMethodDesc(data, md,
4785                                  InstMethodHashEntry, ALWAYS);
4786         }
4787     }
4788     else
4789         CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4790
4791     IF_OPT(SLIM_MODULE_TBLS)
4792     {
4793         DisplayEndStructure(SLIM_MODULE_TBLS);
4794     }
4795 }
4796
4797 void NativeImageDumper::TraverseStubMethodHashEntry(void *pContext, PTR_StubMethodHashEntry pEntry, bool saveClasses)
4798 {
4799     PTR_Module pModule((TADDR)pContext);
4800
4801     IF_OPT(SLIM_MODULE_TBLS)
4802     {
4803         DisplayStartStructure("StubMethodHashEntry",
4804                               DPtrToPreferredAddr(pEntry),
4805                               sizeof(StubMethodHashEntry), SLIM_MODULE_TBLS);
4806     }
4807
4808     IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4809     {
4810         PTR_MethodDesc md = pEntry->GetMethod();
4811         _ASSERTE(md != NULL);
4812
4813         PTR_MethodDesc stub = pEntry->GetStubMethod();
4814         _ASSERTE(stub != NULL);
4815
4816         IF_OPT(METHODDESCS)
4817         {
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
4824
4825             m_display->StartVStructureWithOffset("pStubMD", offsetof(StubMethodHashEntry, pStubMD),
4826                                                   sizeof(pEntry->pStubMD));
4827             DumpMethodDesc(stub, pModule);
4828             DisplayEndVStructure(ALWAYS); //pStubMD
4829         }
4830         else
4831         {
4832             WriteFieldMethodDesc(pMD, md,
4833                                  StubMethodHashEntry, ALWAYS);
4834             WriteFieldMethodDesc(pStubMD, stub,
4835                                  StubMethodHashEntry, ALWAYS);
4836         }
4837     }
4838     else
4839         CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4840
4841     IF_OPT(SLIM_MODULE_TBLS)
4842     {
4843         DisplayEndStructure(SLIM_MODULE_TBLS);
4844     }
4845 }
4846
4847 void NativeImageDumper::TraverseInstMethodHash(PTR_InstMethodHashTable pTable,
4848                                                const char * name,
4849                                                unsigned fieldOffset,
4850                                                unsigned fieldSize,
4851                                                PTR_Module module)
4852 {
4853     TraverseNgenHash<InstMethodHashTable, InstMethodHashEntry>(pTable,
4854                                                                name,
4855                                                                fieldOffset,
4856                                                                fieldSize,
4857                                                                true,
4858                                                                &NativeImageDumper::TraverseInstMethodHashEntry,
4859                                                                (void*)dac_cast<TADDR>(module));
4860 }
4861
4862 void NativeImageDumper::TraverseStubMethodHash(PTR_StubMethodHashTable pTable,
4863                                                const char * name,
4864                                                unsigned fieldOffset,
4865                                                unsigned fieldSize,
4866                                                PTR_Module module)
4867 {
4868     TraverseNgenHash<StubMethodHashTable, StubMethodHashEntry>(pTable,
4869                                                                name,
4870                                                                fieldOffset,
4871                                                                fieldSize,
4872                                                                true,
4873                                                                &NativeImageDumper::TraverseStubMethodHashEntry,
4874                                                                (void*)dac_cast<TADDR>(module));
4875 }
4876
4877 const NativeImageDumper::Dependency *
4878 NativeImageDumper::GetDependencyForModule( PTR_Module module )
4879 {
4880     for( COUNT_T i = 0; i < m_numDependencies; ++i )
4881     {
4882         if( m_dependencies[i].pModule == module )
4883             return &m_dependencies[i];
4884     }
4885     return NULL;
4886 }
4887
4888 #if 0
4889 const NativeImageDumper::Import *
4890 NativeImageDumper::GetImportForPointer( TADDR ptr )
4891 {
4892     for( int i = 0; i < m_numImports; ++i )
4893     {
4894         const Import * import = &m_imports[i];
4895         if( import->dependency->pPreferredBase == NULL )
4896             continue;
4897         if( import->dependency->pPreferredBase <= ptr
4898             && ((import->dependency->pPreferredBase
4899                  + import->dependency->size) > ptr) )
4900         {
4901             //found the right target
4902             return import;
4903         }
4904     }
4905     return NULL;
4906 }
4907 #endif
4908 const NativeImageDumper::Dependency *
4909 NativeImageDumper::GetDependencyForPointer( TADDR ptr )
4910 {
4911     for( COUNT_T i = 0; i < m_numDependencies; ++i )
4912     {
4913         const Dependency * dependency = &m_dependencies[i];
4914         if( dependency->pLoadedAddress == NULL )
4915             continue;
4916         if( dependency->pLoadedAddress <= ptr
4917             && ((dependency->pLoadedAddress + dependency->size) > ptr) )
4918         {
4919             //found the right target
4920             return dependency;
4921         }
4922     }
4923     return NULL;
4924 }
4925
4926 void NativeImageDumper::DictionaryToArgString( PTR_Dictionary dictionary, unsigned numArgs, SString& buf )
4927 {
4928     //this can be called with numArgs == 0 for value type instantiations.
4929     buf.Append( W("<") );
4930
4931     for( unsigned i = 0; i < numArgs; ++i )
4932     {
4933         if( i > 0 )
4934             buf.Append( W(",") );
4935
4936         TypeHandle th = dictionary->GetInstantiation()[i].GetValue();
4937         if( CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) )
4938         {
4939             if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(dictionary))))
4940             {
4941                 //this is an RVA from another hardbound dependency.  We cannot decode it
4942                 buf.Append(W("OUT_OF_MODULE_FIXUP"));
4943             }
4944             else
4945             {
4946                 RVA rva = CORCOMPILE_UNTAG_TOKEN(th.AsTAddr());
4947                 FixupBlobToString(rva, buf);
4948             }
4949         }
4950         else
4951         {
4952             TypeHandleToString( th, buf );
4953         }
4954     }
4955     buf.Append( W(">") );
4956 }
4957
4958 void NativeImageDumper::MethodTableToString( PTR_MethodTable mt, SString& buf )
4959 {
4960     bool hasCompleteExtents = true;
4961     IF_OPT(DISABLE_NAMES)
4962     {
4963         buf.Append( W("Disabled") );
4964         return;
4965     }
4966     mdToken token = mdTokenNil;
4967     if( mt == NULL )
4968         buf.Append( W("mdTypeDefNil") );
4969     else
4970     {
4971         _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)));
4972         const Dependency * dependency; 
4973         if( !mt->IsClassPointerValid() )
4974         {
4975             if( isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))) )
4976             {
4977
4978                 hasCompleteExtents = false;
4979                 RVA rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
4980                 PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
4981
4982                 BYTE kind = *sig++;
4983
4984                 if (kind & ENCODE_MODULE_OVERRIDE)
4985                 {
4986                     /* int moduleIndex = */ DacSigUncompressData(sig);
4987                     kind &= ~ENCODE_MODULE_OVERRIDE;
4988                 }
4989
4990                 _ASSERTE(kind == ENCODE_TYPE_HANDLE);
4991                 CorElementType et = DacSigUncompressElementType(sig);
4992                 if( et == ELEMENT_TYPE_GENERICINST )
4993                 {
4994                     //generic instances have another element type
4995                     et = DacSigUncompressElementType(sig);
4996                 }
4997                 if (et == ELEMENT_TYPE_VALUETYPE || et == ELEMENT_TYPE_CLASS)
4998                 {
4999                     token = DacSigUncompressToken(sig);
5000                 }
5001                 else
5002                 {
5003                     // Arrays, etc.
5004                     token = mdtTypeDef;
5005                 }
5006                 dependency = GetDependencyForFixup(rva);
5007             }
5008             else
5009             {
5010                 //this is an RVA from another hardbound dependency.  We cannot decode it
5011                 buf.Append(W("OUT_OF_MODULE_FIXUP"));
5012                 return;
5013             }
5014         }
5015         else
5016         {
5017             token = mt->GetCl();
5018             dependency = GetDependencyFromMT(mt);
5019         }
5020
5021         if( !isSelf(dependency) )
5022         {
5023             AppendTokenName( dependency->entry->dwAssemblyRef, buf,
5024                              m_manifestImport );
5025             buf.Append(W("!"));
5026         }
5027
5028         _ASSERTE(dependency->pImport);
5029         if( token == mdtTypeDef )
5030             buf.Append( W("No Token") );
5031         else
5032             AppendTokenName( token, buf, dependency->pImport );
5033
5034         if( mt->HasPerInstInfo() )
5035         {
5036             unsigned numDicts;
5037             if( hasCompleteExtents )
5038             {
5039                 numDicts = mt->GetNumDicts();
5040                 _ASSERTE(numDicts == CountDictionariesInClass(token, dependency->pImport));
5041             }
5042             else
5043             {
5044                 numDicts = (DWORD)CountDictionariesInClass(token, dependency->pImport);
5045             }
5046
5047             TADDR base = dac_cast<TADDR>(&(mt->GetPerInstInfo()[numDicts-1]));
5048
5049             PTR_Dictionary dictionary( MethodTable::PerInstInfoElem_t::GetValueAtPtr(base) );
5050             unsigned numArgs = mt->GetNumGenericArgs();
5051
5052             DictionaryToArgString( dictionary, numArgs, buf );
5053         }
5054     }
5055 }
5056
5057 mdToken NativeImageDumper::ConvertToTypeDef( mdToken typeToken, IMetaDataImport2* (&pImport) )
5058 {
5059     _ASSERTE( (TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5060               || (TypeFromToken(typeToken) == mdtTypeSpec) );
5061     if( mdtTypeDef == TypeFromToken(typeToken) )
5062         return typeToken;
5063     if( mdtTypeRef == TypeFromToken(typeToken) )
5064     {
5065         //convert the ref to a def.
5066         mdToken scope;
5067         WCHAR trName[MAX_CLASS_NAME];
5068         ULONG trNameLen;
5069         IfFailThrow(pImport->GetTypeRefProps(typeToken, &scope, trName, _countof(trName), &trNameLen));
5070         _ASSERTE(trName[trNameLen-1] == 0);
5071
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?
5075          */
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);
5081
5082         pImport = dep->pImport;
5083
5084         /* REVISIT_TODO Fri 10/6/2006
5085          * Does this work for inner types?
5086          */
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)
5090         {
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);
5100
5101             pImport = dep->pImport;
5102             hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5103         }
5104         IfFailThrow(hr);
5105     }
5106     else
5107     {
5108         PCCOR_SIGNATURE pSig;
5109         ULONG cbSig;
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);
5117     }
5118
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);
5122     return typeToken;
5123 }
5124
5125 SIZE_T NativeImageDumper::CountDictionariesInClass( mdToken typeToken, IMetaDataImport2 * pImport )
5126 {
5127     SIZE_T myDicts; //either 0 or 1
5128
5129     _ASSERTE((TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5130              || (TypeFromToken(typeToken) == mdtTypeSpec));
5131
5132
5133     //for refs and specs, convert to a def.  This is a nop for defs.
5134     typeToken = ConvertToTypeDef(typeToken, pImport);
5135
5136     _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5137
5138
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;
5145
5146     pImport->CloseEnum(hEnum);
5147
5148     //get my parent for the recursive call.
5149     mdToken parent;
5150     IfFailThrow(pImport->GetTypeDefProps(typeToken, NULL, 0, NULL, NULL, &parent));
5151     return myDicts + (IsNilToken(parent) ? 0 : CountDictionariesInClass(parent, pImport));
5152 }
5153
5154 const NativeImageDumper::EnumMnemonics s_Subsystems[] =
5155 {
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"))
5165 #undef S_ENTRY
5166 };
5167
5168 const NativeImageDumper::EnumMnemonics s_CorCompileHdrFlags[] = 
5169 {
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),
5174 #undef CCHF_ENTRY
5175 };
5176
5177 const NativeImageDumper::EnumMnemonics s_CorPEKind[] =
5178 {
5179 #define CPEK_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5180     CPEK_ENTRY(peNot),
5181     CPEK_ENTRY(peILonly),
5182     CPEK_ENTRY(pe32BitRequired),
5183     CPEK_ENTRY(pe32Plus),
5184     CPEK_ENTRY(pe32Unmanaged),
5185     CPEK_ENTRY(pe32BitPreferred)
5186 #undef CPEK_ENTRY
5187 };
5188 const NativeImageDumper::EnumMnemonics s_IFH_Machine[] =
5189 {
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),
5195 #undef IFH_ENTRY
5196 };
5197
5198 const NativeImageDumper::EnumMnemonics s_IFH_Characteristics[] =
5199 {
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),
5216 #undef IFH_ENTRY
5217 };
5218
5219 const NativeImageDumper::EnumMnemonics s_ImportSectionType[] = 
5220 {
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),
5229 #undef IST_ENTRY
5230 };
5231
5232 const NativeImageDumper::EnumMnemonics s_ImportSectionFlags[] = 
5233 {
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),
5238 #undef IST_FLAGS
5239 };
5240
5241 void NativeImageDumper::DumpNativeHeader()
5242 {
5243     PTR_CORCOMPILE_HEADER nativeHeader(m_decoder.GetNativeHeader());
5244
5245     IF_OPT(NATIVE_INFO)
5246     {
5247
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  )
5253
5254         m_display->StartStructure( "CORCOMPILE_HEADER",
5255                                    DPtrToPreferredAddr(nativeHeader),
5256                                    sizeof(*nativeHeader) );
5257
5258         DisplayWriteFieldUInt( Signature, nativeHeader->Signature, CORCOMPILE_HEADER, ALWAYS );
5259         DisplayWriteFieldUInt( MajorVersion, nativeHeader->MajorVersion, CORCOMPILE_HEADER, ALWAYS );
5260         DisplayWriteFieldUInt( MinorVersion, nativeHeader->MinorVersion, CORCOMPILE_HEADER, ALWAYS );
5261
5262         WRITE_NATIVE_FIELD(HelperTable);
5263
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 )
5271         {
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 );
5278
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 );
5283             
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
5291
5292         }
5293         DisplayEndArray( NULL, ALWAYS ); //delayLoads
5294
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);
5301
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);
5306         
5307         for( COUNT_T i = 0; i < numVirtualSections; ++i )
5308         {
5309             TempBuffer sectionNameBuf;
5310             TempBuffer sectionFlags;
5311             StackScratchBuffer scratch;
5312
5313             sectionNameBuf.Append(g_sectionNames[VirtualSectionData::VirtualSectionType(sects[i].SectionType)]);
5314
5315             EnumFlagsToString( sects[i].SectionType, s_virtualSectionFlags, dim(s_virtualSectionFlags),
5316                        W(" | "), sectionFlags);
5317
5318             sectionNameBuf.Append(W(" ["));
5319             sectionNameBuf.Append(sectionFlags);
5320             sectionNameBuf.Append(W("]"));
5321
5322             DisplayStartElement( "Section", SLIM_MODULE_TBLS );
5323             DisplayWriteElementString("Name", sectionNameBuf.GetANSI(scratch), SLIM_MODULE_TBLS);
5324
5325             DisplayWriteElementAddress( "Address",
5326                                         RvaToDisplay(sects[i].VirtualAddress),
5327                                         sects[i].Size,
5328                                         SLIM_MODULE_TBLS );
5329             DisplayEndElement( SLIM_MODULE_TBLS ); //Section
5330         }
5331         DisplayEndArray( "Total VirtualSections", SLIM_MODULE_TBLS );
5332
5333         WRITE_NATIVE_FIELD(EEInfoTable);
5334
5335 #undef WRITE_NATIVE_FIELD
5336         DisplayWriteFieldEnumerated( Flags, nativeHeader->Flags,
5337                                      CORCOMPILE_HEADER, s_CorCompileHdrFlags, W(", "),
5338                                      NATIVE_INFO );
5339
5340         DisplayWriteFieldEnumerated( PEKind, nativeHeader->PEKind,
5341                                      CORCOMPILE_HEADER, s_CorPEKind, W(", "),
5342                                      NATIVE_INFO );
5343
5344         DisplayWriteFieldEnumerated( COR20Flags, nativeHeader->COR20Flags,
5345                                      CORCOMPILE_HEADER, s_CorHdrFlags, W(", "),
5346                                      NATIVE_INFO );
5347
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 );
5355
5356         m_display->EndStructure(); //CORCOMPILE_HEADER
5357     }
5358 }
5359
5360 const NativeImageDumper::EnumMnemonics s_RelocType[] =
5361 {
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),
5367 #undef REL_ENTRY
5368 };
5369
5370 void NativeImageDumper::DumpBaseRelocs()
5371 {
5372     COUNT_T size;
5373     TADDR data;
5374
5375     data = m_decoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_BASERELOC, &size);
5376
5377     if (size != 0)
5378     {
5379         DisplayStartStructure( "Relocations", DataPtrToDisplay(data), size,
5380                                     ALWAYS );
5381
5382         while (size != 0)
5383         {
5384             IMAGE_BASE_RELOCATION * pBaseRelocation = dac_cast<DPTR(IMAGE_BASE_RELOCATION)>(data);
5385             _ASSERTE(size >= pBaseRelocation->SizeOfBlock);
5386             
5387             SIZE_T rel = sizeof(IMAGE_BASE_RELOCATION);
5388             while (rel < pBaseRelocation->SizeOfBlock)
5389             {
5390                 USHORT typeOffset = *PTR_USHORT(data + rel);
5391
5392                 DisplayStartElement( "Entry", ALWAYS );
5393
5394                 DisplayWriteElementPointer( "Address", RvaToDisplay(pBaseRelocation->VirtualAddress + (typeOffset & 0xFFF)), ALWAYS );
5395
5396                 DisplayWriteElementEnumerated( "Type", (typeOffset >> 12),
5397                                         s_RelocType, W(", "), ALWAYS );
5398
5399                 DisplayEndElement( ALWAYS ); //Entry
5400
5401                 rel += sizeof(USHORT);
5402             }
5403
5404             data += pBaseRelocation->SizeOfBlock;
5405             size -= pBaseRelocation->SizeOfBlock;
5406         }
5407
5408         DisplayEndStructure( ALWAYS ); //Relocations
5409     }
5410 }
5411
5412 void NativeImageDumper::DumpHelperTable()
5413 {
5414     COUNT_T size;
5415     TADDR data;
5416
5417     data = TO_TADDR(m_decoder.GetNativeHelperTable(&size));
5418     if( size != 0 )
5419     {
5420         DisplayStartStructure( "HelperTable", DataPtrToDisplay(data), size,
5421                                     ALWAYS );
5422
5423         TADDR curEntry   = data;
5424         TADDR tableEnd   = data + size;
5425
5426         while (curEntry < tableEnd)
5427         {
5428             DWORD dwHelper = *PTR_DWORD(curEntry);
5429
5430             int iHelper = (USHORT)dwHelper;
5431             _ASSERTE(iHelper < CORINFO_HELP_COUNT);
5432
5433             DisplayStartStructure( "Helper",
5434                                    DataPtrToDisplay(curEntry), (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN,
5435                                    ALWAYS );
5436
5437             DisplayWriteElementUInt( "dwHelper", dwHelper, ALWAYS );
5438             DisplayWriteElementString( "Name", g_helperNames[iHelper], ALWAYS );
5439
5440             DisplayEndStructure( ALWAYS ); //Helper
5441
5442             curEntry += (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN;
5443         }
5444
5445         DisplayEndStructure( ALWAYS ); //HelperTable
5446     }
5447 }
5448
5449 // TODO: fix these to work with the updated flags in MethodTable, AND to understand
5450 //       the new overloading of component size...
5451
5452 NativeImageDumper::EnumMnemonics s_MTFlagsLow[] =
5453 {
5454 #define MTFLAG_ENTRY(x) \
5455     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5456
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),
5482 #undef MTFLAG_ENTRY
5483 };
5484
5485 NativeImageDumper::EnumMnemonics s_MTFlagsHigh[] =
5486 {
5487 #define MTFLAG_ENTRY(x) \
5488     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5489
5490 #define MTFLAG_CATEGORY_ENTRY(x) \
5491     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_Mask, W("Category_") W(#x))
5492
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))
5495
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),
5504
5505     MTFLAG_CATEGORY_ENTRY(Interface),
5506     MTFLAG_CATEGORY_ENTRY(Unused_4),
5507     MTFLAG_CATEGORY_ENTRY(Unused_5),
5508     MTFLAG_CATEGORY_ENTRY(Unused_6),
5509
5510     MTFLAG_CATEGORY_ENTRY_WITH_MASK(Array, Array_Mask),
5511     MTFLAG_CATEGORY_ENTRY_WITH_MASK(IfArrayThenSzArray, IfArrayThenSzArray),
5512
5513 #undef MTFLAG_CATEGORY_ENTRY_WITH_MASK
5514 #undef MTFLAG_CATEGORY_ENTRY
5515
5516     MTFLAG_ENTRY(HasFinalizer),
5517     MTFLAG_ENTRY(IfNotInterfaceThenMarshalable),
5518 #if defined(FEATURE_COMINTEROP)
5519     MTFLAG_ENTRY(IfInterfaceThenHasGuidInfo),
5520 #endif
5521 #if defined(FEATURE_ICASTABLE)    
5522     MTFLAG_ENTRY(ICastable),
5523 #endif    
5524     MTFLAG_ENTRY(HasIndirectParent),
5525     MTFLAG_ENTRY(ContainsPointers),
5526     MTFLAG_ENTRY(HasTypeEquivalence),
5527 #if defined(FEATURE_COMINTEROP)
5528     MTFLAG_ENTRY(HasRCWPerTypeData),
5529 #endif
5530     MTFLAG_ENTRY(HasCriticalFinalizer),
5531     MTFLAG_ENTRY(Collectible),
5532     MTFLAG_ENTRY(ContainsGenericVariables),
5533 #if defined(FEATURE_COMINTEROP)
5534     MTFLAG_ENTRY(ComObject),
5535 #endif
5536     MTFLAG_ENTRY(HasComponentSize),
5537 #undef MTFLAG_ENTRY
5538 };
5539
5540
5541 NativeImageDumper::EnumMnemonics s_MTFlags2[] =
5542 {
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),
5559 #endif
5560     MTFLAG2_ENTRY(HasBoxedRegularStatics),
5561     MTFLAG2_ENTRY(HasSingleNonVirtualSlot),
5562     MTFLAG2_ENTRY(DependsOnEquivalentOrForwardedStructs),
5563 #undef MTFLAG2_ENTRY
5564 };
5565
5566 NativeImageDumper::EnumMnemonics s_WriteableMTFlags[] =
5567 {
5568 #define WMTFLAG_ENTRY(x) \
5569     NativeImageDumper::EnumMnemonics(MethodTableWriteableData::enum_flag_ ## x,\
5570                                      W(#x))
5571
5572         WMTFLAG_ENTRY(Unrestored),
5573         WMTFLAG_ENTRY(HasApproxParent),
5574         WMTFLAG_ENTRY(UnrestoredTypeKey),
5575         WMTFLAG_ENTRY(IsNotFullyLoaded),
5576         WMTFLAG_ENTRY(DependenciesLoaded),
5577
5578 #ifdef _DEBUG
5579         WMTFLAG_ENTRY(ParentMethodTablePointerValid),
5580 #endif
5581
5582         WMTFLAG_ENTRY(NGEN_IsFixedUp),
5583         WMTFLAG_ENTRY(NGEN_IsNeedsRestoreCached),
5584         WMTFLAG_ENTRY(NGEN_CachedNeedsRestore),
5585 #undef WMTFLAG_ENTRY
5586 };
5587
5588 static NativeImageDumper::EnumMnemonics s_CorElementType[] =
5589 {
5590 #define CET_ENTRY(x) NativeImageDumper::EnumMnemonics(ELEMENT_TYPE_ ## x, 0, W("ELEMENT_TYPE_") W(#x))
5591     CET_ENTRY(END),
5592     CET_ENTRY(VOID),
5593     CET_ENTRY(BOOLEAN),
5594     CET_ENTRY(CHAR),
5595     CET_ENTRY(I1),
5596     CET_ENTRY(U1),
5597     CET_ENTRY(I2),
5598     CET_ENTRY(U2),
5599     CET_ENTRY(I4),
5600     CET_ENTRY(U4),
5601     CET_ENTRY(I8),
5602     CET_ENTRY(U8),
5603     CET_ENTRY(R4),
5604     CET_ENTRY(R8),
5605     CET_ENTRY(STRING),
5606     CET_ENTRY(PTR),
5607     CET_ENTRY(BYREF),
5608     CET_ENTRY(VALUETYPE),
5609     CET_ENTRY(CLASS),
5610     CET_ENTRY(VAR),
5611     CET_ENTRY(ARRAY),
5612     CET_ENTRY(GENERICINST),
5613     CET_ENTRY(TYPEDBYREF),
5614     CET_ENTRY(VALUEARRAY_UNSUPPORTED),
5615     CET_ENTRY(I),
5616     CET_ENTRY(U),
5617     CET_ENTRY(R_UNSUPPORTED),
5618     CET_ENTRY(FNPTR),
5619     CET_ENTRY(OBJECT),
5620     CET_ENTRY(SZARRAY),
5621     CET_ENTRY(MVAR),
5622     CET_ENTRY(CMOD_REQD),
5623     CET_ENTRY(CMOD_OPT),
5624     CET_ENTRY(INTERNAL),
5625
5626     CET_ENTRY(SENTINEL),
5627     CET_ENTRY(PINNED),
5628 #undef CET_ENTRY
5629 };
5630
5631 void NativeImageDumper::DoWriteFieldCorElementType( const char * name,
5632                                                     unsigned offset,
5633                                                     unsigned fieldSize,
5634                                                     CorElementType type )
5635 {
5636     TempBuffer buf;
5637     EnumFlagsToString( (int)type, s_CorElementType, dim(s_CorElementType),
5638                        W(""), buf );
5639     m_display->WriteFieldEnumerated( name, offset, fieldSize, (unsigned)type,
5640                                      (const WCHAR *) buf );
5641
5642 }
5643
5644 static NativeImageDumper::EnumMnemonics s_CorTypeAttr[] =
5645 {
5646 #define CTA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5647
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
5658
5659     CTA_ENTRY(tdSequentialLayout),
5660     CTA_ENTRY(tdExplicitLayout),
5661
5662     CTA_ENTRY(tdInterface),
5663
5664     CTA_ENTRY(tdAbstract),
5665     CTA_ENTRY(tdSealed),
5666     CTA_ENTRY(tdSpecialName),
5667
5668     CTA_ENTRY(tdImport),
5669     CTA_ENTRY(tdSerializable),
5670
5671     CTA_ENTRY(tdUnicodeClass),
5672     CTA_ENTRY(tdAutoClass),
5673     CTA_ENTRY(tdCustomFormatClass),
5674     CTA_ENTRY(tdCustomFormatMask),
5675
5676     CTA_ENTRY(tdBeforeFieldInit),
5677     CTA_ENTRY(tdForwarder),
5678
5679     CTA_ENTRY(tdRTSpecialName),
5680     CTA_ENTRY(tdHasSecurity)
5681 #undef CTA_ENTRY
5682 };
5683 static NativeImageDumper::EnumMnemonics s_VMFlags[] =
5684 {
5685 #define VMF_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClass::VMFLAG_ ## x, W(#x) )
5686
5687 #ifdef FEATURE_READYTORUN
5688         VMF_ENTRY(LAYOUT_DEPENDS_ON_OTHER_MODULES),
5689 #endif
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),
5695
5696         VMF_ENTRY(HASOVERLAYEDFIELDS),
5697         VMF_ENTRY(HAS_FIELDS_WHICH_MUST_BE_INITED),
5698         VMF_ENTRY(UNSAFEVALUETYPE),
5699
5700         VMF_ENTRY(BESTFITMAPPING_INITED),
5701         VMF_ENTRY(BESTFITMAPPING),
5702         VMF_ENTRY(THROWONUNMAPPABLECHAR),
5703
5704         VMF_ENTRY(NO_GUID),
5705         VMF_ENTRY(HASNONPUBLICFIELDS),
5706         VMF_ENTRY(PREFER_ALIGN8),
5707
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
5715
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),
5723 #endif        
5724 #undef VMF_ENTRY
5725 };
5726 static NativeImageDumper::EnumMnemonics s_CorFieldAttr[] =
5727 {
5728 #define CFA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5729
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
5739
5740     CFA_ENTRY(fdStatic),
5741     CFA_ENTRY(fdInitOnly),
5742     CFA_ENTRY(fdLiteral),
5743     CFA_ENTRY(fdNotSerialized),
5744
5745     CFA_ENTRY(fdSpecialName),
5746
5747     CFA_ENTRY(fdPinvokeImpl),
5748
5749     CFA_ENTRY(fdRTSpecialName),
5750     CFA_ENTRY(fdHasFieldMarshal),
5751     CFA_ENTRY(fdHasDefault),
5752     CFA_ENTRY(fdHasFieldRVA),
5753 #undef CFA_ENTRY
5754 };
5755
5756 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDFlag2[] =
5757 {
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),
5763 #undef MDF2_ENTRY
5764 };
5765
5766 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDC[] =
5767 {
5768 #define MDC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5769
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
5782
5783     MDC_ENTRY(mdcHasNonVtableSlot),
5784     MDC_ENTRY(mdcMethodImpl),
5785
5786     // Method is static
5787     MDC_ENTRY(mdcStatic),
5788
5789     MDC_ENTRY(mdcDuplicate),
5790     MDC_ENTRY(mdcVerifiedState),
5791     MDC_ENTRY(mdcVerifiable),
5792     MDC_ENTRY(mdcNotInline),
5793     MDC_ENTRY(mdcSynchronized),
5794     MDC_ENTRY(mdcRequiresFullSlotNumber),
5795 #undef MDC_ENTRY
5796 };
5797
5798
5799
5800 void NativeImageDumper::DumpTypes(PTR_Module module)
5801 {
5802     _ASSERTE(CHECK_OPT(EECLASSES) || CHECK_OPT(METHODTABLES)
5803              || CHECK_OPT(TYPEDESCS));
5804
5805     IF_OPT_OR3(METHODTABLES, EECLASSES, TYPEDESCS)
5806         m_display->StartCategory( "Types" );
5807     IF_OPT(METHODTABLES)
5808     {
5809         //there may be duplicates in the list.  Remove them before moving on.
5810         COUNT_T mtCount = m_discoveredMTs.GetCount();
5811
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());
5821 #endif
5822
5823         DisplayStartArray( "MethodTables", NULL, METHODTABLES );
5824         for(COUNT_T i = 0; i < mtCount; ++i )
5825         {
5826             PTR_MethodTable mt = m_discoveredMTs[i];
5827             if( mt == NULL )
5828                 continue;
5829             DumpMethodTable( mt, "MethodTable", module );
5830         }
5831
5832         DisplayEndArray( "Total MethodTables", METHODTABLES );
5833
5834         DisplayStartArray( "MethodTableSlotChunks", NULL, METHODTABLES );
5835         {
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());
5845 #endif
5846             
5847             for (COUNT_T i = 0; i < slotChunkCount; ++i)
5848             {
5849                 DumpMethodTableSlotChunk(m_discoveredSlotChunks[i].addr,
5850                                          m_discoveredSlotChunks[i].nSlots,
5851                                          m_discoveredSlotChunks[i].isRelative);
5852             }
5853         }
5854         DisplayEndArray( "Total MethodTableSlotChunks", METHODTABLES );
5855     }
5856     IF_OPT(EECLASSES)
5857     {
5858         DisplayStartArray( "EEClasses", NULL, EECLASSES );
5859
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());
5871 #endif
5872
5873         for(COUNT_T i = 0; i < clazzCount; ++i )
5874         {
5875             PTR_MethodTable mt = m_discoveredClasses[i];
5876             if( mt == NULL )
5877                 continue;
5878             DumpEEClassForMethodTable( mt );
5879         }
5880
5881         DisplayEndArray( "Total EEClasses", EECLASSES ); //EEClasses
5882
5883     }
5884     IF_OPT(TYPEDESCS)
5885     {
5886         DisplayStartArray( "TypeDescs", NULL, TYPEDESCS );
5887
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());
5900 #endif
5901
5902         for(COUNT_T i = 0; i < tdCount; ++i )
5903         {
5904             PTR_TypeDesc td = m_discoveredTypeDescs[i];
5905             if( td == NULL )
5906                 continue;
5907             DumpTypeDesc( td );
5908         }
5909
5910         DisplayEndArray( "Total TypeDescs", TYPEDESCS ); //EEClasses
5911
5912     }
5913     IF_OPT_OR3(EECLASSES, METHODTABLES, TYPEDESCS)
5914         m_display->EndCategory(); //Types
5915 }
5916
5917 PTR_EEClass NativeImageDumper::GetClassFromMT( PTR_MethodTable mt )
5918 {
5919     /* REVISIT_TODO Tue 10/11/2005
5920      * Handle fixups
5921      */
5922     _ASSERTE( mt->IsClassPointerValid() );
5923     PTR_EEClass clazz( mt->GetClass() );
5924     return clazz;
5925 }
5926 PTR_MethodTable NativeImageDumper::GetParent( PTR_MethodTable mt )
5927 {
5928     /* REVISIT_TODO Thu 12/01/2005
5929      * Handle fixups
5930      */
5931     PTR_MethodTable parent( ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent()) );
5932     _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(parent)));
5933     return parent;
5934 }
5935
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 )
5939 {
5940     SIZE_T fieldCount = 0;
5941
5942     HCORENUM hEnum = NULL;
5943
5944     const Dependency * dep = GetDependencyFromMT(mt);
5945     mdToken classToken = mt->GetCl();
5946
5947     _ASSERTE(dep);
5948     _ASSERTE(dep->pImport);
5949
5950     //Arrays have no token.
5951     if( RidFromToken(classToken) == 0 )
5952         return 0;
5953
5954     for (;;)
5955     {
5956         mdToken fields[1];
5957         ULONG numFields;
5958
5959         IfFailThrow(dep->pImport->EnumFields( &hEnum, classToken, fields,
5960                                        1, &numFields));
5961
5962         if (numFields == 0)
5963             break;
5964
5965         DWORD dwAttr;
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) )
5970             ++fieldCount;
5971     }
5972     dep->pImport->CloseEnum(hEnum);
5973     return fieldCount;
5974 }
5975 const NativeImageDumper::Dependency*
5976 NativeImageDumper::GetDependencyFromMT( PTR_MethodTable mt )
5977 {
5978     if( !mt->IsClassPointerValid() )
5979     {
5980         //This code will not work for out of module dependencies.
5981         _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))));
5982
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);
5987     }
5988     PTR_Module module = mt->GetModule();
5989     if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
5990     {
5991         unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
5992         return GetDependencyForFixup(rva);
5993     }
5994     return GetDependencyForModule(module);
5995 }
5996 const NativeImageDumper::Dependency*
5997 NativeImageDumper::GetDependencyFromFD( PTR_FieldDesc fd )
5998 {
5999     PTR_MethodTable mt = fd->GetApproxEnclosingMethodTable();
6000     if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6001     {
6002         //This code will not work for out of module dependencies.
6003         _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(fd))));
6004
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);
6009     }
6010     return GetDependencyFromMT(mt);
6011 }
6012 const NativeImageDumper::Dependency*
6013 NativeImageDumper::GetDependencyFromMD( PTR_MethodDesc md )
6014 {
6015     PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
6016     PTR_MethodTable mt = chunk->GetMethodTable();
6017     if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6018     {
6019         //This code will not work for out of module dependencies.
6020         _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6021
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);
6026     }
6027     return GetDependencyFromMT(mt);
6028 }
6029
6030 BOOL NativeImageDumper::DoWriteFieldAsFixup( const char * name,
6031                                              unsigned offset,
6032                                              unsigned fieldSize, TADDR fixup)
6033 {
6034     if( !CORCOMPILE_IS_POINTER_TAGGED(fixup) )
6035         return FALSE;
6036     if( UINT_MAX == offset )
6037         m_display->StartVStructure( name );
6038     else
6039         m_display->StartVStructureWithOffset( name, offset, fieldSize );
6040
6041     WriteElementsFixupBlob( NULL, fixup );
6042     m_display->EndVStructure(); //name
6043     return TRUE;
6044 }
6045
6046 void AppendTypeQualifier( CorElementType kind, DWORD rank, SString& buf )
6047 {
6048     switch( kind )
6049     {
6050     case ELEMENT_TYPE_BYREF :
6051         buf.Append( W("&") );
6052         break;
6053     case ELEMENT_TYPE_PTR :
6054         buf.Append( W("*") );
6055         break;
6056     case ELEMENT_TYPE_SZARRAY :
6057         buf.Append( W("[]") );
6058         break;
6059     case ELEMENT_TYPE_ARRAY :        
6060         if( rank == 1 )
6061         {
6062             buf.Append( W("[*]") );
6063         }
6064         else
6065         {
6066             buf.Append( W("[") );
6067             for( COUNT_T i = 0; i < rank; ++i )
6068                 buf.Append( W(","));
6069             buf.Append( W("]") );
6070         }
6071         break;
6072     default :
6073         break;
6074     }
6075 }
6076 void NativeImageDumper::TypeDescToString( PTR_TypeDesc td, SString& buf )
6077 {
6078     _ASSERTE(!(PTR_TO_TADDR(td) & 0x2));
6079     if( td->IsGenericVariable() )
6080     {
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)) )
6087         {
6088             if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(td))))
6089             {
6090                 //this is an RVA from another hardbound dependency.  We cannot decode it
6091                 buf.Append(W("OUT_OF_MODULE_FIXUP"));
6092                 return;
6093             }
6094             else
6095             {
6096                 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
6097                 pImport = GetDependencyForFixup(rva)->pImport;
6098             }
6099         }
6100         else
6101         {
6102             pImport = GetDependencyForModule(module)->pImport;
6103         }
6104         AppendTokenName(token, buf, pImport);
6105     }
6106     else if( ELEMENT_TYPE_FNPTR == td->GetInternalCorElementType() )
6107     {
6108         PTR_FnPtrTypeDesc fptd( PTR_TO_TADDR(td) );
6109         buf.Append( W("(fnptr)") );
6110     }
6111     else if( td->HasTypeParam() || td->IsArray() )
6112     {
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?
6118          */
6119         unsigned rank;
6120         if( td->IsArray()  )
6121         {
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)) )
6126             {
6127                 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(ptd))))
6128                 {
6129                     //this is an RVA from another hardbound dependency.  We cannot decode it
6130                     buf.Append(W("OUT_OF_MODULE_FIXUP"));
6131                 }
6132                 else
6133                 {
6134                     RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6135                     FixupBlobToString(rva, buf);
6136                 }
6137                 return;
6138             }
6139             else
6140             {
6141                 _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) );
6142                 MethodTableToString( mt, buf );
6143                 rank = PTR_ArrayTypeDesc(PTR_TO_TADDR(ptd))->GetRank();
6144             }
6145         }
6146         else
6147         {
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);
6153             rank = 0;
6154         }
6155         AppendTypeQualifier( td->GetInternalCorElementType(), rank, buf );
6156     }
6157     else
6158     {
6159         //generic typedesc?
6160         EnumFlagsToString( (int)td->GetInternalCorElementType(), s_CorElementType, dim(s_CorElementType),
6161                            W(""), buf );
6162     }
6163 }
6164 void NativeImageDumper::TypeHandleToString( TypeHandle th, SString& buf )
6165 {
6166     TADDR arg = th.AsTAddr();
6167     /* REVISIT_TODO Thu 10/5/2006
6168      * Is this constant somewhere?
6169      */
6170     //0x2 is the subtle hint that this is a typedesc.  code:TypeHandle::AsTypeDesc
6171     if( arg & 0x2 )
6172     {
6173         PTR_TypeDesc argTD( arg & ~0x2 );
6174         TypeDescToString( argTD, buf );
6175     }
6176     else
6177     {
6178         PTR_MethodTable argMT( th.AsTAddr() );
6179         MethodTableToString( argMT, buf );
6180     }
6181 }
6182
6183 void NativeImageDumper::DoWriteFieldTypeHandle( const char * name,
6184                                                 unsigned offset,
6185                                                 unsigned fieldSize,
6186                                                 TypeHandle th )
6187 {
6188     TempBuffer buf;
6189     TADDR ptr = th.AsTAddr();
6190     if( DoWriteFieldAsFixup(name, offset, fieldSize, th.AsTAddr() ) )
6191         return;
6192     else
6193     {
6194         TypeHandleToString(th, buf);
6195
6196         buf.Append( W(" (from TypeHandle)") );
6197         /* REVISIT_TODO Fri 10/14/2005
6198          * Do a better job of this
6199          */
6200         if( offset == UINT_MAX )
6201         {
6202             m_display->WriteElementPointerAnnotated( name,
6203                                                      DataPtrToDisplay(ptr),
6204                                                      (const WCHAR*) buf );
6205         }
6206         else
6207         {
6208             m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6209                                                    DataPtrToDisplay(ptr),
6210                                                    (const WCHAR*) buf );
6211         }
6212     }
6213 }
6214 void NativeImageDumper::WriteElementTypeHandle( const char * name,
6215                                                 TypeHandle th )
6216 {
6217     DoWriteFieldTypeHandle( name, UINT_MAX, UINT_MAX, th );
6218 }
6219
6220 void NativeImageDumper::DoDumpFieldStub( PTR_Stub stub, unsigned offset,
6221                                          unsigned fieldSize, const char * name )
6222 {
6223     _ASSERTE(CHECK_OPT(EECLASSES));
6224     if( stub == NULL )
6225     {
6226         m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6227     }
6228     else
6229     {
6230         m_display->StartStructureWithOffset( name, offset, fieldSize,
6231                                              DPtrToPreferredAddr(stub),
6232                                              sizeof(*stub) );
6233         /* REVISIT_TODO Fri 10/14/2005
6234          * Dump stub
6235          */
6236         m_display->EndStructure();
6237     }
6238 }
6239
6240 #ifdef FEATURE_COMINTEROP
6241 void NativeImageDumper::DoDumpComPlusCallInfo( PTR_ComPlusCallInfo compluscall )
6242 {
6243     m_display->StartStructure( "ComPlusCallInfo",
6244                                DPtrToPreferredAddr(compluscall),
6245                                sizeof(*compluscall) );
6246
6247     DisplayWriteFieldPointer( m_pILStub, compluscall->m_pILStub,
6248                    ComPlusCallInfo, ALWAYS);
6249     /* REVISIT_TODO Fri 12/16/2005
6250      * Coverage read stub?
6251      */
6252     WriteFieldMethodTable(m_pInterfaceMT,
6253                           compluscall->m_pInterfaceMT,
6254                           ComPlusCallInfo, ALWAYS);
6255
6256     PTR_MethodDesc pEventProviderMD = PTR_MethodDesc((TADDR)compluscall->m_pEventProviderMD);
6257     WriteFieldMethodDesc(m_pEventProviderMD,
6258                          pEventProviderMD,
6259                          ComPlusCallInfo, ALWAYS);
6260     DisplayWriteFieldInt( m_cachedComSlot, compluscall->m_cachedComSlot,
6261                           ComPlusCallInfo, ALWAYS );
6262
6263     /* REVISIT_TODO Fri 12/16/2005
6264      * Dump these as mnemonics
6265      */
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 );
6271
6272 #ifdef _TARGET_X86_
6273     DisplayWriteFieldInt( m_cbStackArgumentSize, compluscall->m_cbStackArgumentSize,
6274                           ComPlusCallInfo, ALWAYS );
6275
6276     DisplayWriteFieldPointer( m_pRetThunk,
6277                               DataPtrToDisplay((TADDR)compluscall->m_pRetThunk),
6278                               ComPlusCallInfo, ALWAYS );
6279 #endif
6280     m_display->EndStructure(); //ComPlusCallInfo
6281 }
6282 #endif // FEATURE_COMINTEROP
6283
6284 void NativeImageDumper::DoWriteFieldStr( PTR_BYTE ptr, const char * name,
6285                                          unsigned offset, unsigned fieldSize )
6286 {
6287     if( ptr == NULL )
6288     {
6289         if( UINT_MAX == offset )
6290             m_display->WriteElementPointer( name, NULL );
6291         else
6292             m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6293     }
6294     else
6295     {
6296         /* REVISIT_TODO Wed 03/22/2006
6297          * Obviously this does the wrong thing for UTF-8.
6298          */
6299         TempBuffer buf;
6300         BYTE b;
6301         TADDR taddr = DPtrToPreferredAddr(ptr);
6302         PTR_BYTE current = ptr;
6303         /* REVISIT_TODO Mon 03/27/2006
6304          * Actually handle UTF-8 properly
6305          */
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.
6310          */
6311         if( UINT_MAX == offset )
6312         {
6313             m_display->StartStructure( name, DataPtrToDisplay(taddr),
6314                                        current - ptr );
6315         }
6316         else
6317         {
6318             m_display->StartStructureWithOffset( name, offset, fieldSize,
6319                                                  DataPtrToDisplay(taddr),
6320                                                  current - ptr );
6321         }
6322         DisplayWriteElementStringW( "Value", (const WCHAR *)buf, ALWAYS );
6323         m_display->EndStructure();
6324         /*
6325         m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6326                                                taddr, (const WCHAR *)buf );
6327                                                */
6328     }
6329 }
6330 void NativeImageDumper::WriteFieldDictionaryLayout(const char * name,
6331                                                    unsigned offset,
6332                                                    unsigned fieldSize,
6333                                                    PTR_DictionaryLayout layout,
6334                                                    IMetaDataImport2 * import)
6335 {
6336     if( layout == NULL )
6337     {
6338         m_display->WriteFieldPointer(name, NULL, offset, fieldSize);
6339         return;
6340     }
6341     m_display->StartVStructureWithOffset( name, offset, fieldSize );
6342     DisplayStartArray( "DictionaryLayouts", NULL, ALWAYS );
6343     do
6344     {
6345         DisplayStartStructure( "DictionaryLayout", DPtrToPreferredAddr(layout),
6346                                sizeof(DictionaryLayout)
6347                                + sizeof(DictionaryEntryLayout)
6348                                * (layout->m_numSlots - 1), ALWAYS );
6349
6350
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 )
6357         {
6358             PTR_DictionaryEntryLayout entry( PTR_HOST_MEMBER_TADDR(DictionaryLayout, layout, m_slots) + (i * sizeof(DictionaryEntryLayout)) );
6359             DisplayStartStructure( "DictionaryEntryLayout",
6360                                    DPtrToPreferredAddr(entry), sizeof(*entry),
6361                                    ALWAYS );
6362             const char * kind = NULL;
6363             switch( entry->GetKind() )
6364             {
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);
6373 #undef KIND_ENTRY
6374             default:
6375                 _ASSERTE( !"unreachable" );
6376             }
6377             DisplayWriteElementString( "Kind", kind, ALWAYS );
6378             DisplayWriteElementPointer( "Signature", DPtrToPreferredAddr(entry->m_signature), ALWAYS );
6379             DisplayEndStructure( ALWAYS ); //DictionaryEntryLayout
6380         }
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
6386
6387
6388     DisplayEndVStructure( ALWAYS ); // name
6389 }
6390 void NativeImageDumper::DoWriteFieldFieldDesc( const char * name,
6391                                                unsigned offset,
6392                                                unsigned fieldSize,
6393                                                PTR_FieldDesc fd )
6394 {
6395     if( fd == NULL )
6396     {
6397         m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6398     }
6399     else
6400     {
6401         TempBuffer buf;
6402         FieldDescToString( fd, buf );
6403         m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6404                                                DPtrToPreferredAddr(fd),
6405                                                (const WCHAR*) buf );
6406     }
6407
6408 }
6409 void NativeImageDumper::DoWriteFieldMethodDesc( const char * name,
6410                                                 unsigned offset,
6411                                                 unsigned fieldSize,
6412                                                 PTR_MethodDesc md )
6413 {
6414     if( md == NULL )
6415     {
6416         m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6417     }
6418     else if( DoWriteFieldAsFixup(name, offset, fieldSize, PTR_TO_TADDR(md)) )
6419     {
6420         return;
6421     }
6422     else
6423     {
6424         TempBuffer buf;
6425         MethodDescToString( md, buf );
6426         m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6427                                                DPtrToPreferredAddr(md),
6428                                                (const WCHAR*) buf );
6429     }
6430 }
6431
6432 void NativeImageDumper::EntryPointToString( TADDR pEntryPoint,
6433                                             SString& buf )
6434 {
6435     const Dependency * dependency = GetDependencyForPointer(pEntryPoint);
6436
6437     PTR_MethodDesc md;
6438     if (dependency->pModule->IsZappedPrecode(pEntryPoint))
6439     {
6440         md = dac_cast<PTR_MethodDesc>(Precode::GetPrecodeFromEntryPoint(pEntryPoint)->GetMethodDesc());
6441     }
6442     else
6443     {
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()));
6447
6448         for (int iRange = 0; iRange < 2; iRange++)
6449         {
6450             if (pNgenLayout->m_CodeSections[iRange].IsInRange(pEntryPoint))
6451             {
6452                 int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1);
6453                 if (MethodIndex >= 0)
6454                 {
6455 #ifdef WIN64EXCEPTIONS
6456                     while (pNgenLayout->m_MethodDescs[iRange][MethodIndex] == 0)
6457                         MethodIndex--;
6458 #endif
6459
6460                     PTR_RUNTIME_FUNCTION pRuntimeFunction = pNgenLayout->m_pRuntimeFunctions[iRange] + MethodIndex;
6461
6462                     md = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase())); 
6463                     break;
6464                 }
6465             }
6466         }
6467     }
6468
6469     MethodDescToString(md, buf);
6470 }
6471
6472 void NativeImageDumper::MethodDescToString( PTR_MethodDesc md,
6473                                             SString& buf )
6474 {
6475     if( md == NULL )
6476         buf.Append( W("mdMethodDefNil") );
6477     else if( md->IsILStub() )
6478         buf.AppendUTF8(md->AsDynamicMethodDesc()->GetName());
6479     else
6480     {
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;
6484
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
6489         //to MD.
6490         PTR_MethodTable mt = chunk->GetMethodTable();
6491         const Dependency * dependency;
6492         if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6493         {
6494             //This code will not work for out of module dependencies.
6495             _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6496
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.
6500         }
6501         else
6502             dependency = GetDependencyFromMT(mt);
6503
6504         _ASSERTE(dependency);
6505
6506
6507         /* REVISIT_TODO Fri 10/13/2006
6508          * Don't I need the array type name here?
6509          */
6510         _ASSERTE(dependency->pImport);
6511         if( md->GetClassification() == mcArray )
6512         {
6513
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) )
6518             {
6519                 AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6520                                  m_manifestImport );
6521                 tempName.Append(W("!"));
6522             }
6523
6524             _ASSERTE(PTR_TO_TADDR(mt));
6525             MethodTableToString( mt, tempName );
6526             tempName.Append( W("::") );
6527
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() );
6532         }
6533         else
6534         {
6535             //if we have a MethodTable, use that and compose the name
6536             //ourselves.  That way we can get generic arguments.
6537             if( mt )
6538             {
6539                 ULONG size;
6540                 MethodTableToString( mt, tempName );
6541                 tempName.Append( W("::") );
6542                 IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(), NULL, bigBuffer,
6543                                                                 bigBufferSize, &size, NULL, NULL, NULL, NULL,
6544                                                                 NULL));
6545                 tempName.Append(bigBuffer);
6546             }
6547             else
6548             {
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) )
6553                 {
6554                     AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6555                                      m_manifestImport );
6556                     tempName.Append(W("!"));
6557                 }
6558                 AppendTokenName( md->GetMemberDef(), tempName, dependency->pImport );
6559             }
6560
6561             if( mcInstantiated == md->GetClassification() )
6562             {
6563                 PTR_InstantiatedMethodDesc imd(PTR_TO_TADDR(md));
6564                 unsigned numArgs = imd->m_wNumGenericArgs;
6565                 PTR_Dictionary dict(imd->IMD_GetMethodDictionary());
6566                 if( dict != NULL )
6567                 {
6568                     DictionaryToArgString( dict, numArgs, tempName );
6569                 }
6570             }
6571
6572             PCCOR_SIGNATURE pvSigBlob;
6573             ULONG cbSigBlob;
6574             IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(),
6575                                                             NULL,
6576                                                             NULL,
6577                                                             0,
6578                                                             NULL,
6579                                                             NULL,
6580                                                             &pvSigBlob,
6581                                                             &cbSigBlob,
6582                                                             NULL,
6583                                                             NULL));
6584
6585
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 );
6594         }
6595         buf.Append(tempName);
6596     }
6597 }
6598 void NativeImageDumper::WriteElementMethodDesc( const char * name,
6599                                                 PTR_MethodDesc md )
6600 {
6601     if( md == NULL )
6602     {
6603         m_display->WriteElementPointer( name, NULL );
6604     }
6605     else
6606     {
6607         TempBuffer buf;
6608         MethodDescToString( md, buf );
6609         m_display->WriteElementPointerAnnotated( name, DPtrToPreferredAddr(md),
6610                                                  (const WCHAR*) buf );
6611     }
6612 }
6613 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, SString& buf )
6614 {
6615     FieldDescToString( fd, mdFieldDefNil, buf );
6616 }
6617 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, mdFieldDef tok,
6618                                            SString& buf )
6619 {
6620     IF_OPT(DISABLE_NAMES)
6621     {
6622         buf.Append( W("Disabled") );
6623         return;
6624     }
6625     if( fd == NULL )
6626     {
6627         if( tok == mdFieldDefNil )
6628             buf.Append( W("mdFieldDefNil") );
6629         else
6630             AppendTokenName( tok, buf );
6631     }
6632     else
6633     {
6634         _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(fd)));
6635         IMetaDataImport2 * importMD = NULL;
6636         if( !isInRange(PTR_TO_TADDR(fd)) )
6637         {
6638             const Dependency * dependency = GetDependencyFromFD(fd);
6639             _ASSERTE(dependency);
6640             AppendTokenName( dependency->entry->dwAssemblyRef, buf,
6641                              m_manifestImport );
6642             buf.Append(W("!"));
6643             importMD = dependency->pImport;
6644             _ASSERTE(importMD);
6645
6646         }
6647         else
6648         {
6649             importMD = m_import;
6650         }
6651         AppendTokenName( fd->GetMemberDef(), buf, importMD );
6652     }
6653 }
6654
6655 void NativeImageDumper::DoWriteFieldAsHex( const char * name, unsigned offset,
6656                                            unsigned fieldSize, PTR_BYTE ptr,
6657                                            unsigned dataLen )
6658 {
6659     TempBuffer buffer;
6660     for( unsigned i = 0; i < dataLen; ++i )
6661     {
6662         unsigned char b = ptr[i];
6663         buffer.AppendPrintf( W("%02x%02x"), (b & 0xf0) >> 4, b & 0xf );
6664     }
6665     if( offset == UINT_MAX )
6666     {
6667         m_display->WriteElementStringW( name, (const WCHAR *)buffer );
6668     }
6669     else
6670     {
6671         m_display->WriteFieldStringW( name, offset, fieldSize,
6672                                       (const WCHAR *)buffer );
6673     }
6674 }
6675 void NativeImageDumper::WriteElementMDToken( const char * name, mdToken token )
6676 {
6677     DoWriteFieldMDToken( name, UINT_MAX, UINT_MAX, token );
6678 }
6679 void NativeImageDumper::DoWriteFieldMDToken( const char * name, unsigned offset,
6680                                              unsigned fieldSize, mdToken token,
6681                                              IMetaDataImport2 * import )
6682 {
6683     TempBuffer buf;
6684     if( RidFromToken(token) == mdTokenNil )
6685     {
6686         AppendNilToken( token, buf );
6687     }
6688     else
6689     {
6690         AppendToken( token, buf, import );
6691     }
6692     if( UINT_MAX == offset )
6693         m_display->WriteElementEnumerated( name, token, (const WCHAR *)buf );
6694     else
6695     {
6696         m_display->WriteFieldEnumerated(name, offset, fieldSize, token,
6697                                         (const WCHAR*)buf);
6698     }
6699 }
6700
6701 void NativeImageDumper::WriteElementMethodTable( const char * name,
6702                                                  PTR_MethodTable mt )
6703 {
6704     DoWriteFieldMethodTable( name, UINT_MAX, UINT_MAX, mt );
6705 }
6706 void NativeImageDumper::DoWriteFieldMethodTable( const char * name,
6707                                                  unsigned offset, 
6708                                                  unsigned fieldSize, 
6709                                                  PTR_MethodTable mt )
6710 {
6711     if( mt == NULL )
6712     {
6713         if( UINT_MAX == offset )
6714             m_display->WriteElementPointer( name, NULL );
6715         else
6716             m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6717     }
6718     else if( DoWriteFieldAsFixup( name, offset, fieldSize, PTR_TO_TADDR(mt) ) )
6719     {
6720         return;
6721     }
6722     else
6723     {
6724         TempBuffer buf;
6725         MethodTableToString( mt, buf );
6726         if( UINT_MAX == offset )
6727         {
6728
6729             m_display->WriteElementPointerAnnotated( name,
6730                                                      DPtrToPreferredAddr(mt),
6731                                                      (const WCHAR*) buf );
6732         }
6733         else
6734         {
6735             m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6736                                                    DPtrToPreferredAddr(mt),
6737                                                    (const WCHAR*) buf );
6738         }
6739     }
6740 }
6741
6742 const char * s_VTSCallbackNames[] =
6743 {
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),
6749 #undef VTSCB_ENTRY
6750 };
6751 void NativeImageDumper::DumpFieldDesc( PTR_FieldDesc fd, const char * name )
6752 {
6753     DisplayStartStructure( name, DPtrToPreferredAddr(fd), sizeof(*fd),
6754                            ALWAYS );
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),
6763                                fd->m_isStatic );
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),
6770                                fd->m_isRVA );
6771
6772     {
6773         TempBuffer buf;
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 );
6780     }
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),
6788                               fd->m_dwOffset );
6789     DoWriteFieldCorElementType( "m_type",
6790                                 offsetof(FieldDesc, m_dword2),
6791                                 fieldsize(FieldDesc, m_dword2),
6792                                 (CorElementType)fd->m_type );
6793 #ifdef _DEBUG
6794     WriteFieldStr( m_debugName, PTR_BYTE(TO_TADDR(fd->m_debugName)),
6795                    FieldDesc, ALWAYS );
6796 #endif
6797     DisplayEndStructure( ALWAYS ); //name
6798 }
6799
6800 #ifdef _PREFAST_
6801 #pragma warning(push)
6802 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
6803 #endif
6804 void
6805 NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, 
6806                                     PTR_Module module )
6807 {
6808     _ASSERTE(NULL != mt);
6809     TADDR start, end;
6810     bool haveCompleteExtents = true;
6811     PTR_EEClass clazz = NULL;
6812     if( !mt->IsCanonicalMethodTable() && CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt->GetCanonicalMethodTable())) )
6813     {
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.
6818          */
6819         haveCompleteExtents = false;
6820         TempBuffer buf;
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 );
6823     }
6824     else if( !m_isMscorlibHardBound )
6825     {
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.
6829          */
6830         haveCompleteExtents = false;
6831     }
6832     if( haveCompleteExtents )
6833     {
6834         mt->GetSavedExtent(&start, &end);
6835         clazz = mt->GetClass();
6836     }
6837     else
6838     {
6839         start = PTR_TO_TADDR(mt);
6840         end = start + sizeof(*mt);
6841     }
6842     IF_OPT(METHODTABLES)
6843     {
6844         m_display->StartStructureWithNegSpace( name, DPtrToPreferredAddr(mt),
6845                                                DataPtrToDisplay(start), end - start );
6846     }
6847
6848     IF_OPT(METHODTABLES)
6849     {
6850         {
6851             TempBuffer buf;
6852             MethodTableToString( mt, buf );
6853             DisplayWriteElementStringW( "Name", (const WCHAR *)buf, ALWAYS );
6854         }
6855         if( mt->ContainsPointers() )
6856         {
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?
6861              */
6862             m_display->WriteFieldEmpty( "CGCDesc", ~size + 1, size );
6863         }
6864     }
6865
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"
6870      */
6871     if (mt->HasComponentSize())
6872     {
6873         DisplayWriteElementInt( "ComponentSize", mt->RawGetComponentSize(),
6874                                 METHODTABLES );
6875     }
6876     else
6877     {
6878         DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & 0xFFFF, MethodTable,
6879                                      s_MTFlagsLow, W(", "), METHODTABLES );
6880     }
6881
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
6885      * might be busted.
6886      */
6887     DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & ~0xFFFF, MethodTable,
6888                                  s_MTFlagsHigh, W(", "), METHODTABLES );
6889
6890     DisplayWriteFieldInt( m_BaseSize, mt->m_BaseSize, MethodTable,
6891                           METHODTABLES );
6892
6893     DisplayWriteFieldEnumerated( m_wFlags2, mt->m_wFlags2, MethodTable,
6894                                  s_MTFlags2, W(", "), METHODTABLES );
6895
6896     DisplayWriteFieldInt( m_wToken, mt->m_wToken, MethodTable,
6897                           METHODTABLES );
6898     DisplayWriteFieldInt( m_wNumVirtuals, mt->m_wNumVirtuals, MethodTable,
6899                           METHODTABLES );
6900     DisplayWriteFieldInt( m_wNumInterfaces, mt->m_wNumInterfaces, MethodTable,
6901                           METHODTABLES );
6902
6903
6904
6905     PTR_MethodTable parent = ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent());
6906     if( parent == NULL )
6907     {
6908         DisplayWriteFieldPointer( m_pParentMethodTable, NULL, MethodTable,
6909                                   METHODTABLES );
6910     }
6911     else
6912     {
6913         IF_OPT(METHODTABLES)
6914         {
6915             DoWriteFieldMethodTable( "m_pParentMethodTable",
6916                                      offsetof(MethodTable, m_pParentMethodTable), 
6917                                      fieldsize(MethodTable, m_pParentMethodTable), 
6918                                      mt->GetParentMethodTable() );
6919         }
6920     }
6921     DisplayWriteFieldPointer( m_pLoaderModule,
6922                               DPtrToPreferredAddr(mt->GetLoaderModule()),
6923                               MethodTable, METHODTABLES );
6924
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
6937
6938     if( !mt->IsCanonicalMethodTable() )
6939     {
6940         WriteFieldMethodTable( m_pCanonMT, mt->GetCanonicalMethodTable(),
6941                                MethodTable, METHODTABLES );
6942     }
6943     else
6944     {
6945         DisplayWriteFieldPointer( m_pEEClass, DPtrToPreferredAddr(mt->GetClass()),
6946                                   MethodTable, METHODTABLES );
6947     }
6948
6949     if( mt->IsArray() )
6950     {
6951         WriteFieldTypeHandle( m_ElementTypeHnd,
6952                               mt->GetApproxArrayElementTypeHandle(),
6953                               MethodTable, METHODTABLES );
6954     }
6955
6956     if( mt->HasPerInstInfo() && haveCompleteExtents )
6957     {
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);
6962
6963         DisplayStartStructure("GenericsDictInfo", DPtrToPreferredAddr(di), sizeof(*di), METHODTABLES);
6964
6965         DisplayWriteFieldInt( m_wNumDicts, di->m_wNumDicts, GenericsDictInfo,
6966                                 METHODTABLES );
6967         DisplayWriteFieldInt( m_wNumTyPars, di->m_wNumTyPars,
6968                                 GenericsDictInfo, METHODTABLES);
6969         DisplayEndStructure( METHODTABLES ); //GenericsDictInfo
6970
6971         DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo();
6972
6973         DisplayStartStructure( "PerInstInfo",
6974                                DPtrToPreferredAddr(perInstInfo),
6975                                mt->GetPerInstInfoSize(),
6976                                METHODTABLES );
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
6982          */
6983         PTR_Dictionary currentDictionary(mt->GetDictionary());
6984         if( currentDictionary != NULL )
6985         {
6986             PTR_DictionaryEntry entry(currentDictionary->EntryAddr(0));
6987             
6988             PTR_DictionaryLayout layout( clazz->GetDictionaryLayout() );
6989
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
6994                                    //entry.
6995                                    DictionaryLayout::GetFirstDictionaryBucketSize(mt->GetNumGenericArgs(), layout),
6996                                    METHODTABLES );
6997
6998             DisplayStartArrayWithOffset( m_pEntries, NULL, Dictionary,
6999                                          METHODTABLES );
7000
7001             /* REVISIT_TODO Thu 12/15/2005
7002              * use VERBOSE_TYPES here.
7003              */
7004             _ASSERTE(CHECK_OPT(METHODTABLES));
7005
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);
7009
7010             //now check for a layout.  If it is present, then there are more
7011             //entries.
7012             if( layout != NULL && (layout->GetNumUsedSlots() > 0) )
7013             {
7014                 unsigned numUsedSlots = layout->GetNumUsedSlots();
7015                 for( unsigned i = 0; i < numUsedSlots; ++i )
7016                 {
7017                     //DictionaryLayout::GetEntryLayout
7018                     PTR_DictionaryEntryLayout entryLayout(layout->GetEntryLayout(i));
7019
7020                     //Dictionary::GetSlotAddr
7021                     PTR_DictionaryEntry ent(currentDictionary->EntryAddr(mt->GetNumGenericArgs() + i));
7022
7023                     DumpDictionaryEntry( "Entry", entryLayout->GetKind(), ent );
7024                 }
7025             }
7026             if( layout != NULL )
7027             {
7028                 /* REVISIT_TODO Thu 12/15/2005
7029                  * Where is this data?
7030                  */
7031             }
7032             DisplayEndArray( "Total Per instance Info",
7033                              METHODTABLES ); //m_pEntries
7034             DisplayEndStructure( METHODTABLES ); //Dictionary
7035         }
7036         DisplayEndStructure( METHODTABLES ); //m_pPerInstInfo
7037     }
7038
7039 #ifdef _DEBUG
7040     WriteFieldStr( debug_m_szClassName,
7041                    PTR_BYTE(TO_TADDR(mt->debug_m_szClassName)), MethodTable,
7042                    METHODTABLES );
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
7047      */
7048     DisplayStartArrayWithOffset( m_pIMapDEBUG, NULL, MethodTable,
7049                                  METHODTABLES );
7050     DisplayEndArray( "Total Interfaces", METHODTABLES );
7051 #endif
7052 #endif
7053
7054     if( mt->HasDispatchMapSlot() )
7055     {
7056         PTR_DispatchMap dispatchMap(mt->GetDispatchMap());
7057
7058         DisplayStartStructure( "DispatchMap",
7059                                DPtrToPreferredAddr(dispatchMap),
7060                                DispatchMap::GetObjectSize(dispatchMap->GetMapSize()),
7061                                METHODTABLES );
7062
7063         IF_OPT(VERBOSE_TYPES )
7064         {
7065             DispatchMap::Iterator iter(mt);
7066             DisplayStartArray( "DispatchMap", NULL, VERBOSE_TYPES );
7067             while( iter.Next() )
7068             {
7069                 DispatchMapEntry * ent = iter.Entry();
7070
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() )
7077                 {
7078                     DisplayWriteElementFlag( "IsImplementedInterface",
7079                                              true, METHODTABLES );
7080                     DisplayWriteElementInt( "GetInterfaceNum",
7081                                             typeID.GetInterfaceNum(), METHODTABLES );
7082                 }
7083                 DisplayEndStructure( METHODTABLES ); //TypeID
7084                 m_display->WriteElementInt( "SlotNumber",
7085                                             ent->GetSlotNumber() );
7086                 DisplayWriteElementInt( "TargetSlotNumber",
7087                                         ent->GetSlotNumber(), METHODTABLES );
7088
7089                 m_display->EndElement(); //Entry
7090             }
7091             //DispatchMap
7092             DisplayEndArray("Total Dispatch Map Entries", METHODTABLES );
7093         }
7094         else
7095         {
7096             CoverageRead(PTR_TO_TADDR(dispatchMap),
7097                          DispatchMap::GetObjectSize(dispatchMap->GetMapSize()));
7098         }
7099
7100         DisplayEndStructure( METHODTABLES ); //DispatchMap
7101     }
7102
7103     IF_OPT( METHODTABLES )
7104     {
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));
7110
7111
7112         MethodTable::VtableIndirectionSlotIterator itIndirect = mt->IterateVtableIndirectionSlots();
7113         while (itIndirect.Next())
7114         {
7115             SlotChunk sc;
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);
7120         }
7121
7122         IF_OPT(VERBOSE_TYPES)
7123         {
7124             DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7125             for( unsigned i = 0; i < mt->GetNumVtableIndirections(); ++i )
7126             {
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)),
7133                                             ALWAYS );
7134                 DisplayWriteElementString( "Type", "chunk indirection",
7135                                            ALWAYS );
7136                 DisplayEndElement( ALWAYS ); //Slot
7137             }
7138
7139             if (mt->HasNonVirtualSlotsArray())
7140             {
7141                 DisplayStartElement( "Slot", ALWAYS );
7142                 DisplayWriteElementInt( "Index", -1, ALWAYS );
7143                 PTR_PCODE tgt = mt->GetNonVirtualSlotsArray();
7144                 DisplayWriteElementPointer( "Pointer",
7145                                             DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7146                                             ALWAYS );
7147                 DisplayWriteElementString( "Type", "non-virtual chunk indirection",
7148                                            ALWAYS );
7149                 DisplayEndElement( ALWAYS ); //Slot
7150
7151                 SlotChunk sc;
7152                 sc.addr = dac_cast<TADDR>(tgt);
7153                 sc.nSlots = (mt->GetNumVtableSlots() - mt->GetNumVirtuals());
7154                 sc.isRelative = false;
7155                 m_discoveredSlotChunks.AppendEx(sc);
7156             } 
7157             else if (mt->HasSingleNonVirtualSlot())
7158             {
7159                 DumpSlot((unsigned)-1, mt->GetSlot(mt->GetNumVirtuals()));
7160             }
7161
7162             DisplayEndList( ALWAYS ); //vtable
7163         }
7164         else
7165         {
7166             CoverageRead( PTR_TO_TADDR(mt) + mt->GetVtableOffset(),
7167                           mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t) );
7168
7169             if (mt->HasNonVirtualSlotsArray())
7170             {
7171                 CoverageRead( PTR_TO_TADDR(mt->GetNonVirtualSlotsArray()),
7172                               mt->GetNonVirtualSlotsArraySize() );
7173             }
7174             
7175         }
7176         DisplayEndStructure(ALWAYS); //Vtable
7177     }
7178
7179     if( mt->HasInterfaceMap() && CHECK_OPT(METHODTABLES) )
7180     {
7181         PTR_InterfaceInfo ifMap = mt->GetInterfaceMap();
7182         m_display->StartArrayWithOffset( "InterfaceMap",
7183                                          offsetof(MethodTable, m_pInterfaceMap),
7184                                          sizeof(void*),
7185                                          NULL );
7186         for( unsigned i = 0; i < mt->GetNumInterfaces(); ++i )
7187         {
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
7195         }
7196         DisplayEndArray( "Total InterfaceInfos",
7197                          METHODTABLES ); //InterfaceMap
7198     }
7199
7200     //rest of the optional members
7201
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)
7207         )
7208     {
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) );
7216
7217         PTR_FieldDesc fieldDescs = ReadPointerMaybeNull((GenericsStaticsInfo *) genStatics, &GenericsStaticsInfo::m_pFieldDescs);
7218         if( fieldDescs == NULL )
7219         {
7220             DisplayWriteFieldPointer( m_pFieldDescs, NULL, GenericsStaticsInfo,
7221                                       ALWAYS );
7222         }
7223         else
7224         {
7225             DisplayStartArrayWithOffset( m_pFieldDescs, NULL,
7226                                          GenericsStaticsInfo, ALWAYS );
7227             _ASSERTE(clazz == GetClassFromMT(mt));
7228             for( int i = 0; i < clazz->GetNumStaticFields(); ++i )
7229             {
7230                 PTR_FieldDesc fd = fieldDescs + i;
7231                 DumpFieldDesc( fd, "FieldDesc" );
7232             }
7233             DisplayEndArray( "Total Static Fields", ALWAYS ); // m_pFieldDescs
7234         }
7235         DisplayWriteFieldUInt( m_DynamicTypeID, (DWORD)genStatics->m_DynamicTypeID,
7236                                GenericsStaticsInfo, METHODTABLES );
7237
7238         DisplayEndStructure( METHODTABLES );//OptionalMember_GenericsStaticsInfo
7239
7240     }
7241
7242 #ifdef FEATURE_COMINTEROP
7243     if (haveCompleteExtents &&
7244         mt->HasGuidInfo() &&
7245         CHECK_OPT(METHODTABLES)
7246         )
7247     {
7248         PTR_GuidInfo guidInfo(*mt->GetGuidInfoPtr());
7249
7250         if (guidInfo != NULL)
7251         {
7252             m_display->StartStructureWithOffset( "OptionalMember_GuidInfo",
7253                                                  mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GuidInfo),
7254                                                  sizeof(void*),
7255                                                  DPtrToPreferredAddr(guidInfo),
7256                                                  sizeof(GuidInfo)
7257                                                  );
7258             TempBuffer buf;
7259             GuidToString( guidInfo->m_Guid, buf );
7260             DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
7261                                       ALWAYS );
7262             DisplayWriteFieldFlag( m_bGeneratedFromName,
7263                                    guidInfo->m_bGeneratedFromName,
7264                                    GuidInfo, ALWAYS );
7265             DisplayEndStructure( ALWAYS ); // OptionalMember_GuidInfo
7266         }
7267     }
7268
7269     if (haveCompleteExtents &&
7270         mt->HasCCWTemplate() 
7271         && CHECK_OPT(METHODTABLES)
7272         )
7273     {
7274         PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(*mt->GetCCWTemplatePtr()));
7275         m_display->WriteFieldPointer( "OptionalMember_CCWTemplate",
7276                                       mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_CCWTemplate),
7277                                       sizeof(void *),
7278                                       DPtrToPreferredAddr(ccwTemplate)
7279                                       );
7280     }
7281 #endif // FEATURE_COMINTEROP
7282
7283     DisplayEndStructure( METHODTABLES ); //MethodTable
7284 } // NativeImageDumper::DumpMethodTable
7285 #ifdef _PREFAST_
7286 #pragma warning(pop)
7287 #endif
7288
7289 void
7290 NativeImageDumper::DumpMethodTableSlotChunk( TADDR slotChunk, COUNT_T numSlots, bool isRelative )
7291 {
7292     IF_OPT( METHODTABLES )
7293     {
7294         COUNT_T slotsSize;
7295         if (isRelative)
7296         {
7297             slotsSize = numSlots * sizeof(RelativePointer<PCODE>);
7298         }
7299         else
7300         {
7301             slotsSize = numSlots * sizeof(PCODE);
7302         }
7303         DisplayStartStructure( "MethodTableSlotChunk", DataPtrToDisplay(slotChunk), slotsSize, METHODTABLES );
7304
7305         IF_OPT(VERBOSE_TYPES)
7306         {
7307             DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7308             for( unsigned i = 0; i < numSlots; ++i )
7309             {
7310                 PCODE target;
7311                 if (isRelative)
7312                 {
7313                     target = RelativePointer<PCODE>::GetValueMaybeNullAtPtr(slotChunk + i * sizeof(RelativePointer<PCODE>));
7314                 }
7315                 else
7316                 {
7317                     target = dac_cast<PTR_PCODE>(slotChunk)[i];
7318                 }
7319
7320                 DumpSlot(i, target);
7321             }
7322             DisplayEndList( ALWAYS ); //Slot list
7323         }
7324         else
7325             CoverageRead( slotChunk, slotsSize );
7326         DisplayEndStructure(ALWAYS); //Slot chunk
7327     }
7328 }
7329
7330
7331 void
7332 NativeImageDumper::DumpSlot( unsigned index, PCODE tgt )
7333 {
7334     IF_OPT(VERBOSE_TYPES)
7335     {
7336         DisplayStartElement( "Slot", ALWAYS );
7337         DisplayWriteElementInt( "Index", index, ALWAYS );
7338         DisplayWriteElementPointer( "Pointer",
7339                                     DataPtrToDisplay(tgt),
7340                                     ALWAYS );
7341         if( !isInRange(TO_TADDR(tgt)) )
7342         {
7343             DisplayWriteElementString( "Type", "external",
7344                                        ALWAYS );
7345         }
7346         else if( isPrecode(TO_TADDR(tgt))
7347                            && Precode::IsValidType(PTR_Precode(TO_TADDR(tgt))->GetType()) )
7348         {
7349             PTR_Precode precode(TO_TADDR(tgt));
7350             DisplayWriteElementString( "Type", "precode",
7351                                        ALWAYS );
7352             //DumpPrecode( precode, module );
7353         }
7354         else
7355         {
7356             DisplayWriteElementString( "Type", "code pointer",
7357                                        ALWAYS );
7358         }
7359         DisplayEndElement( ALWAYS ); //Slot
7360     }
7361 }
7362
7363 NativeImageDumper::EnumMnemonics NativeImageDumper::s_SSMDExtendedFlags[] =
7364 {
7365 #define SSMD_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
7366     
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
7376
7377     SSMD_ENTRY(mdStatic),
7378     SSMD_ENTRY(mdFinal),
7379     SSMD_ENTRY(mdVirtual),
7380     SSMD_ENTRY(mdHideBySig),
7381
7382     SSMD_ENTRY(mdVtableLayoutMask),
7383     SSMD_ENTRY(mdNewSlot),
7384
7385     SSMD_ENTRY(mdCheckAccessOnOverride),
7386     SSMD_ENTRY(mdAbstract),
7387     SSMD_ENTRY(mdSpecialName),
7388
7389     SSMD_ENTRY(mdPinvokeImpl),
7390     SSMD_ENTRY(mdUnmanagedExport),
7391
7392     SSMD_ENTRY(mdRTSpecialName),
7393     SSMD_ENTRY(mdHasSecurity),
7394     SSMD_ENTRY(mdRequireSecObject),
7395
7396     NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdILStub,
7397                                       W("nomdILStub") ),
7398     NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdLCGMethod,
7399                                       W("nomdLCGMethod") ),
7400 #undef SSMD_ENTRY
7401 };
7402
7403 //maps MethodClassification to a name for a MethodDesc
7404 const char * const s_MDTypeName[] =
7405 {
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
7414 #else
7415     "",
7416 #endif
7417     "DynamicMethodDesc", //mcDynamic -- //public StoredSigMethodDesc
7418 };
7419
7420 unsigned s_MDSizes[] =
7421 {
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
7430 #else
7431     0,
7432 #endif
7433     sizeof(DynamicMethodDesc),          //mcDynamic
7434 };
7435
7436 static NativeImageDumper::EnumMnemonics g_NDirectFlags[] =
7437 {
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),
7451 #undef NDF_ENTRY
7452 };
7453 NativeImageDumper::EnumMnemonics NativeImageDumper::s_IMDFlags[] =
7454 {
7455 #define IMD_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, W(#x) )
7456
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
7463
7464 #ifdef EnC_SUPPORTED
7465         // Method is a new virtual function added through EditAndContinue.
7466         IMD_ENTRY(EnCAddedMethod),
7467 #endif // EnC_SUPPORTED
7468
7469         IMD_ENTRY(Unrestored),
7470
7471 #ifdef FEATURE_COMINTEROP
7472         IMD_ENTRY(HasComPlusCallInfo),
7473 #endif // FEATURE_COMINTEROP
7474
7475 #undef IMD_ENTRY
7476 };
7477
7478 void NativeImageDumper::DumpPrecode( PTR_Precode precode, PTR_Module module )
7479 {
7480     _ASSERTE(isPrecode(PTR_TO_TADDR(precode)));
7481
7482     PrecodeType pType = precode->GetType();
7483     switch(pType)
7484     {
7485 #define DISPLAY_PRECODE(type) \
7486         IF_OPT_AND(PRECODES, METHODDESCS)   \
7487         { \
7488             PTR_ ## type p( precode->As ## type () ); \
7489             DisplayStartStructure( # type, \
7490                                    DPtrToPreferredAddr(p), \
7491                                    sizeof(*p), ALWAYS ); \
7492             WriteFieldMethodDesc( m_pMethodDesc, \
7493                                   p->m_pMethodDesc, \
7494                                   type, ALWAYS ); \
7495             TADDR target = p->GetTarget(); \
7496             DisplayWriteElementPointer("Target",\
7497                                         DataPtrToDisplay(target),\
7498                                         ALWAYS );\
7499             DisplayEndStructure( ALWAYS ); \
7500         }
7501
7502     case PRECODE_STUB:
7503         DISPLAY_PRECODE(StubPrecode); break;
7504 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7505     case PRECODE_NDIRECT_IMPORT:
7506         DISPLAY_PRECODE(NDirectImportPrecode); break;
7507 #endif
7508 #ifdef HAS_FIXUP_PRECODE
7509     case PRECODE_FIXUP:
7510         IF_OPT_AND(PRECODES, METHODDESCS)
7511         {
7512             PTR_FixupPrecode p( precode->AsFixupPrecode() );
7513             DisplayStartStructure( "FixupPrecode",
7514                                    DPtrToPreferredAddr(p),
7515                                    sizeof(*p),
7516                                    ALWAYS );
7517             PTR_MethodDesc precodeMD(p->GetMethodDesc());
7518 #ifdef HAS_FIXUP_PRECODE_CHUNKS
7519             {
7520                 DisplayWriteFieldInt( m_MethodDescChunkIndex,
7521                                       p->m_MethodDescChunkIndex, FixupPrecode,
7522                                       ALWAYS );
7523                 DisplayWriteFieldInt( m_PrecodeChunkIndex,
7524                                       p->m_PrecodeChunkIndex, FixupPrecode,
7525                                       ALWAYS );
7526                 if( p->m_PrecodeChunkIndex == 0 )
7527                 {
7528                     //dump the location of the Base
7529                     DisplayWriteElementAddress( "PrecodeChunkBase",
7530                                                 DataPtrToDisplay(p->GetBase()),
7531                                                 sizeof(void*), ALWAYS );
7532                 }
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*),
7538                                            8 );
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 );
7545             }
7546 #else //HAS_FIXUP_PRECODE_CHUNKS
7547             WriteFieldMethodDesc( m_pMethodDesc,
7548                                   p->m_pMethodDesc,
7549                                   FixupPrecode, ALWAYS );
7550 #endif //HAS_FIXUP_PRECODE_CHUNKS
7551             TADDR target = p->GetTarget();
7552             DisplayWriteElementPointer("Target",
7553                                         DataPtrToDisplay(target),
7554                                         ALWAYS );
7555             /* REVISIT_TODO Thu 01/05/2006
7556              * dump slot with offset if it is here
7557              */
7558             DisplayEndStructure( ALWAYS ); //FixupPrecode
7559         }
7560         break;
7561 #endif
7562 #ifdef HAS_THISPTR_RETBUF_PRECODE
7563     case PRECODE_THISPTR_RETBUF:
7564         DISPLAY_PRECODE(ThisPtrRetBufPrecode); break;
7565 #endif
7566     default:
7567         _ASSERTE( !"Unsupported precode type" );
7568 #undef DISPLAY_PRECODE
7569 #undef PrecodeMDWrite
7570     }
7571 }
7572
7573 #ifdef _PREFAST_
7574 #pragma warning(push)
7575 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
7576 #endif
7577 void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module )
7578 {
7579     //StoredSigMethodDesc
7580
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();
7586
7587     DisplayStartStructure( mdTypeName, DPtrToPreferredAddr(md),
7588                            mdSize, METHODDESCS );
7589     IF_OPT(METHODDESCS)
7590     {
7591         TempBuffer buf;
7592         MethodDescToString( md, buf );
7593         DisplayWriteElementStringW( "Name", (const WCHAR *)buf, METHODDESCS );
7594     }
7595 #ifdef _DEBUG
7596     IF_OPT(METHODDESCS)
7597     {
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);
7607     }
7608     else
7609     {
7610         CoverageReadString(TO_TADDR(md->m_pszDebugMethodName));
7611         CoverageReadString(TO_TADDR(md->m_pszDebugClassName));
7612         CoverageReadString(TO_TADDR(md->m_pszDebugMethodSignature));
7613     }
7614 #endif
7615
7616     DisplayWriteFieldInt( m_wFlags3AndTokenRemainder, md->m_wFlags3AndTokenRemainder,
7617                           MethodDesc, METHODDESCS );
7618
7619     DisplayWriteFieldInt( m_chunkIndex, md->m_chunkIndex,
7620                           MethodDesc, METHODDESCS );
7621
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.
7625      */
7626     if( mc == mcInstantiated && md->m_chunkIndex == 0 )
7627     {
7628         PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
7629         DisplayWriteElementAddress( "MethodDescChunk", DPtrToPreferredAddr(chunk),
7630                                     chunk->SizeOf(), METHODDESCS );
7631     }
7632
7633     DisplayWriteFieldEnumerated( m_bFlags2, md->m_bFlags2, MethodDesc,
7634                                  s_MDFlag2, W(", "), METHODDESCS );
7635
7636     DisplayWriteFieldInt( m_wSlotNumber, md->GetSlot(), MethodDesc,
7637                           METHODDESCS );
7638     DisplayWriteFieldEnumerated( m_wFlags, md->m_wFlags, MethodDesc,
7639                                  s_MDC, W(", "), METHODDESCS );
7640
7641     IF_OPT(IL)
7642     {
7643         if( md->IsIL() )
7644         {
7645             PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
7646             //chunk is implicitly remapped because it's calculated from the pointer
7647             //to MD.
7648             PTR_MethodTable mt = chunk->GetMethodTable();
7649             if( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
7650             {
7651                 if ( md->IsTypicalMethodDefinition() )
7652                 {
7653                     DWORD dwRVA = 0;
7654                     m_import->GetMethodProps(md->GetMemberDef(), NULL, NULL, NULL, 0,
7655                         NULL, NULL, NULL, &dwRVA, NULL);
7656
7657                     if (dwRVA != 0)
7658                     {
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);
7667
7668                         COR_ILMETHOD_DECODER decoder(pILHeader);
7669
7670                         DisplayStartStructure( "IL",
7671                                        DataPtrToDisplay(pILTarget),
7672                                        PEDecoder::ComputeILMethodSize(pILTarget),
7673                                        ALWAYS );
7674
7675                         DisplayWriteElementInt( "CodeSize", decoder.GetCodeSize(), ALWAYS );
7676
7677                         // Dump the disassembled IL code?
7678
7679                         DisplayEndStructure( ALWAYS );
7680                     }
7681                 }
7682             }
7683         }
7684     }
7685     if( md->HasPrecode() )
7686     {
7687         PTR_Precode precode( md->GetPrecode() );
7688
7689         DumpPrecode( precode, module );
7690     }
7691     if ( md->HasNonVtableSlot() )
7692     {
7693         DisplayWriteElementInt( "Slot", (DWORD)(md->GetAddrOfSlot() - PTR_TO_TADDR(md)), ALWAYS);
7694     }
7695     if (md->HasNativeCodeSlot())
7696     {
7697         DisplayWriteElementInt( "NativeCode", DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)), ALWAYS);
7698         //m_display->WriteFieldPointer( "NativeCode",
7699         //                              DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)),
7700         //                              sizeof(TADDR),
7701         //                              md->GetNativeCode() );
7702     }
7703     if (md->HasMethodImplSlot())
7704     {
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)))
7712         {
7713             DisplayWriteFieldAddress(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7714                                      (numSlots + 1) * sizeof(*slots),
7715                                      MethodImpl, METHODDESCS);
7716         }
7717         else
7718         {
7719             DisplayWriteFieldPointer(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7720                                      MethodImpl, METHODDESCS);
7721
7722         }
7723         _ASSERTE(impl->pImplementedMD.IsNull()
7724                  || isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())));
7725         if (!impl->pImplementedMD.IsNull() &&
7726             isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())))
7727         {
7728             DisplayWriteFieldAddress( pImplementedMD,
7729                                       DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDsNonNull())),
7730                                       numSlots * sizeof(RelativePointer <MethodDesc*>),
7731                                       MethodImpl, METHODDESCS );
7732         }
7733         else
7734         {
7735             DisplayWriteFieldPointer( pImplementedMD,
7736                                       DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDs())),
7737                                       MethodImpl, METHODDESCS );
7738         }
7739         DisplayEndVStructure( METHODDESCS );
7740     }
7741     if (md->HasStoredSig())
7742     {
7743         DisplayStartVStructure( "StoredSigMethodDesc", METHODDESCS );
7744         PTR_StoredSigMethodDesc ssmd(md); 
7745         //display signature information.
7746         if( isInRange(ssmd->GetSigRVA()) )
7747         {
7748             DisplayWriteFieldAddress(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7749                                      ssmd->m_cSig, StoredSigMethodDesc,
7750                                      METHODDESCS);
7751         }
7752         else
7753         {
7754             DisplayWriteFieldPointer(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7755                                      StoredSigMethodDesc, METHODDESCS);
7756
7757         }
7758         CoverageRead(TO_TADDR(ssmd->GetSigRVA()), ssmd->m_cSig);
7759         DisplayWriteFieldInt( m_cSig, ssmd->m_cSig,
7760                               StoredSigMethodDesc, METHODDESCS );
7761 #ifdef _WIN64
7762         DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7763                                      ssmd->m_dwExtendedFlags,
7764                                      StoredSigMethodDesc,
7765                                      s_SSMDExtendedFlags, W(", "),
7766                                      METHODDESCS );
7767 #endif
7768         DisplayEndVStructure( METHODDESCS ); //StoredSigMethodDesc
7769     }
7770     if( mc == mcDynamic )
7771     {
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 );
7781 #ifndef _WIN64
7782         DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7783                                      dmd->m_dwExtendedFlags,
7784                                      DynamicMethodDesc,
7785                                      s_SSMDExtendedFlags, W(", "),
7786                                      METHODDESCS );
7787 #endif
7788         DisplayEndVStructure( METHODDESCS );
7789     }
7790     if (mc == mcFCall )
7791     {
7792         PTR_FCallMethodDesc fcmd(md);
7793         DisplayStartVStructure( "FCallMethodDesc", METHODDESCS );
7794
7795         DisplayWriteFieldInt( m_dwECallID,
7796                               fcmd->m_dwECallID,
7797                               FCallMethodDesc,
7798                               METHODDESCS );
7799
7800         DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7801     }
7802     if( mc == mcNDirect )
7803     {
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,
7810                                          METHODDESCS );
7811         DisplayWriteFieldPointer( m_pNativeNDirectTarget,
7812                                   DataPtrToDisplay((TADDR)nd->m_pNativeNDirectTarget),
7813                                   NDirectMethodDesc::temp1,
7814                                   METHODDESCS );
7815         DisplayWriteFieldEnumerated( m_wFlags, nd->m_wFlags,
7816                                      NDirectMethodDesc::temp1,
7817                                      g_NDirectFlags, W(", "),
7818                                      METHODDESCS );
7819
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()));
7825         if (md->IsQCall())
7826         {
7827             DisplayWriteFieldInt( m_dwECallID,
7828                                   nd->m_dwECallID,
7829                                   NDirectMethodDesc::temp1,
7830                                   METHODDESCS );
7831         }
7832         else
7833         {
7834             WriteFieldStr( m_pszLibName,
7835                            PTR_BYTE(dac_cast<TADDR>(ndmd->GetLibNameRaw())),
7836                            NDirectMethodDesc::temp1, METHODDESCS );
7837         }
7838         if( !CHECK_OPT(METHODDESCS) )
7839             CoverageReadString( dac_cast<TADDR>(ndmd->GetLibNameRaw()) );
7840
7841         PTR_NDirectWriteableData wnd( ndmd->GetWriteableData() );
7842         DisplayStartStructureWithOffset( m_pWriteableData,
7843                                          DPtrToPreferredAddr(wnd),
7844                                          sizeof(*wnd),
7845                                          NDirectMethodDesc::temp1,
7846                                          METHODDESCS );
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
7852
7853         PTR_NDirectImportThunkGlue glue(ndmd->GetNDirectImportThunkGlue());
7854
7855 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7856         if (glue == NULL)
7857         {
7858             // import thunk glue is not needed for P/Invoke that is not inlinable
7859             DisplayWriteFieldPointer( m_pImportThunkGlue,
7860                                       NULL,
7861                                       NDirectMethodDesc::temp1,
7862                                       METHODDESCS );
7863         }
7864         else
7865         {
7866             DisplayStartStructureWithOffset( m_pImportThunkGlue,
7867                                              DPtrToPreferredAddr(glue),
7868                                              sizeof(*glue),
7869                                              NDirectMethodDesc::temp1,
7870                                              METHODDESCS);
7871 #else
7872             DisplayStartStructureWithOffset( m_ImportThunkGlue,
7873                                              DPtrToPreferredAddr(glue),
7874                                              sizeof(*glue),
7875                                              NDirectMethodDesc::temp1,
7876                                              METHODDESCS);
7877 #endif
7878 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7879             /* REVISIT_TODO Thu 01/05/2006
7880              * Dump this properly as a precode
7881              */
7882             WriteFieldMethodDesc( m_pMethodDesc, glue->m_pMethodDesc,
7883                                   NDirectImportThunkGlue, METHODDESCS );
7884             {
7885                 PTR_Precode p(glue);
7886                 DumpPrecode( p, module );
7887             }
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
7892              */
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.
7896              */
7897 #endif //HAS_NDIRECT_IMPORT_PRECODE
7898
7899             DisplayEndStructure( METHODDESCS ); //m_pImportThunkGlue
7900 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7901         }
7902 #endif
7903
7904 #ifdef _TARGET_X86_
7905         DisplayWriteFieldInt( m_cbStackArgumentSize,
7906                               nd->m_cbStackArgumentSize,
7907                               NDirectMethodDesc::temp1, METHODDESCS );
7908 #endif
7909
7910         WriteFieldMethodDesc( m_pStubMD,
7911                               nd->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc::temp1, nd, m_pStubMD)),
7912                               NDirectMethodDesc::temp1, METHODDESCS );
7913
7914         DisplayEndStructure( METHODDESCS ); //ndirect
7915
7916
7917         DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7918     }
7919     if( mc == mcEEImpl )
7920     {
7921         DisplayStartVStructure( "EEImplMethodDesc", METHODDESCS );
7922         DisplayEndVStructure( METHODDESCS );
7923     }
7924 #if defined(FEATURE_COMINTEROP)
7925     if( mc == mcComInterop )
7926     {
7927         PTR_ComPlusCallMethodDesc cpmd(md);
7928         DisplayStartVStructure( "ComPlusCallMethodDesc", METHODDESCS );
7929         PTR_ComPlusCallInfo compluscall((TADDR)cpmd->m_pComPlusCallInfo);
7930
7931         if (compluscall == NULL)
7932         {
7933             DisplayWriteFieldPointer( m_pComPlusCallInfo,
7934                                       NULL,
7935                                       ComPlusCallMethodDesc,
7936                                       METHODDESCS );
7937         }
7938         else
7939         {
7940             DumpComPlusCallInfo( compluscall, METHODDESCS );
7941         }
7942
7943         DisplayEndVStructure( METHODDESCS ); //ComPlusCallMethodDesc
7944     }
7945 #endif
7946     if( mc == mcInstantiated )
7947     {
7948         PTR_InstantiatedMethodDesc imd(md);
7949         DisplayStartVStructure( "InstantiatedMethodDesc", METHODDESCS );
7950         unsigned kind = imd->m_wFlags2
7951             & InstantiatedMethodDesc::KindMask;
7952         if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
7953         {
7954             PTR_DictionaryLayout layout(dac_cast<TADDR>(imd->GetDictLayoutRaw()));
7955             IF_OPT(METHODDESCS)
7956             {
7957                 WriteFieldDictionaryLayout( "m_pDictLayout",
7958                                             offsetof(InstantiatedMethodDesc, m_pDictLayout ),
7959                                             fieldsize(InstantiatedMethodDesc, m_pDictLayout),
7960                                             layout,
7961                                             GetDependencyFromMD(md)->pImport );
7962             }
7963             else
7964             {
7965                 while( layout != NULL )
7966                 {
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));
7972                 }
7973             }
7974         }
7975         else if( kind ==
7976                  InstantiatedMethodDesc::WrapperStubWithInstantiations )
7977         {
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) ) )
7983             {
7984                 WriteFieldMethodDesc( m_pWrappedMethodDesc, wimd,
7985                                       InstantiatedMethodDesc, METHODDESCS );
7986             }
7987         }
7988         else
7989         {
7990             _ASSERTE(imd->m_pDictLayout.IsNull());
7991             DisplayWriteFieldPointer( m_pDictLayout, NULL,
7992                                       InstantiatedMethodDesc,
7993                                       METHODDESCS );
7994         }
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());
7998         unsigned dictSize;
7999         if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
8000         {
8001             dictSize = sizeof(TypeHandle);
8002         }
8003         else if( kind == InstantiatedMethodDesc::WrapperStubWithInstantiations )
8004         {
8005             PTR_InstantiatedMethodDesc wrapped =
8006                 PTR_InstantiatedMethodDesc(imd->IMD_GetWrappedMethodDesc());
8007             if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(wrapped)) )
8008             {
8009                 /* XXX Mon 03/27/2006
8010                  * Note that 4 is the correct answer for all IMDs at this time.
8011                  */
8012                 TempBuffer buf;
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*);
8016             }
8017             else
8018             {
8019                 PTR_DictionaryLayout layout(wrapped->IsSharedByGenericMethodInstantiations()
8020                                             ? dac_cast<TADDR>(wrapped->GetDictLayoutRaw()) : NULL );
8021                 dictSize = DictionaryLayout::GetFirstDictionaryBucketSize(imd->GetNumGenericMethodArgs(), 
8022                                                                           layout);
8023             }
8024         }
8025         else
8026         {
8027             dictSize = sizeof(TypeHandle);
8028         }
8029         //instantiations has the number of slots of
8030         //GetNumGenericMethodArgs.
8031         if( inst == NULL )
8032         {
8033             m_display->WriteFieldPointer( "m_pPerInstInfo",
8034                                           offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8035                                           fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8036                                           NULL );
8037         }
8038         else
8039         {
8040             IF_OPT(METHODDESCS)
8041             {
8042
8043                 m_display->StartStructureWithOffset( "m_pPerInstInfo",
8044                                                      offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8045                                                      fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8046                                                      DPtrToPreferredAddr(inst),
8047                                                      dictSize );
8048             }
8049             DisplayStartArray( "InstantiationInfo", W("[%-2s]: %s"),
8050                                METHODDESCS );
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.
8054              */
8055             for( unsigned i = 0; i < numSlots
8056                  && CHECK_OPT(METHODDESCS); ++i )
8057             {
8058                 DisplayStartElement( "Handle", METHODDESCS );
8059                 DisplayWriteElementInt( "Index", i, METHODDESCS );
8060
8061                 TypeHandle thArg = inst->GetInstantiation()[i].GetValue();
8062                 IF_OPT(METHODDESCS)
8063                     WriteElementTypeHandle( "TypeHandle", thArg);
8064
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.
8068                  */
8069                 if( !CORCOMPILE_IS_POINTER_TAGGED(thArg.AsTAddr()) &&
8070                     thArg.IsTypeDesc() )
8071                 {
8072                     PTR_TypeDesc td(thArg.AsTypeDesc());
8073                     if( isInRange(PTR_TO_TADDR(td)) )
8074                     {
8075                         m_discoveredTypeDescs.AppendEx(td);
8076                     }
8077                 }
8078                 DisplayEndElement( METHODDESCS ); //Handle
8079             }
8080             //Instantiation Info
8081             DisplayEndArray( "Total TypeHandles", METHODDESCS );
8082
8083             DisplayEndVStructure(METHODDESCS); //m_pPerInstInfo;
8084             if( !CHECK_OPT(METHODDESCS) )
8085                 CoverageRead(PTR_TO_TADDR(inst), numSlots * sizeof(*inst));
8086         }
8087
8088         DisplayWriteFieldEnumerated( m_wFlags2, imd->m_wFlags2,
8089                                      InstantiatedMethodDesc, s_IMDFlags,
8090                                      W(", "), METHODDESCS );
8091         DisplayWriteFieldInt( m_wNumGenericArgs, imd->m_wNumGenericArgs,
8092                               InstantiatedMethodDesc, METHODDESCS );
8093
8094 #ifdef FEATURE_COMINTEROP
8095         if (imd->IMD_HasComPlusCallInfo())
8096         {
8097             PTR_ComPlusCallInfo compluscall = imd->IMD_GetComPlusCallInfo();
8098             DumpComPlusCallInfo( compluscall, METHODDESCS );
8099         }
8100 #endif // FEATURE_COMINTEROP
8101
8102         DisplayEndStructure( METHODDESCS );
8103     }
8104
8105     DisplayEndStructure( METHODDESCS ); //MethodDesc (mdTypeName)
8106     if( !CHECK_OPT(METHODDESCS) )
8107         CoverageRead( PTR_TO_TADDR(md), mdSize );
8108
8109 }
8110 #ifdef _PREFAST_
8111 #pragma warning(pop)
8112 #endif
8113
8114 NativeImageDumper::EnumMnemonics NativeImageDumper::s_EECLIFlags[] =
8115 {
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
8122 };
8123
8124
8125 #ifdef _PREFAST_
8126 #pragma warning(push)
8127 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
8128 #endif
8129 void 
8130 NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
8131 {
8132     PTR_EEClass clazz = mt->GetClass();
8133
8134     _ASSERTE(CHECK_OPT(EECLASSES));
8135     _ASSERTE(clazz != NULL);
8136     _ASSERTE(isInRange(PTR_TO_TADDR(clazz)));
8137
8138     const char * eeClassType;
8139
8140     if( clazz->HasLayout() )
8141         eeClassType = "LayoutEEClass";
8142     else if( mt->IsArray() )
8143         eeClassType = "ArrayClass";
8144     else if( clazz->IsDelegate() )
8145         eeClassType = "DelegateEEClass";
8146     else
8147         eeClassType = "EEClass";
8148
8149     DisplayStartStructure( eeClassType, DPtrToPreferredAddr(clazz), clazz->GetSize(),
8150                            EECLASSES );
8151     {
8152         TempBuffer buf;
8153         MethodTableToString( mt, buf );
8154         DisplayWriteElementStringW( "Name", (const WCHAR *)buf, EECLASSES );
8155     }
8156
8157     PTR_GuidInfo guidInfo = clazz->GetGuidInfo();
8158     if(guidInfo != NULL)
8159     {
8160         DisplayStartStructureWithOffset( m_pGuidInfo,
8161                                          DPtrToPreferredAddr(guidInfo),
8162                                          sizeof(*guidInfo), EEClass,
8163                                          EECLASSES );
8164         TempBuffer buf;
8165         GuidToString( guidInfo->m_Guid, buf );
8166         DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
8167                                   EECLASSES );
8168         DisplayWriteFieldFlag( m_bGeneratedFromName,
8169                                guidInfo->m_bGeneratedFromName,
8170                                GuidInfo, EECLASSES );
8171         DisplayEndStructure( EECLASSES ); //guidinfo
8172     }
8173     else
8174     {
8175         /* XXX Fri 10/14/2005
8176          * if Clazz isn't an interface, m_pGuidInfo is undefined.
8177          */
8178         DisplayWriteFieldPointerAnnotated( m_pGuidInfo, PTR_TO_TADDR(guidInfo),
8179                                            W("Invalid"), EEClass, EECLASSES );
8180     }
8181
8182
8183 #ifdef _DEBUG
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 );
8189 #endif
8190
8191     WriteFieldMethodTable( m_pMethodTable, clazz->GetMethodTable(), EEClass,
8192                            EECLASSES );
8193
8194     WriteFieldCorElementType( m_NormType, (CorElementType)clazz->m_NormType,
8195                               EEClass, EECLASSES );
8196
8197     PTR_FieldDesc fdList = clazz->GetFieldDescList();
8198
8199     ULONG fieldCount = (ULONG)CountFields(mt);
8200     _ASSERTE((fdList == NULL) == (fieldCount == 0));
8201
8202     IF_OPT(EECLASSES)
8203     {
8204         m_display->StartStructureWithOffset( "m_pFieldDescList",
8205                                              offsetof(EEClass, m_pFieldDescList),
8206                                              fieldsize(EEClass, m_pFieldDescList),
8207                                              DPtrToPreferredAddr(fdList),
8208                                              fdList != NULL ? 
8209                                                 sizeof(*fdList) * fieldCount :
8210                                                 0 );
8211     }
8212     IF_OPT(VERBOSE_TYPES)
8213     {
8214         if( fdList != NULL )
8215         {
8216             DisplayStartArray( "FieldDescs", NULL, EECLASSES );
8217             for( SIZE_T i = 0; i < fieldCount; ++i )
8218             {
8219                 PTR_FieldDesc fd = fdList + i;
8220                 IF_OPT(EECLASSES)
8221                     DumpFieldDesc( fd, "FieldDesc" );
8222             }
8223             DisplayEndArray( "Total FieldDescs", EECLASSES ); //FieldDescs
8224         }
8225     }
8226     else if( (fdList != NULL) && CHECK_OPT(DEBUG_COVERAGE) )
8227     {
8228         for( SIZE_T i = 0; i < fieldCount; ++i )
8229         {
8230             PTR_FieldDesc fd = fdList + i;
8231 #ifdef _DEBUG
8232             if( fd != NULL && fd->m_debugName != NULL )
8233                 CoverageReadString( fd->m_debugName );
8234 #endif
8235         }
8236         CoverageRead( PTR_TO_TADDR(fdList), sizeof(*fdList) * fieldCount );
8237     }
8238
8239     DisplayEndStructure( EECLASSES ); //FieldDescList
8240
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 );
8245
8246     PTR_MethodDescChunk chunk = clazz->GetChunks();
8247
8248     DisplayStartArrayWithOffset( m_pChunks, NULL, EEClass, EECLASSES );
8249     while( chunk != NULL )
8250     {
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,
8264                               EECLASSES );
8265         DisplayWriteFieldInt( m_count, chunk->m_count, MethodDescChunk,
8266                               EECLASSES );
8267         DisplayWriteFieldInt( m_flagsAndTokenRange, chunk->m_flagsAndTokenRange, MethodDescChunk,
8268                               EECLASSES );
8269         /* XXX Wed 12/14/2005
8270          * Don't skip walking this array.  I need to make sure I touch the
8271          * precodes.
8272          */
8273         DisplayStartArray( "MethodDescs", NULL, METHODDESCS );
8274         PTR_MethodDesc md(chunk->GetFirstMethodDesc());
8275         while (md != NULL)
8276         {
8277             IF_OPT_OR(METHODDESCS, DEBUG_COVERAGE)
8278             {
8279                 PTR_Module module = mt->GetModule();
8280                 if(CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module) )) 
8281                     DumpMethodDesc( md, PTR_Module((TADDR)0) );
8282                 else
8283                     DumpMethodDesc( md, module );
8284             }
8285
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();
8289
8290             md = (pNext < pEnd) ? PTR_MethodDesc(pNext) : NULL;
8291         }
8292
8293         DisplayEndArray( "Total MethodDescs", METHODDESCS); //MethodDescs
8294
8295         chunk = chunk->GetNextChunk();
8296
8297         DisplayEndStructure( EECLASSES ); //MethodDescChunk
8298     }
8299
8300     DisplayEndArray( "Total MethodDescChunks", EECLASSES );
8301     /* REVISIT_TODO Fri 10/14/2005
8302      * Dump the class dependencies
8303      */
8304     //_ASSERTE(!clazz->m_classDependencies.TestAnyBit());
8305
8306     /* REVISIT_TODO Mon 10/24/2005
8307      * Create vstructure for union?
8308      */
8309     //decode union here
8310 #ifdef FEATURE_COMINTEROP
8311     if( clazz->IsBlittable() || clazz->HasLayout() )
8312     {
8313         DisplayWriteFieldInt(m_cbNativeSize, clazz->m_cbNativeSize, EEClass,
8314                              EECLASSES );
8315     }
8316     else if( clazz->IsInterface() )
8317     {
8318         DisplayWriteFieldPointer( m_ohDelegate,
8319                                   DataPtrToDisplay(clazz->m_ohDelegate),
8320                                   EEClass, EECLASSES );
8321     }
8322     else
8323     {
8324         static const WCHAR * ifnames[] ={W("Dual"),W("Vtable"),W("Dispatch")};
8325         m_display->WriteFieldEnumerated( "ComInterfaceType",
8326                                          offsetof(EEClass,
8327                                                   m_ComInterfaceType),
8328                                          fieldsize(EEClass,
8329                                                    m_ComInterfaceType),
8330                                          (int)clazz->m_ComInterfaceType,
8331                                          ifnames[(int)clazz->m_ComInterfaceType] );
8332     }
8333 #else
8334     DisplayWriteFieldInt( m_cbNativeSize, clazz->m_cbNativeSize,
8335                           EEClass, EECLASSES );
8336 #endif
8337
8338 #if defined(FEATURE_COMINTEROP)
8339     PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(clazz->m_pccwTemplate));
8340     if( ccwTemplate != NULL )
8341     {
8342         DisplayWriteFieldPointer( m_pccwTemplate, NULL, EEClass,
8343                                   EECLASSES );
8344     }
8345     else
8346     {
8347         /* REVISIT_TODO Fri 10/14/2005
8348          * Dump CcwTemplate
8349          */
8350         DisplayWriteFieldPointer( m_pccwTemplate,
8351                                   DPtrToPreferredAddr(ccwTemplate), EEClass,
8352                                   EECLASSES );
8353     }
8354 #endif // defined(FEATURE_COMINTEROP)
8355
8356     //fields for classes that aren't just EEClasses.
8357     if( clazz->HasLayout() )
8358     {
8359         PTR_LayoutEEClass layoutClass(PTR_TO_TADDR(clazz));
8360         DisplayStartVStructure("LayoutEEClass", EECLASSES );
8361
8362         PTR_EEClassLayoutInfo eecli( PTR_HOST_MEMBER_TADDR( LayoutEEClass,
8363                                                             layoutClass,
8364                                                             m_LayoutInfo ) );
8365         DisplayStartStructureWithOffset( m_LayoutInfo,
8366                                          DPtrToPreferredAddr(eecli),
8367                                          sizeof(EEClassLayoutInfo),
8368                                          LayoutEEClass, EECLASSES );
8369         /* REVISIT_TODO Fri 10/14/2005
8370          * Dump EEClassLayoutInfo
8371          */
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(", "),
8384                                      VERBOSE_TYPES );
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.
8395          */
8396 #if 0
8397         DisplayStartArrayWithOffset( m_pFieldMarshalers, NULL,
8398                                      EEClassLayoutInfo, VERBOSE_TYPES );
8399         for( unsigned i = 0; i < eecli->m_numCTMFields; ++i )
8400         {
8401             /* REVISIT_TODO Wed 03/22/2006
8402              * Try to display the type of the field marshaler in the future.
8403              */
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,
8412                                   VERBOSE_TYPES );
8413             DisplayEndStructure( VERBOSE_TYPES ); //FieldMarshaler
8414         }
8415         
8416         DisplayEndArray( "Number of FieldMarshalers", VERBOSE_TYPES ); //m_pFieldMarshalers
8417 #endif
8418         
8419         DisplayEndStructure( EECLASSES ); //LayoutInfo
8420
8421         DisplayEndVStructure( EECLASSES ); //LayoutEEClass
8422     }
8423     else if( mt->IsArray() )
8424     {
8425         PTR_ArrayClass arrayClass(PTR_TO_TADDR(clazz));
8426         DisplayStartVStructure( "ArrayClass", EECLASSES);
8427         IF_OPT(EECLASSES)
8428         {
8429             m_display->WriteFieldInt( "m_rank", offsetof(ArrayClass, m_rank),
8430                                       fieldsize(ArrayClass, m_rank),
8431                                       arrayClass->GetRank() );
8432         }
8433         DoWriteFieldCorElementType( "m_ElementType",
8434                                     offsetof(ArrayClass, m_ElementType),
8435                                     fieldsize(ArrayClass, m_ElementType),
8436                                     arrayClass->GetArrayElementType() );
8437
8438         DisplayEndVStructure( EECLASSES ); //ArrayClass
8439     }
8440     else if( clazz->IsDelegate() )
8441     {
8442         PTR_DelegateEEClass delegateClass(PTR_TO_TADDR(clazz));
8443         DisplayStartVStructure( "DelegateEEClass", EECLASSES );
8444
8445         DumpFieldStub( m_pStaticCallStub, delegateClass->m_pStaticCallStub,
8446                        DelegateEEClass, EECLASSES );
8447         DumpFieldStub( m_pInstRetBuffCallStub,
8448                        delegateClass->m_pInstRetBuffCallStub,
8449                        DelegateEEClass, EECLASSES );
8450
8451         WriteFieldMethodDesc( m_pInvokeMethod,
8452                               delegateClass->GetInvokeMethod(),
8453                               DelegateEEClass, EECLASSES );
8454         DumpFieldStub( m_pMultiCastInvokeStub, 
8455                        delegateClass->m_pMultiCastInvokeStub,
8456                        DelegateEEClass, EECLASSES );
8457
8458         DPTR(UMThunkMarshInfo)
8459             umInfo(TO_TADDR(delegateClass->m_pUMThunkMarshInfo));
8460
8461         if( umInfo == NULL )
8462         {
8463             DisplayWriteFieldPointer( m_pUMThunkMarshInfo, NULL,
8464                                       DelegateEEClass, EECLASSES );
8465         }
8466         else
8467         {
8468             DisplayStartStructureWithOffset( m_pUMThunkMarshInfo,
8469                                              DPtrToPreferredAddr(umInfo),
8470                                              sizeof(*umInfo),
8471                                              DelegateEEClass, EECLASSES );
8472             /* REVISIT_TODO Fri 10/14/2005
8473              * DumpUMThunkMarshInfo
8474              */
8475             DisplayEndStructure( EECLASSES ); //UMThunkMarshInfo
8476         }
8477
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 );
8486
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 );
8493
8494 #ifdef FEATURE_COMINTEROP
8495         DPTR(ComPlusCallInfo) compluscall((TADDR)delegateClass->m_pComPlusCallInfo);
8496         if (compluscall == NULL)
8497         {
8498             DisplayWriteFieldPointer( m_pComPlusCallInfo,
8499                                       NULL,
8500                                       DelegateEEClass,
8501                                       EECLASSES );
8502         }
8503         else
8504         {
8505             DumpComPlusCallInfo( compluscall, EECLASSES );
8506         }        
8507 #endif // FEATURE_COMINTEROP
8508
8509         DisplayEndVStructure( EECLASSES ); //DelegateEEClass
8510     }
8511
8512     DisplayEndStructure( EECLASSES ); //eeClassType
8513
8514     PTR_EEClassOptionalFields pClassOptional = clazz->GetOptionalFields();
8515     if (pClassOptional)
8516     {
8517         DisplayStartStructure( "EEClassOptionalFields", DPtrToPreferredAddr(pClassOptional), sizeof(EEClassOptionalFields),
8518                                EECLASSES );
8519
8520 #ifdef FEATURE_COMINTEROP
8521         PTR_SparseVTableMap sparseVTMap(TO_TADDR(pClassOptional->m_pSparseVTableMap));
8522         if( sparseVTMap == NULL )
8523         {
8524             DisplayWriteFieldPointer( m_pSparseVTableMap, NULL, EEClassOptionalFields,
8525                                       EECLASSES );
8526         }
8527         else
8528         {
8529             _ASSERTE( !"Untested code" );
8530             IF_OPT(EECLASSES)
8531             {
8532                 m_display->StartStructure( "m_SparseVTableMap",
8533                                            DPtrToPreferredAddr(sparseVTMap),
8534                                            sizeof(*sparseVTMap) );
8535             }
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 )
8540             {
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 );
8547             }
8548
8549             DisplayEndArray( "Total Entries", EECLASSES ); //m_MapList
8550
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 );
8561
8562             DisplayEndStructure( EECLASSES ); //SparseVTableMap
8563         }
8564
8565         WriteFieldTypeHandle( m_pCoClassForIntf, pClassOptional->m_pCoClassForIntf,
8566                               EEClassOptionalFields, EECLASSES );
8567
8568         PTR_ClassFactoryBase classFactory(TO_TADDR(pClassOptional->m_pClassFactory));
8569         if( classFactory != NULL )
8570         {
8571             DisplayWriteFieldPointer( m_pClassFactory, NULL, EEClassOptionalFields,
8572                                       EECLASSES );
8573         }
8574         else
8575         {
8576             /* REVISIT_TODO Fri 10/14/2005
8577              * Dump ComClassFactory
8578              */
8579             DisplayWriteFieldPointer( m_pClassFactory,
8580                                       DPtrToPreferredAddr(classFactory),
8581                                       EEClassOptionalFields, EECLASSES );
8582         }
8583 #endif // FEATURE_COMINTEROP
8584
8585         PTR_DictionaryLayout layout = pClassOptional->m_pDictLayout;
8586         if( layout == NULL )
8587         {
8588             DisplayWriteFieldPointer( m_pDictLayout, NULL, EEClassOptionalFields, EECLASSES );
8589         }
8590         else
8591         {
8592             IF_OPT(VERBOSE_TYPES)
8593             {
8594                 WriteFieldDictionaryLayout( "m_pDictLayout",
8595                                             offsetof(EEClassOptionalFields, m_pDictLayout),
8596                                             fieldsize(EEClassOptionalFields, m_pDictLayout),
8597                                             layout, GetDependencyFromMT(mt)->pImport );
8598             }
8599             else
8600             {
8601                 while( layout != NULL )
8602                 {
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));
8608                 }
8609             }
8610         }
8611         PTR_BYTE varianceInfo = pClassOptional->GetVarianceInfo();
8612         if( varianceInfo == NULL )
8613         {
8614             DisplayWriteFieldPointer( m_pVarianceInfo, NULL,
8615                                       EEClassOptionalFields, EECLASSES );
8616         }
8617         else
8618         {
8619             /* REVISIT_TODO Fri 10/14/2005
8620              * Dump variance info
8621              */
8622             DisplayWriteFieldPointer( m_pVarianceInfo,
8623                                       DPtrToPreferredAddr(varianceInfo), EEClassOptionalFields,
8624                                       EECLASSES );
8625         }
8626
8627         DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID,
8628                               EEClassOptionalFields, EECLASSES );
8629
8630         DisplayEndStructure( EECLASSES ); // EEClassOptionalFields
8631     }
8632 } // NativeImageDumper::DumpEEClassForMethodTable
8633 #ifdef _PREFAST_
8634 #pragma warning(pop)
8635 #endif
8636
8637 enum TypeDescType
8638 {
8639     TDT_IsTypeDesc,
8640     TDT_IsParamTypeDesc,
8641     TDT_IsArrayTypeDesc,
8642     TDT_IsTypeVarTypeDesc,
8643     TDT_IsFnPtrTypeDesc
8644 };
8645 const char * const g_typeDescTypeNames[] =
8646 {
8647     "TypeDesc",
8648     "ParamTypeDesc",
8649     "ArrayTypeDesc",
8650     "TypeVarTypeDesc",
8651     "FnPtrTypeDesc"
8652 };
8653 int g_typeDescSizes[] =
8654 {
8655     sizeof(TypeDesc),
8656     sizeof(ParamTypeDesc),
8657     sizeof(ArrayTypeDesc),
8658     sizeof(TypeVarTypeDesc),
8659     -1//sizeof(FnPtrTypeDesc) -- variable size
8660 };
8661 TypeDescType getTypeDescType( PTR_TypeDesc td )
8662 {
8663     _ASSERTE(td != NULL);
8664     if( td->IsArray() )
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;
8673 }
8674 NativeImageDumper::EnumMnemonics NativeImageDumper::s_TDFlags[] =
8675 {
8676
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),
8684 #undef TDF_ENTRY
8685 };
8686
8687 NativeImageDumper::EnumMnemonics s_CConv[] =
8688 {
8689 #define CC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
8690
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
8700
8701     CC_ENTRY(IMAGE_CEE_CS_CALLCONV_HASTHIS),
8702     CC_ENTRY(IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS),
8703     CC_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERIC)
8704 };
8705
8706
8707 void NativeImageDumper::DumpTypeDesc( PTR_TypeDesc td )
8708 {
8709     _ASSERTE(CHECK_OPT(TYPEDESCS));
8710     TypeDescType tdt = getTypeDescType(td);
8711     int size = g_typeDescSizes[(int)tdt];
8712     if( size == -1 )
8713     {
8714         _ASSERTE(tdt == TDT_IsFnPtrTypeDesc);
8715         size = FnPtrTypeDesc::DacSize(PTR_TO_TADDR(td));
8716     }
8717     DisplayStartStructure( g_typeDescTypeNames[(int)tdt],
8718                            DPtrToPreferredAddr(td), size, TYPEDESCS );
8719
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 )
8726     {
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 );
8736
8737         DisplayEndVStructure( TYPEDESCS ); //ParamTypeDesc
8738     }
8739     else if( tdt == TDT_IsFnPtrTypeDesc )
8740     {
8741         PTR_FnPtrTypeDesc ftd(td);
8742         DisplayStartVStructure( "FnPtrTypeDesc", TYPEDESCS );
8743         DisplayWriteFieldInt( m_NumArgs, ftd->m_NumArgs, FnPtrTypeDesc,
8744                               TYPEDESCS );
8745         DisplayWriteFieldEnumerated( m_CallConv, ftd->m_CallConv, 
8746                                      FnPtrTypeDesc, s_CConv, W(", "),
8747                                      TYPEDESCS );
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 )
8753         {
8754             DisplayStartElement( "Argument", TYPEDESCS );
8755             DisplayWriteElementInt( "Index", i, TYPEDESCS );
8756             IF_OPT( TYPEDESCS )
8757                 WriteElementTypeHandle( "TypeHandle", args[i] );
8758             DisplayEndElement( TYPEDESCS );
8759         }
8760         DisplayEndArray( "Total Arguments", TYPEDESCS ); 
8761         DisplayEndVStructure( TYPEDESCS );
8762     }
8763     else if( tdt == TDT_IsTypeVarTypeDesc )
8764     {
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 )
8776         {
8777             DisplayWriteFieldPointer( m_constraints, NULL, TypeVarTypeDesc,
8778                                       TYPEDESCS );
8779         }
8780         else
8781         {
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 )
8789             {
8790                 WriteElementTypeHandle( "TypeHandle", tvtd->m_constraints[i] );
8791             }
8792             DisplayEndArray( "Total Constraints", TYPEDESCS ); //Constraints
8793             DisplayEndStructure( TYPEDESCS ); //m_constraints
8794         }
8795         DisplayWriteFieldPointer( m_hExposedClassObject,
8796                                   DataPtrToDisplay(tvtd->m_hExposedClassObject),
8797                                   TypeVarTypeDesc, TYPEDESCS );
8798         DisplayWriteFieldUInt( m_token, tvtd->m_token, TypeVarTypeDesc,
8799                                TYPEDESCS );
8800         DisplayWriteFieldInt( m_index, tvtd->m_index, TypeVarTypeDesc,
8801                               TYPEDESCS );
8802
8803         DisplayEndVStructure( TYPEDESCS ); //TypeVarTypeDesc
8804     }
8805     
8806
8807     DisplayEndStructure( TYPEDESCS ); // g_typeDescTypeNames
8808
8809 }
8810
8811 void NativeImageDumper::DumpDictionaryEntry( const char * elementName,
8812                                              DictionaryEntryKind kind,
8813                                              PTR_DictionaryEntry entry )
8814 {
8815     m_display->StartElement( elementName );
8816     const char * name = NULL;
8817     switch(kind)
8818     {
8819     case EmptySlot:
8820         m_display->WriteEmptyElement("EmptySlot");
8821         break;
8822     case TypeHandleSlot:
8823         {
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
8828              * record them
8829              */
8830             if( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc() )
8831             {
8832                 PTR_TypeDesc td(th.AsTypeDesc());
8833                 if( isInRange(PTR_TO_TADDR(td)) )
8834                 {
8835                     m_discoveredTypeDescs.AppendEx(td);
8836                 }
8837             }
8838         }
8839         break;
8840     case MethodDescSlot:
8841         {
8842             TempBuffer buf;
8843             PTR_MethodDesc md(TO_TADDR(*entry));
8844             WriteElementMethodDesc( "MethodDesc", md );
8845         }
8846         break;
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
8858          */
8859     case FieldDescSlot:
8860         name = "FieldDescSlot";
8861 StandardEntryDisplay:
8862         m_display->WriteElementPointer(name, DataPtrToDisplay((TADDR)*entry));
8863         break;
8864     default:
8865         _ASSERTE( !"unreachable" );
8866     }
8867     m_display->EndElement(); //elementName
8868 }
8869
8870 #ifdef FEATURE_READYTORUN
8871 IMAGE_DATA_DIRECTORY * NativeImageDumper::FindReadyToRunSection(DWORD type)
8872 {
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++)
8875     {
8876         // Verify that section types are sorted
8877         _ASSERTE(i == 0 || (pSections[i - 1].Type < pSections[i].Type));
8878
8879         READYTORUN_SECTION * pSection = pSections + i;
8880         if (pSection->Type == type)
8881             return &pSection->Section;
8882     }
8883     return NULL;
8884 }
8885
8886 //
8887 // Ready to Run specific dumping methods
8888 //
8889 void NativeImageDumper::DumpReadyToRun()
8890 {
8891     m_pReadyToRunHeader = m_decoder.GetReadyToRunHeader();
8892
8893     m_nativeReader = NativeFormat::NativeReader(dac_cast<PTR_BYTE>(m_decoder.GetBase()), m_decoder.GetVirtualSize());
8894
8895     IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindReadyToRunSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS);
8896     if (pRuntimeFunctionsDir != NULL)
8897     {
8898         m_pRuntimeFunctions = dac_cast<PTR_RUNTIME_FUNCTION>(m_decoder.GetDirectoryData(pRuntimeFunctionsDir));
8899         m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION);
8900     }
8901     else
8902     {
8903         m_nRuntimeFunctions = 0;
8904     }
8905
8906     IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindReadyToRunSection(READYTORUN_SECTION_METHODDEF_ENTRYPOINTS);
8907     if (pEntryPointsDir != NULL)
8908         m_methodDefEntryPoints = NativeFormat::NativeArray((TADDR)&m_nativeReader, pEntryPointsDir->VirtualAddress);
8909
8910     DisplayStartCategory("NativeInfo", NATIVE_INFO);
8911
8912     IF_OPT(NATIVE_INFO)
8913         DumpReadyToRunHeader();
8914
8915     DisplayEndCategory(NATIVE_INFO); //NativeInfo
8916
8917     IF_OPT_OR3(METHODS, GC_INFO, DISASSEMBLE_CODE)
8918         DumpReadyToRunMethods();
8919
8920     IF_OPT(RELOCATIONS)
8921         DumpBaseRelocs();
8922 }
8923
8924 const NativeImageDumper::EnumMnemonics s_ReadyToRunFlags[] = 
8925 {
8926 #define RTR_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
8927     RTR_FLAGS(READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE),
8928 #undef RTR_FLAGS
8929 };
8930
8931 void NativeImageDumper::DumpReadyToRunHeader()
8932 {
8933     IF_OPT(NATIVE_INFO)
8934     {
8935         m_display->StartStructure( "READYTORUN_HEADER",
8936                                    DPtrToPreferredAddr(dac_cast<PTR_READYTORUN_HEADER>(m_pReadyToRunHeader)),
8937                                    sizeof(*m_pReadyToRunHeader) );
8938
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 );
8942
8943         DisplayWriteFieldEnumerated( Flags, m_pReadyToRunHeader->Flags,
8944                                      READYTORUN_HEADER, s_ReadyToRunFlags, W(", "),
8945                                      NATIVE_INFO );
8946
8947         m_display->EndStructure(); //READYTORUN_HEADER
8948     }
8949 }
8950
8951 void NativeImageDumper::DumpReadyToRunMethods()
8952 {
8953     DisplayStartArray("Methods", NULL, METHODS);
8954
8955     for (uint rid = 1; rid <= m_methodDefEntryPoints.GetCount(); rid++)
8956     {
8957         uint offset;
8958         if (!m_methodDefEntryPoints.TryGetAt(rid - 1, &offset))
8959             continue;
8960
8961         uint id;
8962         offset = m_nativeReader.DecodeUnsigned(offset, &id);
8963
8964         if (id & 1)
8965         {
8966             if (id & 2)
8967             {
8968                 uint val;
8969                 m_nativeReader.DecodeUnsigned(offset, &val);
8970                 offset -= val;
8971             }
8972
8973             // TODO: Dump fixups from dac_cast<TADDR>(m_pLayout->GetBase()) + offset
8974
8975             id >>= 2;
8976         }
8977         else
8978         {
8979             id >>= 1;
8980         }
8981
8982         _ASSERTE(id < m_nRuntimeFunctions);
8983         PTR_RUNTIME_FUNCTION pRuntimeFunction = m_pRuntimeFunctions + id;
8984         PCODE pEntryPoint = dac_cast<TADDR>(m_decoder.GetBase()) + pRuntimeFunction->BeginAddress;
8985
8986         SString buf;
8987         AppendTokenName(TokenFromRid(rid, mdtMethodDef), buf, m_import);
8988
8989         DumpReadyToRunMethod(pEntryPoint, pRuntimeFunction, buf);
8990     }
8991
8992     DisplayEndArray("Total Methods", METHODS); //Methods
8993 }
8994
8995 extern PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntimeFunction, /* out */ SIZE_T * pSize);
8996
8997 void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNCTION pRuntimeFunction, SString& name)
8998 {
8999     //Read the GCInfo to get the total method size.
9000     unsigned methodSize = 0;
9001     unsigned gcInfoSize = UINT_MAX;
9002
9003     SIZE_T nUnwindDataSize;
9004     PTR_VOID pUnwindData = GetUnwindDataBlob(dac_cast<TADDR>(m_decoder.GetBase()), pRuntimeFunction, &nUnwindDataSize);
9005
9006     // GCInfo immediatelly follows unwind data
9007     PTR_CBYTE gcInfo = dac_cast<PTR_CBYTE>(pUnwindData) + nUnwindDataSize;
9008
9009     void(*stringOutFn)(const char *, ...);
9010     IF_OPT(GC_INFO)
9011     {
9012         stringOutFn = stringOut;
9013     }
9014     else
9015     {
9016         stringOutFn = nullStringOut;
9017     }
9018     if (gcInfo != NULL)
9019     {
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 };
9027
9028 #if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
9029         GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
9030         methodSize = gcInfoDecoder.GetCodeLength();
9031 #endif
9032
9033         //dump the data to a string first so we can get the gcinfo size.
9034 #ifdef _TARGET_X86_
9035         InfoHdr hdr;
9036         stringOutFn("method info Block:\n");
9037         curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0);
9038         stringOutFn("\n");
9039 #endif
9040
9041         IF_OPT(METHODS)
9042         {
9043 #ifdef _TARGET_X86_
9044             stringOutFn("PointerTable:\n");
9045             curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9046                 hdr,
9047                 methodSize, 0);
9048             gcInfoSize = curGCInfoPtr - gcInfo;
9049 #elif defined(USE_GC_INFO_DECODER)
9050             stringOutFn("PointerTable:\n");
9051             curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9052                 methodSize, 0);
9053             gcInfoSize = (unsigned)(curGCInfoPtr - gcInfo);
9054 #endif
9055         }
9056
9057         //data is output below.
9058     }
9059
9060     DisplayStartElement("Method", METHODS);
9061     DisplayWriteElementStringW("Name", (const WCHAR *)name, METHODS);
9062
9063     DisplayStartStructure("GCInfo",
9064         DPtrToPreferredAddr(gcInfo),
9065         gcInfoSize,
9066         METHODS);
9067
9068     DisplayStartTextElement("Contents", GC_INFO);
9069     DisplayWriteXmlTextBlock(("%S", (const WCHAR *)g_holdStringOutData), GC_INFO);
9070     DisplayEndTextElement(GC_INFO); //Contents
9071
9072     DisplayEndStructure(METHODS); //GCInfo
9073
9074     DisplayStartStructure("Code", DataPtrToDisplay(pEntryPoint), methodSize,
9075         METHODS);
9076
9077     IF_OPT(DISASSEMBLE_CODE)
9078     {
9079         // Disassemble hot code.  Read the code into the host process.
9080         /* REVISIT_TODO Mon 10/24/2005
9081         * Is this align up right?
9082         */
9083         BYTE * codeStartHost =
9084             reinterpret_cast<BYTE*>(PTR_READ(pEntryPoint,
9085                 (ULONG32)ALIGN_UP(methodSize,
9086                     CODE_SIZE_ALIGN)));
9087         DisassembleMethod(codeStartHost, methodSize);
9088     }
9089
9090     DisplayEndStructure(METHODS); //Code 
9091
9092     DisplayEndElement(METHODS); //Method
9093 }
9094 #endif // FEATURE_READYTORUN
9095
9096 #if 0
9097 void NativeImageDumper::RecordTypeRef( mdTypeRef token, PTR_MethodTable mt )
9098 {
9099     if( mt != NULL )
9100         m_mtToTypeRefMap.Add( mt, token );
9101 }
9102 mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt )
9103 {
9104     return m_mtToTypeRefMap.Find(mt);
9105 }
9106 #endif
9107
9108 #else //!FEATURE_PREJIT
9109 //dummy implementation for dac
9110 HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase,
9111     LPCWSTR name,
9112     IXCLRDataDisplay* display,
9113     IXCLRLibrarySupport* support,
9114     IXCLRDisassemblySupport* dis)
9115 {
9116     return E_FAIL;
9117 }
9118 #endif //FEATURE_PREJIT
9119
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
9123  * are all about.
9124  */
9125 #ifdef __MSC_VER
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
9128 #endif // __MSC_VER
9129
9130 #undef assert
9131 #define assert(a)
9132 #define NOTHROW
9133 #define GC_NOTRIGGER
9134 #include <gcdecoder.cpp>
9135 #undef NOTHROW
9136 #undef GC_NOTRIGGER
9137
9138 #if defined _DEBUG && defined _TARGET_X86_ 
9139 #ifdef _MSC_VER
9140 // disable FPO for checked build
9141 #pragma optimize("y", off)
9142 #endif // _MSC_VER
9143 #endif
9144
9145 #undef _ASSERTE
9146 #define _ASSERTE(a) do {} while (0)
9147 #ifdef _TARGET_X86_
9148 #include <gcdump.cpp>
9149 #endif
9150
9151 #undef LIMITED_METHOD_CONTRACT
9152 #undef WRAPPER_NO_CONTRACT
9153 #ifdef _TARGET_X86_
9154 #include <i386/gcdumpx86.cpp>
9155 #else // !_TARGET_X86_
9156 #undef PREGDISPLAY
9157 #include <gcdumpnonx86.cpp>
9158 #endif // !_TARGET_X86_
9159
9160 #ifdef __MSC_VER
9161 #pragma warning(default:4244)
9162 #pragma warning(default:4189)
9163 #endif // __MSC_VER