7812bd72f0fd391660763b71cf6a9d82a3502cbd
[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 #ifdef HAS_RELATIVE_FIXUP_PRECODE
3490                     _ASSERTE(!"unreachable"); break;
3491 #else // HAS_RELATIVE_FIXUP_PRECODE
3492                     precodeName = "FixupPrecode"; break;
3493 #endif // HAS_RELATIVE_FIXUP_PRECODE
3494 #endif // HAS_FIXUP_PRECODE
3495 #ifdef HAS_RELATIVE_FIXUP_PRECODE
3496                 case PRECODE_RELATIVE_FIXUP:
3497                     precodeName = "RelativeFixupPrecode"; break;
3498 #endif // HAS_RELATIVE_FIXUP_PRECODE
3499 #ifdef HAS_THISPTR_RETBUF_PRECODE
3500                 case PRECODE_THISPTR_RETBUF:
3501                     precodeName = "ThisPtrRetBufPrecode"; break;
3502 #endif // HAS_THISPTR_RETBUF_PRECODE
3503                 }
3504                 
3505                 if( precodeName )
3506                 {
3507                     //hot or cold?
3508                     precodeBuf.AppendPrintf( W("%S (0x%p)"), precodeName, addr );
3509                 }
3510                 //get MethodDesc from precode and dump the target
3511                 PTR_MethodDesc precodeMD(maybePrecode->GetMethodDesc());
3512                 precodeBuf.Append( W(" for ") );
3513                 MethodDescToString(precodeMD, precodeBuf);
3514
3515                 _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)precodeBuf);
3516
3517                 *offset = 0;
3518                 return wcslen(name);
3519             }
3520         }
3521
3522         PTR_CORCOMPILE_IMPORT_SECTION pImportSection = m_decoder.GetNativeImportSectionForRVA(rva);
3523         if (pImportSection != NULL)
3524         {
3525             const char * wbRangeName = NULL;
3526             switch (pImportSection->Type)
3527             {
3528             case CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD:
3529                 wbRangeName = "ExternalMethod";
3530                 break;
3531
3532 #if 0
3533             case CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD:
3534                 wbRangeName = "VirtualMethod";
3535                 break;
3536
3537             case CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH:
3538                 wbRangeName = "StubDispatch";
3539                 break;
3540 #endif
3541
3542             // This method is only ever called for targets of direct calls right now and so the only
3543             // import that can meaninfully show up here is external method thunk.
3544             default:
3545                 return 0;
3546             }
3547
3548             TempBuffer fixupThunkBuf;
3549             fixupThunkBuf.AppendPrintf( W("%S (0x%p) for "), wbRangeName, addr );
3550             FixupThunkToString(pImportSection, (TADDR)addr, fixupThunkBuf);
3551
3552             _snwprintf_s(name, nameSize, _TRUNCATE, W("%s"), (const WCHAR *)fixupThunkBuf);
3553
3554             *offset = 0;
3555             return wcslen(name);
3556         }
3557     }
3558     else if( g_dacImpl->GetJitHelperFunctionName(addr,
3559                                                  _countof(bigByteBuffer),
3560                                                  (char*)bigByteBuffer,
3561                                                  NULL ) == S_OK )
3562     {
3563         *offset = 0;
3564         _snwprintf_s( name, nameSize, _TRUNCATE, W("%S"), bigByteBuffer );
3565         return wcslen(name);
3566     }
3567     else
3568     {
3569         //check mscorwks
3570         if( m_mscorwksBase <= addr &&
3571             addr < (m_mscorwksBase + m_mscorwksSize) )
3572         {
3573             *offset = addr - m_mscorwksBase;
3574             _snwprintf_s( name, nameSize, _TRUNCATE, W("clr") );
3575             return wcslen(name);
3576         }
3577         for( COUNT_T i = 0; i < m_numDependencies; ++i )
3578         {
3579             const Dependency& dep = m_dependencies[i];
3580             if( dep.pLoadedAddress <= addr &&
3581                 addr < (dep.pLoadedAddress + dep.size) )
3582             {
3583                 *offset = addr - dep.pLoadedAddress;
3584                 _snwprintf_s( name, nameSize, _TRUNCATE, W("%s.ni"), dep.name );
3585                 return wcslen(name);
3586             }
3587         }
3588     }
3589
3590     return 0;
3591 }
3592
3593 BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
3594 {
3595     PTR_SIZE_T fixupPtr(TO_TADDR(fixupCell));
3596     m_display->StartElement( "Fixup" );
3597     m_display->WriteElementPointer( "Address",
3598                                     DataPtrToDisplay( TO_TADDR(fixupCell) ) );
3599     m_display->WriteElementUInt( "TaggedValue", (DWORD)*fixupPtr );
3600     WriteElementsFixupBlob(pSection, *fixupPtr);
3601     m_display->EndElement();
3602
3603     return TRUE;
3604 }
3605
3606 void NativeImageDumper::DumpMethodFixups(PTR_Module module,
3607                                          TADDR fixupList)
3608 {
3609     _ASSERTE( CHECK_OPT(METHODS) );
3610
3611     COUNT_T nImportSections;
3612     PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
3613
3614     //create the first element outside of the callback.  The callback creates
3615     //subsequent elements.
3616     module->FixupDelayListAux( fixupList, this,
3617                                &NativeImageDumper::HandleFixupForMethodDump,
3618                                pImportSections, nImportSections,
3619                                &m_decoder );
3620 }
3621
3622 IMAGE_SECTION_HEADER * NativeImageDumper::FindSection( char const * name )
3623 {
3624     COUNT_T numberOfSections = m_decoder.GetNumberOfSections();
3625     PTR_IMAGE_SECTION_HEADER curSection( m_decoder.FindFirstSection() );
3626
3627     for ( ; numberOfSections > 0; --numberOfSections, ++curSection )
3628     {
3629         if ( ! strncmp( reinterpret_cast< char * >( curSection->Name ), name, 8 ) )
3630             break;
3631     }
3632
3633     if ( ! numberOfSections )
3634         return NULL;
3635
3636     return curSection;    
3637 }
3638
3639 NativeImageDumper::EnumMnemonics NativeImageDumper::s_ModulePersistedFlags[] =
3640 {
3641 #define MPF_ENTRY(f) NativeImageDumper::EnumMnemonics(Module::f, W(#f))
3642     MPF_ENTRY(COMPUTED_GLOBAL_CLASS),
3643
3644     MPF_ENTRY(COMPUTED_STRING_INTERNING),
3645     MPF_ENTRY(NO_STRING_INTERNING),
3646
3647     MPF_ENTRY(COMPUTED_WRAP_EXCEPTIONS),
3648     MPF_ENTRY(WRAP_EXCEPTIONS),
3649
3650     MPF_ENTRY(COMPUTED_RELIABILITY_CONTRACT),
3651
3652     MPF_ENTRY(COLLECTIBLE_MODULE),
3653     MPF_ENTRY(COMPUTED_IS_PRE_V4_ASSEMBLY),
3654     MPF_ENTRY(IS_PRE_V4_ASSEMBLY),
3655     MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED),
3656     MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS),
3657
3658     MPF_ENTRY(COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP),
3659     MPF_ENTRY(LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME),    
3660 #undef MPF_ENTRY
3661 };
3662
3663 //VirtualSectionTypes.
3664 #define TEXTIFY(x) W(#x)
3665 static const NativeImageDumper::EnumMnemonics s_virtualSectionFlags [] = 
3666 {
3667
3668 #define CORCOMPILE_SECTION_IBCTYPE(ibcType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(ibcType)),
3669     CORCOMPILE_SECTION_IBCTYPES()
3670 #undef CORCOMPILE_SECTION_IBCTYPE
3671
3672 #define CORCOMPILE_SECTION_RANGE_TYPE(rangeType, _value) NativeImageDumper::EnumMnemonics(_value, TEXTIFY(rangeType) W("Range")),
3673     CORCOMPILE_SECTION_RANGE_TYPES()
3674 #undef CORCOMPILE_SECTION_RANGE_TYPE
3675 };
3676 const WCHAR * g_sectionNames[] = 
3677 {
3678     W("SECTION_DUMMY"), // the first section start at 0x1. Make the array 1 based.
3679 #define CORCOMPILE_SECTION_TYPE(section) W("SECTION_") TEXTIFY(section),
3680     CORCOMPILE_SECTION_TYPES()
3681 #undef CORCOMPILE_SECTION
3682
3683 };
3684 #undef TEXTIFY
3685
3686
3687 #ifdef _PREFAST_
3688 #pragma warning(push)
3689 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3690 #endif
3691
3692 void NativeImageDumper::DumpModule( PTR_Module module )
3693 {
3694
3695     //the module is the fisrt thing in the .data section.  We use this fact for
3696     //the sectionBases down below.
3697 //    _ASSERTE(m_decoder.GetDataRva(PTR_TO_TADDR(module))
3698 //             == FindSection(".data")->VirtualAddress );
3699
3700     DisplayStartStructure( "module", DPtrToPreferredAddr(module),
3701                            sizeof(*module), MODULE );
3702     PTR_PEFile file = module->m_file;
3703     _ASSERTE(file == NULL); 
3704     DisplayWriteFieldPointer( m_file, DPtrToPreferredAddr(file), Module,
3705                               MODULE );
3706
3707     PTR_MethodDesc dllMain( TO_TADDR(module->m_pDllMain) );
3708     WriteFieldMethodDesc( m_pDllMain, dllMain, Module,
3709                           MODULE );
3710
3711     _ASSERTE(module->m_dwTransientFlags == 0U);
3712     DisplayWriteFieldUInt(m_dwTransientFlags, module->m_dwTransientFlags,
3713                           Module, MODULE );
3714                            
3715
3716
3717     DisplayWriteFieldEnumerated( m_dwPersistedFlags, module->m_dwPersistedFlags,
3718                                  Module, s_ModulePersistedFlags, W("|"), MODULE );
3719
3720     DisplayWriteFieldPointer( m_pAssembly,
3721                               DPtrToPreferredAddr(module->m_pAssembly),
3722                               Module, MODULE );
3723     _ASSERTE(module->m_pAssembly == NULL); //never appears in the image
3724
3725     DisplayWriteFieldUInt( m_moduleRef, module->m_moduleRef, Module, MODULE );
3726     DisplayWriteFieldInt( m_dwDebuggerJMCProbeCount,
3727                           module->m_dwDebuggerJMCProbeCount, Module, MODULE );
3728     /* REVISIT_TODO Fri 10/14/2005
3729      * Dump the binder
3730      */
3731     PTR_MscorlibBinder binder = module->m_pBinder;
3732     if( NULL != binder )
3733     {
3734         DisplayStartStructureWithOffset( m_pBinder, DPtrToPreferredAddr(binder),
3735                                          sizeof(*binder), Module,
3736                                          MODULE );
3737
3738         //these four fields don't have anything useful in ngen images.
3739         DisplayWriteFieldPointer( m_classDescriptions,
3740                                   DPtrToPreferredAddr(binder->m_classDescriptions),
3741                                   MscorlibBinder, MODULE );
3742         DisplayWriteFieldPointer( m_methodDescriptions,
3743                                   DPtrToPreferredAddr(binder->m_methodDescriptions),
3744                                   MscorlibBinder, MODULE );
3745         DisplayWriteFieldPointer( m_fieldDescriptions,
3746                                   DPtrToPreferredAddr(binder->m_fieldDescriptions),
3747                                   MscorlibBinder, MODULE );
3748         DisplayWriteFieldPointer( m_pModule,
3749                                   DPtrToPreferredAddr(binder->m_pModule),
3750                                   MscorlibBinder, MODULE );
3751
3752         DisplayWriteFieldInt( m_cClasses, binder->m_cClasses, MscorlibBinder,
3753                               MODULE );
3754         DisplayWriteFieldAddress( m_pClasses,
3755                                   DPtrToPreferredAddr(binder->m_pClasses),
3756                                   sizeof(*binder->m_pClasses)
3757                                   * binder->m_cClasses,
3758                                   MscorlibBinder, MODULE );
3759         DisplayWriteFieldInt( m_cFields, binder->m_cFields, MscorlibBinder,
3760                               MODULE );
3761         DisplayWriteFieldAddress( m_pFields,
3762                                   DPtrToPreferredAddr(binder->m_pFields),
3763                                   sizeof(*binder->m_pFields)
3764                                   * binder->m_cFields,
3765                                   MscorlibBinder, MODULE );
3766         DisplayWriteFieldInt( m_cMethods, binder->m_cMethods, MscorlibBinder,
3767                               MODULE );
3768         DisplayWriteFieldAddress( m_pMethods,
3769                                   DPtrToPreferredAddr(binder->m_pMethods),
3770                                   sizeof(*binder->m_pMethods)
3771                                   * binder->m_cMethods,
3772                                   MscorlibBinder, MODULE );
3773
3774         DisplayEndStructure( MODULE ); //m_pBinder
3775     }
3776     else
3777     {
3778         DisplayWriteFieldPointer( m_pBinder, NULL, Module, MODULE );
3779     }
3780
3781
3782     /* REVISIT_TODO Tue 10/25/2005
3783      * unconditional dependencies, activations, class dependencies, thunktable
3784      */
3785
3786
3787     //round trip the LookupMap back through the DAC so that we don't have an
3788     //interior host pointer.
3789     PTR_LookupMapBase lookupMap( PTR_TO_TADDR(module)
3790                              + offsetof(Module, m_TypeDefToMethodTableMap) );
3791     TraverseMap( lookupMap, "m_TypeDefToMethodTableMap",
3792                  offsetof(Module, m_TypeDefToMethodTableMap),
3793                  fieldsize(Module, m_TypeDefToMethodTableMap), 
3794                  &NativeImageDumper::IterateTypeDefToMTCallback );
3795
3796     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3797                                + offsetof(Module, m_TypeRefToMethodTableMap) );
3798
3799     TraverseMap( lookupMap, "m_TypeRefToMethodTableMap", 
3800                  offsetof(Module, m_TypeRefToMethodTableMap),
3801                  fieldsize(Module, m_TypeRefToMethodTableMap),
3802                  &NativeImageDumper::IterateTypeRefToMTCallback );
3803
3804     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3805                                + offsetof(Module, m_MethodDefToDescMap) );
3806     TraverseMap( lookupMap, "m_MethodDefToDescMap",
3807                  offsetof(Module, m_MethodDefToDescMap),
3808                  fieldsize(Module, m_MethodDefToDescMap),
3809                  &NativeImageDumper::IterateMethodDefToMDCallback);
3810
3811     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3812                                + offsetof(Module, m_FieldDefToDescMap) );
3813     TraverseMap( lookupMap, "m_FieldDefToDescMap",
3814                  offsetof(Module, m_FieldDefToDescMap),
3815                  fieldsize(Module, m_FieldDefToDescMap),
3816                  &NativeImageDumper::IterateFieldDefToFDCallback);
3817
3818     TraverseMemberRefToDescHash(module->m_pMemberRefToDescHashTable, "m_pMemberRefToDescHashTable", 
3819                                 offsetof(Module, m_pMemberRefToDescHashTable),
3820                                 fieldsize(Module, m_pMemberRefToDescHashTable),
3821                                 FALSE);
3822
3823     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3824                                + offsetof(Module, m_GenericParamToDescMap) );
3825
3826     TraverseMap( lookupMap, "m_GenericParamToDescMap",
3827                  offsetof(Module, m_GenericParamToDescMap),
3828                  fieldsize(Module, m_GenericParamToDescMap),
3829                  &NativeImageDumper::IterateGenericParamToDescCallback);
3830
3831     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3832                                + offsetof(Module, m_GenericTypeDefToCanonMethodTableMap) );
3833
3834     TraverseMap( lookupMap, "m_GenericTypeDefToCanonMethodTableMap",
3835                  offsetof(Module, m_GenericTypeDefToCanonMethodTableMap),
3836                  fieldsize(Module, m_GenericTypeDefToCanonMethodTableMap),
3837                  &NativeImageDumper::IterateTypeDefToMTCallback );
3838
3839     lookupMap = PTR_LookupMapBase( PTR_TO_TADDR(module)
3840                                + offsetof(Module, m_FileReferencesMap) );
3841     TraverseMap( lookupMap, "m_FileReferencesMap",
3842                  offsetof(Module, m_FileReferencesMap),
3843                  fieldsize(Module, m_FileReferencesMap),
3844                  &NativeImageDumper::IterateMemberRefToDescCallback);
3845
3846     lookupMap = PTR_LookupMapBase(PTR_TO_TADDR(module)
3847                               + offsetof(Module,m_ManifestModuleReferencesMap));
3848
3849     TraverseMap( lookupMap, "m_ManifestModuleReferencesMap",
3850                  offsetof(Module, m_ManifestModuleReferencesMap),
3851                  fieldsize(Module, m_ManifestModuleReferencesMap),
3852                  &NativeImageDumper::IterateManifestModules);
3853
3854     TraverseClassHash( module->m_pAvailableClasses, "m_pAvailableClasses",
3855                        offsetof(Module, m_pAvailableClasses),
3856                        fieldsize(Module, m_pAvailableClasses), true );
3857
3858     TraverseTypeHash( module->m_pAvailableParamTypes, "m_pAvailableParamTypes",
3859                       offsetof(Module, m_pAvailableParamTypes),
3860                       fieldsize(Module, m_pAvailableParamTypes) ); 
3861     TraverseInstMethodHash( module->m_pInstMethodHashTable,
3862                             "m_pInstMethodHashTable",
3863                             offsetof(Module, m_pInstMethodHashTable),
3864                             fieldsize(Module, m_pInstMethodHashTable),
3865                             module );
3866     TraverseStubMethodHash( module->m_pStubMethodHashTable,
3867                             "m_pStubMethodHashTable",
3868                             offsetof(Module, m_pStubMethodHashTable),
3869                             fieldsize(Module, m_pStubMethodHashTable),
3870                             module );
3871
3872     IF_OPT(MODULE)
3873     {
3874         TraverseClassHash( module->m_pAvailableClassesCaseIns,
3875                            "m_pAvailableClassesCaseIns",
3876                            offsetof(Module, m_pAvailableClassesCaseIns),
3877                            fieldsize(Module, m_pAvailableClassesCaseIns),
3878                            false );
3879     }
3880
3881 #ifdef FEATURE_COMINTEROP
3882     TraverseGuidToMethodTableHash( module->m_pGuidToTypeHash, 
3883                             "m_pGuidToTypeHash",
3884                             offsetof(Module, m_pGuidToTypeHash),
3885                             fieldsize(Module, m_pGuidToTypeHash),
3886                             true);
3887
3888 #endif // FEATURE_COMINTEROP
3889
3890     _ASSERTE(module->m_pProfilingBlobTable == NULL);
3891
3892     DisplayWriteFieldFlag( m_nativeImageProfiling,
3893                            module->m_nativeImageProfiling, Module, MODULE );
3894
3895     DisplayWriteFieldPointer( m_methodProfileList,
3896                               DataPtrToDisplay((TADDR)module->m_methodProfileList),
3897                               Module, MODULE );
3898     _ASSERTE(module->m_methodProfileList == NULL);
3899
3900     /* REVISIT_TODO Tue 10/04/2005
3901      * Dump module->m_moduleCtorInfo
3902      */
3903     PTR_ModuleCtorInfo ctorInfo( PTR_HOST_MEMBER_TADDR(Module, module,
3904                                                        m_ModuleCtorInfo) );
3905
3906     DisplayStartStructureWithOffset( m_ModuleCtorInfo,
3907                                      DPtrToPreferredAddr(ctorInfo), 
3908                                      sizeof(*ctorInfo),
3909                                      Module, SLIM_MODULE_TBLS );
3910     DisplayWriteFieldInt( numElements, ctorInfo->numElements, ModuleCtorInfo,
3911                           SLIM_MODULE_TBLS );
3912     DisplayWriteFieldInt( numLastAllocated, ctorInfo->numLastAllocated,
3913                           ModuleCtorInfo, SLIM_MODULE_TBLS );
3914     DisplayWriteFieldInt( numElementsHot, ctorInfo->numElementsHot,
3915                           ModuleCtorInfo, SLIM_MODULE_TBLS );
3916     DisplayWriteFieldAddress( ppMT, DPtrToPreferredAddr(ctorInfo->ppMT),
3917                               ctorInfo->numElements * sizeof(RelativePointer<MethodTable*>),
3918                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3919     /* REVISIT_TODO Tue 03/21/2006
3920      * is cctorInfoHot and cctorInfoCold actually have anything interesting
3921      * inside of them?
3922      */
3923     DisplayWriteFieldAddress( cctorInfoHot,
3924                               DPtrToPreferredAddr(ctorInfo->cctorInfoHot),
3925                               sizeof(*ctorInfo->cctorInfoHot)
3926                                 * ctorInfo->numElementsHot,
3927                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3928     DisplayWriteFieldAddress( cctorInfoCold,
3929                               DPtrToPreferredAddr(ctorInfo->cctorInfoCold),
3930                               sizeof(*ctorInfo->cctorInfoCold)
3931                                 * (ctorInfo->numElements
3932                                    - ctorInfo->numElementsHot),
3933                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3934     /* XXX Thu 03/23/2006
3935      * See ModuleCtorInfo::Save for why these are +1.
3936      */
3937     DisplayWriteFieldAddress( hotHashOffsets,
3938                               DPtrToPreferredAddr(ctorInfo->hotHashOffsets),
3939                               (ctorInfo->numHotHashes + 1)
3940                               * sizeof(*ctorInfo->hotHashOffsets),
3941                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3942     DisplayWriteFieldAddress( coldHashOffsets,
3943                               DPtrToPreferredAddr(ctorInfo->coldHashOffsets),
3944                               (ctorInfo->numColdHashes + 1)
3945                               * sizeof(*ctorInfo->coldHashOffsets),
3946                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3947
3948     DisplayWriteFieldInt( numHotHashes, ctorInfo->numHotHashes, ModuleCtorInfo,
3949                           SLIM_MODULE_TBLS );
3950     DisplayWriteFieldInt( numColdHashes, ctorInfo->numColdHashes,
3951                           ModuleCtorInfo, SLIM_MODULE_TBLS );
3952
3953     DisplayWriteFieldAddress( ppHotGCStaticsMTs,
3954                               DPtrToPreferredAddr(ctorInfo->ppHotGCStaticsMTs),
3955                               ctorInfo->numHotGCStaticsMTs
3956                               * sizeof(*ctorInfo->ppHotGCStaticsMTs),
3957                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3958     DisplayWriteFieldAddress( ppColdGCStaticsMTs,
3959                               DPtrToPreferredAddr(ctorInfo->ppColdGCStaticsMTs),
3960                               ctorInfo->numColdGCStaticsMTs
3961                               * sizeof(*ctorInfo->ppColdGCStaticsMTs),
3962                               ModuleCtorInfo, SLIM_MODULE_TBLS );
3963     DisplayWriteFieldInt( numHotGCStaticsMTs, ctorInfo->numHotGCStaticsMTs,
3964                           ModuleCtorInfo, SLIM_MODULE_TBLS );
3965     DisplayWriteFieldInt( numColdGCStaticsMTs, ctorInfo->numColdGCStaticsMTs,
3966                           ModuleCtorInfo, SLIM_MODULE_TBLS );
3967
3968     DisplayEndStructure( SLIM_MODULE_TBLS ); //m_ModuleCtorInfo
3969
3970     _ASSERTE(module->m_pNgenStats == NULL);
3971
3972     DisplayWriteFieldPointer( m_pNgenStats,
3973                               DataPtrToDisplay((TADDR)module->m_pNgenStats),
3974                               Module, MODULE );
3975
3976     DisplayWriteFieldAddress(m_propertyNameSet,
3977                              DPtrToPreferredAddr(module->m_propertyNameSet),
3978                              sizeof(module->m_propertyNameSet[0]) *
3979                              module->m_nPropertyNameSet,
3980                              Module, MODULE);
3981
3982     DisplayWriteFieldPointer( m_ModuleID,
3983                               DataPtrToDisplay(dac_cast<TADDR>(module->m_ModuleID)),
3984                               Module, MODULE );
3985     _ASSERTE(module->m_ModuleID == NULL);
3986
3987     /* XXX Tue 04/11/2006
3988      * Value is either -1 or 0, so no need to rebase.
3989      */
3990     DisplayWriteFieldPointer( m_pRegularStaticOffsets,
3991                               PTR_TO_TADDR(module->m_pRegularStaticOffsets),
3992                               Module, MODULE );
3993     _ASSERTE(module->m_pRegularStaticOffsets == (void*)-1
3994              || module->m_pRegularStaticOffsets == 0 );
3995
3996     DisplayWriteFieldInt( m_dwMaxGCRegularStaticHandles,
3997                           module->m_dwMaxGCRegularStaticHandles, Module, MODULE );
3998     DisplayWriteFieldInt( m_dwRegularStaticsBlockSize, module->m_dwRegularStaticsBlockSize,
3999                           Module, MODULE );
4000     DisplayWriteFieldAddress( m_pDynamicStaticsInfo,
4001                               DataPtrToDisplay((TADDR)module->m_pDynamicStaticsInfo),
4002                               module->m_maxDynamicEntries
4003                                 * sizeof(*(module->m_pDynamicStaticsInfo)),
4004                               Module, MODULE );
4005
4006     DisplayWriteFieldInt( m_cDynamicEntries,
4007                           (int)module->m_cDynamicEntries, Module, MODULE );
4008
4009     CoverageRead(TO_TADDR(module->m_pDynamicStaticsInfo),
4010                  (int)(module->m_maxDynamicEntries
4011                  * sizeof(*(module->m_pDynamicStaticsInfo))));
4012
4013
4014
4015     _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL);
4016     DisplayWriteFieldPointer( m_debuggerSpecificData.m_pDynamicILCrst,
4017                               DataPtrToDisplay(dac_cast<TADDR>(module->m_debuggerSpecificData.m_pDynamicILCrst)),
4018                               Module, MODULE );
4019
4020
4021     /* REVISIT_TODO Wed 09/21/2005
4022      * Get me in the debugger and look at the activations and module/class
4023      * dependencies.
4024      * As well as the thunks.
4025      */
4026     
4027     /* REVISIT_TODO Wed 09/21/2005
4028      * Dump the following
4029      */
4030     //file
4031     //assembly
4032
4033     DisplayWriteFieldInt( m_DefaultDllImportSearchPathsAttributeValue,
4034                           module->m_DefaultDllImportSearchPathsAttributeValue, Module, MODULE );
4035
4036
4037     DisplayEndStructure(MODULE); //Module
4038 }
4039 #ifdef _PREFAST_
4040 #pragma warning(pop)
4041 #endif
4042
4043 bool NativeImageDumper::isPrecode(TADDR maybePrecode)
4044 {
4045     PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
4046
4047     return !!module->IsZappedPrecode(maybePrecode);
4048 }
4049
4050
4051 void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget,
4052                                                     TADDR flags,
4053                                                     PTR_LookupMapBase map,
4054                                                     DWORD rid )
4055 {
4056     DisplayStartElement( "Entry", MODULE_TABLES );
4057
4058     PTR_MethodTable mt(mtTarget);
4059
4060     DisplayWriteElementUInt( "Token", rid | mdtTypeDef, MODULE_TABLES );
4061     /* REVISIT_TODO Fri 10/21/2005
4062      * Can I use WriteElementMethodTable here?
4063      */
4064     DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4065                                 MODULE_TABLES );
4066     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4067     /* REVISIT_TODO Fri 09/30/2005
4068      * This handles the extra entries in the type table that shouldn't be there.
4069      */
4070     if( rid == 0 || ((rid != 1) && (mtTarget == NULL)) )
4071     {
4072         DisplayWriteElementString( "Name", "mdTypeDefNil", MODULE_TABLES );
4073     }
4074     else
4075     {
4076         TempBuffer buf;
4077         MethodTableToString( mt, buf );
4078         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4079     }
4080     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4081                              MODULE_TABLES );
4082     DisplayEndElement( MODULE_TABLES );
4083
4084     if( isInRange(PTR_TO_TADDR(mt)) )
4085     {
4086         m_discoveredMTs.AppendEx(mt);
4087         PTR_EEClass clazz = GetClassFromMT(mt);
4088         if( isInRange(PTR_TO_TADDR(clazz)) )
4089             m_discoveredClasses.AppendEx(mt);
4090     }
4091 }
4092
4093 void NativeImageDumper::IterateTypeRefToMTCallback( TADDR mtTarget,
4094                                                     TADDR flags,
4095                                                     PTR_LookupMapBase map,
4096                                                     DWORD rid )
4097 {
4098     DisplayStartElement( "Entry", MODULE_TABLES );
4099
4100     mtTarget = ((FixupPointer<TADDR>&)mtTarget).GetValue();
4101
4102     PTR_MethodTable mt(mtTarget);
4103
4104 #if 0
4105     RecordTypeRef(rid | mdtTypeRef, mt);
4106 #endif
4107
4108     DisplayWriteElementUInt( "Token", rid | mdtTypeRef, MODULE_TABLES );
4109
4110     DisplayWriteElementPointer( "MethodTable", DPtrToPreferredAddr(mt),
4111                                 MODULE_TABLES );
4112
4113     if( rid == 0 )
4114     {
4115         DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4116         DisplayWriteElementString( "Name", "mdtTypeRefNil", MODULE_TABLES );
4117     }
4118     else if( mt == NULL )
4119     {
4120         DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4121         IF_OPT(MODULE_TABLES)
4122             WriteElementMDToken( "Name", mdtTypeRef | rid );
4123     }
4124     else if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
4125     {
4126         RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
4127         //
4128         // This guy writes two things FixupTargetValue and FixupTargetName
4129         //
4130         WriteElementsFixupBlob( NULL,PTR_TO_TADDR(mt));
4131     }
4132     else
4133     {
4134         TempBuffer buf;
4135         MethodTableToString( mt, buf ); 
4136         DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4137         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4138     }
4139     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4140                              MODULE_TABLES );
4141     DisplayEndElement( MODULE_TABLES );
4142     if( isInRange(mtTarget) )
4143     {
4144         m_discoveredMTs.AppendEx(mt);
4145         PTR_EEClass clazz = GetClassFromMT(mt);
4146         if( isInRange(PTR_TO_TADDR(clazz)) )
4147             m_discoveredClasses.AppendEx(mt);
4148     }
4149 }
4150
4151 void NativeImageDumper::IterateMethodDefToMDCallback( TADDR mdTarget,
4152                                                       TADDR flags,
4153                                                       PTR_LookupMapBase map,
4154                                                       DWORD rid )
4155 {
4156     DisplayStartElement( "Entry", MODULE_TABLES );
4157
4158     PTR_MethodDesc md(mdTarget);
4159
4160     DisplayWriteElementUInt( "Token", rid | mdtMethodDef, MODULE_TABLES );
4161
4162     DisplayWriteElementPointer( "MethodDesc", DPtrToPreferredAddr(md),
4163                                 MODULE_TABLES );
4164
4165     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4166     if( rid == 0 )
4167     {
4168         DisplayWriteElementString( "Name", "mdtMethodDefNil", MODULE_TABLES );
4169     }
4170     else
4171     {
4172         TempBuffer buf;
4173         MethodDescToString( md, buf );
4174         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4175     }
4176     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4177                              MODULE_TABLES );
4178     DisplayEndElement( MODULE_TABLES );
4179     //m_discoveredMDs.AppendEx(md);
4180 }
4181
4182 void NativeImageDumper::IterateFieldDefToFDCallback( TADDR fdTarget,
4183                                                      TADDR flags,
4184                                                      PTR_LookupMapBase map,
4185                                                      DWORD rid )
4186 {
4187     PTR_FieldDesc fd(fdTarget);
4188     DisplayStartElement( "Entry", MODULE_TABLES );
4189
4190
4191     DisplayWriteElementUInt( "Token", rid | mdtFieldDef, MODULE_TABLES );
4192
4193     DisplayWriteElementPointer( "FieldDef", DPtrToPreferredAddr(fd),
4194                                 MODULE_TABLES );
4195
4196     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4197     if( rid == 0 )
4198     {
4199         DisplayWriteElementString( "Name", "mdtFieldDefNil", MODULE_TABLES );
4200     }
4201     else
4202     {
4203         TempBuffer buf;
4204         FieldDescToString( fd, mdtFieldDef | rid, buf );
4205         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4206     }
4207     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4208                              MODULE_TABLES );
4209     DisplayEndElement( MODULE_TABLES );
4210     /* XXX Mon 10/17/2005
4211      * All FieldDescs are reachable from the EEClasses
4212      */
4213     //m_discoveredFDs.AppendEx(PTR_FieldDesc(fdTarget));
4214 }
4215
4216 void NativeImageDumper::IterateMemberRefToDescCallback( TADDR mrTarget,
4217                                                         TADDR flags,
4218                                                         PTR_LookupMapBase map,
4219                                                         DWORD rid )
4220 {
4221     DisplayStartElement( "Entry", MODULE_TABLES );
4222
4223
4224     bool isFieldRef = (flags & IS_FIELD_MEMBER_REF) != 0;
4225     mdToken targetToken =  mdtMemberRef | rid;
4226     mrTarget = ((FixupPointer<TADDR>&)mrTarget).GetValue();
4227     DisplayWriteElementUInt( "Token", targetToken, MODULE_TABLES );
4228     DisplayWriteElementPointer( isFieldRef ? "FieldDesc" : "MethodDesc",
4229                                 DataPtrToDisplay(mrTarget), MODULE_TABLES );
4230
4231     TempBuffer buf;
4232     if( rid == 0 )
4233     {
4234         buf.Append( W("mdtMemberDefNil") );
4235     }
4236     else if( CORCOMPILE_IS_POINTER_TAGGED(mrTarget) )
4237     {
4238         WriteElementsFixupBlob( NULL, mrTarget );
4239     }    
4240     else if( isFieldRef )
4241     {
4242         FieldDescToString( PTR_FieldDesc(mrTarget), buf );
4243     }
4244     else
4245     {
4246         MethodDescToString( PTR_MethodDesc(mrTarget), buf );
4247     }
4248     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4249     DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4250
4251     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4252                              MODULE_TABLES );
4253     DisplayEndElement(MODULE_TABLES);
4254     //m_discoveredMTs.AppendEx(mt);
4255 }
4256
4257 void NativeImageDumper::IterateGenericParamToDescCallback( TADDR tdTarget,
4258                                                      TADDR flags,
4259                                                      PTR_LookupMapBase map,
4260                                                      DWORD rid )
4261 {
4262     PTR_TypeDesc td(tdTarget);
4263     DisplayStartElement( "Entry", MODULE_TABLES );
4264
4265
4266     DisplayWriteElementUInt( "Token", rid | mdtGenericParam, MODULE_TABLES );
4267
4268     DisplayWriteElementPointer( "GenericParam", DPtrToPreferredAddr(td),
4269                                 MODULE_TABLES );
4270
4271     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4272     if( rid == 0 || td == NULL )
4273     {
4274         DisplayWriteElementString( "Name", "mdtGenericParamNil", MODULE_TABLES );
4275     }
4276     else
4277     {
4278         TempBuffer buf;
4279         TypeDescToString( td, buf );
4280         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4281     }
4282     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4283                              MODULE_TABLES );
4284     DisplayEndElement( MODULE_TABLES );
4285 }
4286
4287 #if 0
4288 void NativeImageDumper::IterateFileReferencesCallback(TADDR moduleTarget,
4289                                                       TADDR flags,
4290                                                       PTR_LookupMapBase map,
4291                                                       DWORD rid)
4292 {
4293     DisplayStartElement( "Entry", MODULE_TABLES );
4294
4295     PTR_Module module(moduleTarget);
4296
4297     DisplayWriteElementUInt( "Token", rid | mdtFile, MODULE_TABLES );
4298
4299     DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4300                                 MODULE_TABLES );
4301
4302     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4303     if( rid == 0 || (module == NULL) )
4304     {
4305         DisplayWriteElementString( "Name", "mdtFileNil", MODULE_TABLES );
4306     }
4307     else
4308     {
4309         TempBuffer buf;
4310         AppendTokenName(mdtFile | rid, buf);
4311         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4312     }
4313     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4314                              MODULE_TABLES );
4315     DisplayEndElement( MODULE_TABLES );
4316     //m_discoveredFDs.AppendEx(mt);
4317 }
4318 #endif
4319
4320 void NativeImageDumper::IterateManifestModules( TADDR moduleTarget,
4321                                                TADDR flags,
4322                                                PTR_LookupMapBase map, 
4323                                                DWORD rid )
4324 {
4325     DisplayStartElement( "Entry", MODULE_TABLES );
4326
4327     moduleTarget = ((FixupPointer<TADDR>&)moduleTarget).GetValue();
4328
4329     PTR_Module module(moduleTarget);
4330
4331     DisplayWriteElementUInt( "Token", rid | mdtAssemblyRef, MODULE_TABLES );
4332
4333     DisplayWriteElementPointer( "Module", DPtrToPreferredAddr(module),
4334                                 MODULE_TABLES );
4335     DisplayWriteElementFlag( "fake", false, MODULE_TABLES );
4336     if( rid == 0 || (module == NULL) )
4337     {
4338         DisplayWriteElementString( "Name", "mdtAssemblyRefNil", MODULE_TABLES );
4339     }
4340     else
4341     {
4342         TempBuffer buf;
4343         AppendTokenName(mdtAssemblyRef | rid, buf, m_import);
4344         DisplayWriteElementStringW( "Name", (const WCHAR*)buf, MODULE_TABLES );
4345     }
4346     DisplayWriteElementFlag( "hot", !!map->FindHotItemValuePtr(rid),
4347                              MODULE_TABLES );
4348     DisplayEndElement( MODULE_TABLES );
4349     //m_discoveredFDs.AppendEx(mt);
4350 }
4351
4352 void NativeImageDumper::TraverseMap(PTR_LookupMapBase map, const char * name,
4353                                     unsigned offset, unsigned fieldSize,
4354                                     void(NativeImageDumper::*cb)(TADDR,
4355                                                                  TADDR,
4356                                                                  PTR_LookupMapBase,
4357                                                                  DWORD))
4358 {
4359     if( map == NULL )
4360     {
4361         IF_OPT(MODULE)
4362             m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
4363         return;
4364     }
4365     DisplayStartVStructure(name, MODULE);
4366
4367     DisplayStartArray( "Tables", W("%s"), MODULE );
4368     PTR_LookupMapBase current = map;
4369     do
4370     {
4371         DWORD cbTable = map->MapIsCompressed() ? map->cbTable : map->dwCount * sizeof(*map->pTable);
4372
4373         IF_OPT(MODULE)
4374         {
4375             DisplayWriteElementAddress( "Table",
4376                                         DPtrToPreferredAddr(map->pTable),
4377                                         cbTable,
4378                                         MODULE);
4379         }
4380
4381         CoverageRead( PTR_TO_TADDR(map->pTable), cbTable );
4382         _ASSERTE(current == map || current->hotItemList == NULL);
4383         current = current->pNext;
4384     }while( current != NULL );
4385     
4386     DisplayEndArray( "Total Tables", MODULE ); //Tables
4387
4388     DisplayWriteFieldAddress( hotItemList,
4389                               DPtrToPreferredAddr(map->hotItemList),
4390                               map->dwNumHotItems * sizeof(*map->hotItemList),
4391                               LookupMapBase, MODULE );
4392
4393     DisplayStartArray( "Map", W("[%s]: %s %s%s  %s %s %s"), MODULE_TABLES );
4394
4395     IF_OPT_OR3(MODULE_TABLES, EECLASSES, METHODTABLES)
4396     {
4397         LookupMap<TADDR>::Iterator iter(dac_cast<DPTR(LookupMap<TADDR>)>(map));
4398         DWORD rid = 0;
4399         while(iter.Next())
4400         {
4401             TADDR flags = 0;
4402             TADDR element = iter.GetElementAndFlags(&flags);
4403             (this->*cb)( element, flags, map, rid );
4404             rid++;                         
4405         }
4406
4407     }
4408     CoverageRead( PTR_TO_TADDR(map->hotItemList),
4409                   map->dwNumHotItems * sizeof(*map->hotItemList) );
4410     DisplayEndArray( "Total" , MODULE_TABLES );//Map
4411
4412     DisplayEndVStructure(MODULE); //name
4413 }
4414
4415 // Templated method containing the core code necessary to traverse hash tables based on NgenHash (see
4416 // vm\NgenHash.h).
4417 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4418 void NativeImageDumper::TraverseNgenHash(DPTR(HASH_CLASS) pTable,
4419                                          const char * name,
4420                                          unsigned offset,
4421                                          unsigned fieldSize,
4422                                          bool saveClasses,
4423                                          void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4424                                          void *pContext)
4425 {
4426     if (pTable == NULL)
4427     {
4428         IF_OPT(MODULE)
4429             m_display->WriteFieldPointer(name, offset, fieldSize, NULL);
4430         return;
4431     }
4432     IF_OPT(MODULE)
4433     {
4434         m_display->StartStructureWithOffset(name, offset, fieldSize,
4435                                             DPtrToPreferredAddr(pTable),
4436                                             sizeof(HASH_CLASS));
4437     }
4438
4439     DisplayWriteFieldPointer(m_pModule,
4440                              DPtrToPreferredAddr(pTable->GetModule()),
4441                              HASH_CLASS, MODULE);
4442
4443     // Dump warm (volatile) entries.
4444     DisplayWriteFieldUInt(m_cWarmEntries, pTable->m_cWarmEntries, HASH_CLASS, MODULE);
4445     DisplayWriteFieldUInt(m_cWarmBuckets, pTable->m_cWarmBuckets, HASH_CLASS, MODULE);
4446     DisplayWriteFieldAddress(m_pWarmBuckets,
4447                              DPtrToPreferredAddr(pTable->GetWarmBuckets()),
4448                              sizeof(HASH_ENTRY_CLASS*) * pTable->m_cWarmBuckets,
4449                              HASH_CLASS, MODULE);
4450
4451     // Dump hot (persisted) entries.
4452     DPTR(typename HASH_CLASS::PersistedEntries) pHotEntries(PTR_HOST_MEMBER_TADDR(HASH_CLASS, pTable, m_sHotEntries));
4453     DisplayStartStructureWithOffset(m_sHotEntries, DPtrToPreferredAddr(pHotEntries),
4454                                     sizeof(typename HASH_CLASS::PersistedEntries),
4455                                     HASH_CLASS, MODULE);
4456     TraverseNgenPersistedEntries<HASH_CLASS, HASH_ENTRY_CLASS>(pTable, pHotEntries, saveClasses, DisplayEntryFunction, pContext);
4457     DisplayEndStructure(MODULE); // Hot entries
4458
4459     // Dump cold (persisted) entries.
4460     DPTR(typename HASH_CLASS::PersistedEntries) pColdEntries(PTR_HOST_MEMBER_TADDR(HASH_CLASS, pTable, m_sColdEntries));
4461     DisplayStartStructureWithOffset(m_sColdEntries, DPtrToPreferredAddr(pColdEntries),
4462                                     sizeof(typename HASH_CLASS::PersistedEntries),
4463                                     HASH_CLASS, MODULE);
4464     TraverseNgenPersistedEntries<HASH_CLASS, HASH_ENTRY_CLASS>(pTable, pColdEntries, saveClasses, DisplayEntryFunction, pContext);
4465     DisplayEndStructure(MODULE); // Cold entries
4466
4467     DisplayEndStructure(MODULE); // pTable
4468 }
4469
4470 // Helper used by TraverseNgenHash above to traverse an ngen persisted section of a table (separated out here
4471 // because NgenHash-based tables can have two such sections, one for hot and one for cold entries).
4472 template<typename HASH_CLASS, typename HASH_ENTRY_CLASS>
4473 void NativeImageDumper::TraverseNgenPersistedEntries(DPTR(HASH_CLASS) pTable,
4474                                                      DPTR(typename HASH_CLASS::PersistedEntries) pEntries,
4475                                                      bool saveClasses,
4476                                                      void (NativeImageDumper::*DisplayEntryFunction)(void *, DPTR(HASH_ENTRY_CLASS), bool),
4477                                                      void *pContext)
4478 {
4479     // Display top-level fields.
4480     DisplayWriteFieldUInt(m_cEntries, pEntries->m_cEntries, typename HASH_CLASS::PersistedEntries, MODULE);
4481     DisplayWriteFieldUInt(m_cBuckets, pEntries->m_cBuckets, typename HASH_CLASS::PersistedEntries, MODULE);
4482     DisplayWriteFieldAddress(m_pBuckets,
4483                              DPtrToPreferredAddr(pTable->GetPersistedBuckets(pEntries)),
4484                              pEntries->m_cBuckets ? pTable->GetPersistedBuckets(pEntries)->GetSize(pEntries->m_cBuckets) : 0,
4485                              typename HASH_CLASS::PersistedEntries, MODULE);
4486     DisplayWriteFieldAddress(m_pEntries,
4487                              DPtrToPreferredAddr(pTable->GetPersistedEntries(pEntries)),
4488                              sizeof(typename HASH_CLASS::PersistedEntry) * pEntries->m_cEntries,
4489                              typename HASH_CLASS::PersistedEntries, MODULE);
4490
4491     // Display entries (or maybe just the classes referenced by those entries).
4492     DisplayStartArray("Entries", NULL, SLIM_MODULE_TBLS);
4493
4494     // Enumerate bucket list.
4495     for (DWORD i = 0; i < pEntries->m_cBuckets; ++i)
4496     {
4497         // Get index of the first entry and the count of entries in the bucket.
4498         DWORD dwEntryId, cEntries;
4499         pTable->GetPersistedBuckets(pEntries)->GetBucket(i, &dwEntryId, &cEntries);
4500
4501         // Loop over entries.
4502         while (cEntries && (CHECK_OPT(SLIM_MODULE_TBLS)
4503                             || CHECK_OPT(EECLASSES)
4504                             || CHECK_OPT(METHODTABLES)))
4505         {
4506             // Lookup entry in the array via the index we have.
4507             typename HASH_CLASS::PTR_PersistedEntry pEntry(PTR_TO_TADDR(pTable->GetPersistedEntries(pEntries)) +
4508                                                         (dwEntryId * sizeof(typename HASH_CLASS::PersistedEntry)));
4509
4510             IF_OPT(SLIM_MODULE_TBLS)
4511             {
4512                 DisplayStartStructure("PersistedEntry",
4513                                       DPtrToPreferredAddr(pEntry),
4514                                       sizeof(typename HASH_CLASS::PersistedEntry), SLIM_MODULE_TBLS);
4515             }
4516
4517             // Display entry via a member function specific to the type of hash table we're traversing. Each
4518             // sub-class of NgenHash hash its own entry structure that is embedded NgenHash's entry. The
4519             // helper function expects a pointer to this inner entry.
4520             DPTR(HASH_ENTRY_CLASS) pInnerEntry(PTR_TO_MEMBER_TADDR(typename HASH_CLASS::PersistedEntry, pEntry, m_sValue));
4521             (this->*DisplayEntryFunction)(pContext, pInnerEntry, saveClasses);
4522
4523             IF_OPT(SLIM_MODULE_TBLS)
4524             {
4525                 DisplayWriteFieldUInt(m_iHashValue, pEntry->m_iHashValue,
4526                                       typename HASH_CLASS::PersistedEntry, SLIM_MODULE_TBLS);
4527
4528                 DisplayEndStructure(SLIM_MODULE_TBLS); // Entry
4529             }
4530
4531             dwEntryId++;
4532             cEntries--;
4533         }
4534     }
4535
4536     DisplayEndArray("Total Entries", SLIM_MODULE_TBLS); // Entry array
4537 }
4538
4539 void NativeImageDumper::TraverseClassHashEntry(void *pContext, PTR_EEClassHashEntry pEntry, bool saveClasses)
4540 {
4541     IF_OPT(SLIM_MODULE_TBLS)
4542     {
4543         DisplayStartStructure("EEClassHashEntry",
4544                               DPtrToPreferredAddr(pEntry),
4545                               sizeof(EEClassHashEntry), SLIM_MODULE_TBLS);
4546     }
4547
4548     size_t datum = size_t(PTR_TO_TADDR(pEntry->GetData()));
4549
4550     if (datum & EECLASSHASH_TYPEHANDLE_DISCR)
4551     {
4552         IF_OPT(SLIM_MODULE_TBLS)
4553         {
4554             /* REVISIT_TODO Tue 10/25/2005
4555              * Raw data with annotation?
4556              */
4557             mdTypeDef tk;
4558             tk = EEClassHashTable::UncompressModuleAndClassDef(pEntry->GetData());
4559             DoWriteFieldMDToken("Token",
4560                                 offsetof(EEClassHashEntry, m_Data),
4561                                 fieldsize(EEClassHashEntry, m_Data),
4562                                 tk);
4563         }
4564     }
4565     else
4566     {
4567         PTR_MethodTable pMT(TO_TADDR(datum));
4568         IF_OPT(SLIM_MODULE_TBLS)
4569         {
4570             DoWriteFieldMethodTable("MethodTable",
4571                                     offsetof(EEClassHashEntry, m_Data),
4572                                     fieldsize(EEClassHashEntry, m_Data),
4573                                     pMT);
4574         }
4575
4576         if (saveClasses)
4577         {
4578             // These are MethodTables.  Get back to the EEClass from there.
4579             if (isInRange(PTR_TO_TADDR(pMT)))
4580                 m_discoveredMTs.AppendEx(pMT);
4581             if (pMT != NULL)
4582             {
4583                 PTR_EEClass pClass = GetClassFromMT(pMT);
4584                 if (isInRange(PTR_TO_TADDR(pClass)))
4585                     m_discoveredClasses.AppendEx(pMT);
4586             }
4587         }
4588     }
4589
4590     IF_OPT(SLIM_MODULE_TBLS)
4591     {
4592         DisplayWriteFieldPointer(m_pEncloser,
4593                                  DPtrToPreferredAddr(pEntry->GetEncloser()),
4594                                  EEClassHashEntry, SLIM_MODULE_TBLS);
4595         DisplayEndStructure(SLIM_MODULE_TBLS);
4596     }
4597 }
4598
4599 void NativeImageDumper::TraverseClassHash(PTR_EEClassHashTable pTable,
4600                                           const char * name,
4601                                           unsigned offset,
4602                                           unsigned fieldSize,
4603                                           bool saveClasses)
4604 {
4605     TraverseNgenHash<EEClassHashTable, EEClassHashEntry>(pTable,
4606                                                          name,
4607                                                          offset,
4608                                                          fieldSize,
4609                                                          saveClasses,
4610                                                          &NativeImageDumper::TraverseClassHashEntry,
4611                                                          NULL);
4612 }
4613
4614 #ifdef FEATURE_COMINTEROP
4615
4616 void NativeImageDumper::TraverseGuidToMethodTableEntry(void *pContext, PTR_GuidToMethodTableEntry pEntry, bool saveClasses)
4617 {
4618     IF_OPT(SLIM_MODULE_TBLS)
4619     {
4620         DisplayStartStructure("GuidToMethodTableEntry",
4621                               DPtrToPreferredAddr(pEntry),
4622                               sizeof(GuidToMethodTableEntry), SLIM_MODULE_TBLS);
4623     }
4624
4625     WriteFieldMethodTable(m_pMT, pEntry->m_pMT, GuidToMethodTableEntry, ALWAYS);
4626     
4627     TempBuffer buf;
4628     GuidToString( *(pEntry->m_Guid), buf );
4629     DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidToMethodTableEntry, ALWAYS );
4630
4631     DisplayEndStructure( SLIM_MODULE_TBLS );
4632 }
4633
4634 void NativeImageDumper::TraverseGuidToMethodTableHash(PTR_GuidToMethodTableHashTable pTable, 
4635                         const char * name,
4636                         unsigned offset,
4637                         unsigned fieldSize,
4638                         bool saveClasses)
4639 {
4640     TraverseNgenHash<GuidToMethodTableHashTable, GuidToMethodTableEntry>(pTable,
4641                         name,
4642                         offset,
4643                         fieldSize,
4644                         saveClasses,
4645                         &NativeImageDumper::TraverseGuidToMethodTableEntry,
4646                         NULL);
4647 }
4648
4649 #endif // FEATURE_COMINTEROP
4650
4651 void NativeImageDumper::TraverseMemberRefToDescHashEntry(void *pContext, PTR_MemberRefToDescHashEntry pEntry, bool saveClasses)
4652 {
4653     IF_OPT(SLIM_MODULE_TBLS)
4654     {
4655         DisplayStartStructure("MemberRefToDescHashEntry",
4656                               DPtrToPreferredAddr(pEntry),
4657                               sizeof(MemberRefToDescHashEntry), SLIM_MODULE_TBLS);
4658     }
4659
4660     if(pEntry->m_value & IS_FIELD_MEMBER_REF)
4661         WriteFieldFieldDesc(m_value, dac_cast<PTR_FieldDesc>(pEntry->m_value & (~MEMBER_REF_MAP_ALL_FLAGS)), MemberRefToDescHashEntry, MODULE_TABLES);
4662     else
4663         WriteFieldMethodDesc(m_value, dac_cast<PTR_MethodDesc>(pEntry->m_value), MemberRefToDescHashEntry, MODULE_TABLES);
4664     
4665     DisplayEndStructure( SLIM_MODULE_TBLS );
4666 }
4667
4668 void NativeImageDumper::TraverseMemberRefToDescHash(PTR_MemberRefToDescHashTable pTable, 
4669                         const char * name,
4670                         unsigned offset,
4671                         unsigned fieldSize,
4672                         bool saveClasses)
4673 {
4674     TraverseNgenHash<MemberRefToDescHashTable, MemberRefToDescHashEntry>(pTable,
4675                         name,
4676                         offset,
4677                         fieldSize,
4678                         saveClasses,
4679                         &NativeImageDumper::TraverseMemberRefToDescHashEntry,
4680                         NULL);
4681 }
4682
4683
4684 void NativeImageDumper::TraverseTypeHashEntry(void *pContext, PTR_EETypeHashEntry pEntry, bool saveClasses)
4685 {
4686     TypeHandle th = pEntry->GetTypeHandle();
4687     IF_OPT(SLIM_MODULE_TBLS)
4688     {
4689         DisplayStartStructure("EETypeHashEntry",
4690                               DPtrToPreferredAddr(pEntry),
4691                               sizeof(EETypeHashEntry), SLIM_MODULE_TBLS);
4692
4693         DoWriteFieldTypeHandle("TypeHandle",
4694                                offsetof(EETypeHashEntry, m_data),
4695                                fieldsize(EETypeHashEntry, m_data),
4696                                th);
4697     }
4698             
4699     if (!CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc())
4700     {
4701         PTR_TypeDesc td(th.AsTypeDesc());
4702         if (isInRange(PTR_TO_TADDR(td)))
4703             m_discoveredTypeDescs.AppendEx(td);
4704         if (td->HasTypeParam())
4705         {
4706             PTR_ParamTypeDesc ptd(td);
4707
4708             /* REVISIT_TODO Thu 12/15/2005
4709              * Check OwnsTemplateMethodTable.  However, this asserts in
4710              * this special completely unrestored and messed up state
4711              * (also, it chases through MT->GetClass()).  There isn't
4712              * all that much harm here (bloats m_discoveredMTs though,
4713              * but not by a huge amount.
4714              */
4715             PTR_MethodTable mt(ptd->GetTemplateMethodTableInternal());
4716             if (isInRange(PTR_TO_TADDR(mt)))
4717             {
4718                 m_discoveredMTs.AppendEx(mt);
4719                 if (mt->IsClassPointerValid())
4720                 {
4721                     PTR_EEClass pClass = mt->GetClass();
4722                     if (isInRange(PTR_TO_TADDR(pClass)))
4723                         m_discoveredClasses.AppendEx(mt);
4724                 }
4725             }
4726         }
4727     }
4728     else
4729     {
4730         PTR_MethodTable mt(th.AsTAddr());
4731
4732         if (isInRange( PTR_TO_TADDR(mt)))
4733             m_discoveredMTs.AppendEx(mt);
4734         //don't use GetClassFromMT here.  mt->m_pEEClass might be a
4735         //fixup.  In that case, just skip it.
4736         if (mt->IsClassPointerValid())
4737         {
4738             PTR_EEClass pClass = mt->GetClass();
4739             if (isInRange(PTR_TO_TADDR(pClass)))
4740                 m_discoveredClasses.AppendEx(mt);
4741         }
4742     }
4743
4744     IF_OPT(SLIM_MODULE_TBLS)
4745     {
4746         DisplayEndStructure(SLIM_MODULE_TBLS);
4747     }
4748 }
4749
4750 void NativeImageDumper::TraverseTypeHash(PTR_EETypeHashTable pTable,
4751                                          const char * name,
4752                                          unsigned offset,
4753                                          unsigned fieldSize)
4754 {
4755     TraverseNgenHash<EETypeHashTable, EETypeHashEntry>(pTable,
4756                                                        name,
4757                                                        offset,
4758                                                        fieldSize,
4759                                                        true,
4760                                                        &NativeImageDumper::TraverseTypeHashEntry,
4761                                                        NULL);
4762 }
4763
4764 void NativeImageDumper::TraverseInstMethodHashEntry(void *pContext, PTR_InstMethodHashEntry pEntry, bool saveClasses)
4765 {
4766     PTR_Module pModule((TADDR)pContext);
4767
4768     IF_OPT(SLIM_MODULE_TBLS)
4769     {
4770         DisplayStartStructure("InstMethodHashEntry",
4771                               DPtrToPreferredAddr(pEntry),
4772                               sizeof(InstMethodHashEntry), SLIM_MODULE_TBLS);
4773     }
4774
4775     IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4776     {
4777         IF_OPT(METHODDESCS)
4778         {
4779             PTR_MethodDesc md = pEntry->GetMethod();
4780             _ASSERTE(md != NULL);
4781
4782             //if we want methoddescs, write the data field as a
4783             //structure with the whole contents of the method desc.
4784             m_display->StartVStructureWithOffset("data", offsetof(InstMethodHashEntry, data),
4785                                                   sizeof(pEntry->data));
4786             DumpMethodDesc(md, pModule);
4787             DisplayEndVStructure(ALWAYS); //data
4788         }
4789         else
4790         {
4791             PTR_MethodDesc md = pEntry->GetMethod();
4792             WriteFieldMethodDesc(data, md,
4793                                  InstMethodHashEntry, ALWAYS);
4794         }
4795     }
4796     else
4797         CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4798
4799     IF_OPT(SLIM_MODULE_TBLS)
4800     {
4801         DisplayEndStructure(SLIM_MODULE_TBLS);
4802     }
4803 }
4804
4805 void NativeImageDumper::TraverseStubMethodHashEntry(void *pContext, PTR_StubMethodHashEntry pEntry, bool saveClasses)
4806 {
4807     PTR_Module pModule((TADDR)pContext);
4808
4809     IF_OPT(SLIM_MODULE_TBLS)
4810     {
4811         DisplayStartStructure("StubMethodHashEntry",
4812                               DPtrToPreferredAddr(pEntry),
4813                               sizeof(StubMethodHashEntry), SLIM_MODULE_TBLS);
4814     }
4815
4816     IF_OPT_OR(SLIM_MODULE_TBLS, METHODDESCS)
4817     {
4818         PTR_MethodDesc md = pEntry->GetMethod();
4819         _ASSERTE(md != NULL);
4820
4821         PTR_MethodDesc stub = pEntry->GetStubMethod();
4822         _ASSERTE(stub != NULL);
4823
4824         IF_OPT(METHODDESCS)
4825         {
4826             //if we want methoddescs, write the data fields as a
4827             //structure with the whole contents of the method desc.
4828             m_display->StartVStructureWithOffset("pMD", offsetof(StubMethodHashEntry, pMD),
4829                                                   sizeof(pEntry->pMD));
4830             DumpMethodDesc(md, pModule);
4831             DisplayEndVStructure(ALWAYS); //pMD
4832
4833             m_display->StartVStructureWithOffset("pStubMD", offsetof(StubMethodHashEntry, pStubMD),
4834                                                   sizeof(pEntry->pStubMD));
4835             DumpMethodDesc(stub, pModule);
4836             DisplayEndVStructure(ALWAYS); //pStubMD
4837         }
4838         else
4839         {
4840             WriteFieldMethodDesc(pMD, md,
4841                                  StubMethodHashEntry, ALWAYS);
4842             WriteFieldMethodDesc(pStubMD, stub,
4843                                  StubMethodHashEntry, ALWAYS);
4844         }
4845     }
4846     else
4847         CoverageRead(PTR_TO_TADDR(pEntry), sizeof(*pEntry));
4848
4849     IF_OPT(SLIM_MODULE_TBLS)
4850     {
4851         DisplayEndStructure(SLIM_MODULE_TBLS);
4852     }
4853 }
4854
4855 void NativeImageDumper::TraverseInstMethodHash(PTR_InstMethodHashTable pTable,
4856                                                const char * name,
4857                                                unsigned fieldOffset,
4858                                                unsigned fieldSize,
4859                                                PTR_Module module)
4860 {
4861     TraverseNgenHash<InstMethodHashTable, InstMethodHashEntry>(pTable,
4862                                                                name,
4863                                                                fieldOffset,
4864                                                                fieldSize,
4865                                                                true,
4866                                                                &NativeImageDumper::TraverseInstMethodHashEntry,
4867                                                                (void*)dac_cast<TADDR>(module));
4868 }
4869
4870 void NativeImageDumper::TraverseStubMethodHash(PTR_StubMethodHashTable pTable,
4871                                                const char * name,
4872                                                unsigned fieldOffset,
4873                                                unsigned fieldSize,
4874                                                PTR_Module module)
4875 {
4876     TraverseNgenHash<StubMethodHashTable, StubMethodHashEntry>(pTable,
4877                                                                name,
4878                                                                fieldOffset,
4879                                                                fieldSize,
4880                                                                true,
4881                                                                &NativeImageDumper::TraverseStubMethodHashEntry,
4882                                                                (void*)dac_cast<TADDR>(module));
4883 }
4884
4885 const NativeImageDumper::Dependency *
4886 NativeImageDumper::GetDependencyForModule( PTR_Module module )
4887 {
4888     for( COUNT_T i = 0; i < m_numDependencies; ++i )
4889     {
4890         if( m_dependencies[i].pModule == module )
4891             return &m_dependencies[i];
4892     }
4893     return NULL;
4894 }
4895
4896 #if 0
4897 const NativeImageDumper::Import *
4898 NativeImageDumper::GetImportForPointer( TADDR ptr )
4899 {
4900     for( int i = 0; i < m_numImports; ++i )
4901     {
4902         const Import * import = &m_imports[i];
4903         if( import->dependency->pPreferredBase == NULL )
4904             continue;
4905         if( import->dependency->pPreferredBase <= ptr
4906             && ((import->dependency->pPreferredBase
4907                  + import->dependency->size) > ptr) )
4908         {
4909             //found the right target
4910             return import;
4911         }
4912     }
4913     return NULL;
4914 }
4915 #endif
4916 const NativeImageDumper::Dependency *
4917 NativeImageDumper::GetDependencyForPointer( TADDR ptr )
4918 {
4919     for( COUNT_T i = 0; i < m_numDependencies; ++i )
4920     {
4921         const Dependency * dependency = &m_dependencies[i];
4922         if( dependency->pLoadedAddress == NULL )
4923             continue;
4924         if( dependency->pLoadedAddress <= ptr
4925             && ((dependency->pLoadedAddress + dependency->size) > ptr) )
4926         {
4927             //found the right target
4928             return dependency;
4929         }
4930     }
4931     return NULL;
4932 }
4933
4934 void NativeImageDumper::DictionaryToArgString( PTR_Dictionary dictionary, unsigned numArgs, SString& buf )
4935 {
4936     //this can be called with numArgs == 0 for value type instantiations.
4937     buf.Append( W("<") );
4938
4939     for( unsigned i = 0; i < numArgs; ++i )
4940     {
4941         if( i > 0 )
4942             buf.Append( W(",") );
4943
4944         TypeHandle th = dictionary->GetInstantiation()[i].GetValue();
4945         if( CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) )
4946         {
4947             if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(dictionary))))
4948             {
4949                 //this is an RVA from another hardbound dependency.  We cannot decode it
4950                 buf.Append(W("OUT_OF_MODULE_FIXUP"));
4951             }
4952             else
4953             {
4954                 RVA rva = CORCOMPILE_UNTAG_TOKEN(th.AsTAddr());
4955                 FixupBlobToString(rva, buf);
4956             }
4957         }
4958         else
4959         {
4960             TypeHandleToString( th, buf );
4961         }
4962     }
4963     buf.Append( W(">") );
4964 }
4965
4966 void NativeImageDumper::MethodTableToString( PTR_MethodTable mt, SString& buf )
4967 {
4968     bool hasCompleteExtents = true;
4969     IF_OPT(DISABLE_NAMES)
4970     {
4971         buf.Append( W("Disabled") );
4972         return;
4973     }
4974     mdToken token = mdTokenNil;
4975     if( mt == NULL )
4976         buf.Append( W("mdTypeDefNil") );
4977     else
4978     {
4979         _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)));
4980         const Dependency * dependency; 
4981         if( !mt->IsClassPointerValid() )
4982         {
4983             if( isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))) )
4984             {
4985
4986                 hasCompleteExtents = false;
4987                 RVA rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
4988                 PTR_CCOR_SIGNATURE sig = (TADDR) m_decoder.GetRvaData(rva);
4989
4990                 BYTE kind = *sig++;
4991
4992                 if (kind & ENCODE_MODULE_OVERRIDE)
4993                 {
4994                     /* int moduleIndex = */ DacSigUncompressData(sig);
4995                     kind &= ~ENCODE_MODULE_OVERRIDE;
4996                 }
4997
4998                 _ASSERTE(kind == ENCODE_TYPE_HANDLE);
4999                 CorElementType et = DacSigUncompressElementType(sig);
5000                 if( et == ELEMENT_TYPE_GENERICINST )
5001                 {
5002                     //generic instances have another element type
5003                     et = DacSigUncompressElementType(sig);
5004                 }
5005                 if (et == ELEMENT_TYPE_VALUETYPE || et == ELEMENT_TYPE_CLASS)
5006                 {
5007                     token = DacSigUncompressToken(sig);
5008                 }
5009                 else
5010                 {
5011                     // Arrays, etc.
5012                     token = mdtTypeDef;
5013                 }
5014                 dependency = GetDependencyForFixup(rva);
5015             }
5016             else
5017             {
5018                 //this is an RVA from another hardbound dependency.  We cannot decode it
5019                 buf.Append(W("OUT_OF_MODULE_FIXUP"));
5020                 return;
5021             }
5022         }
5023         else
5024         {
5025             token = mt->GetCl();
5026             dependency = GetDependencyFromMT(mt);
5027         }
5028
5029         if( !isSelf(dependency) )
5030         {
5031             AppendTokenName( dependency->entry->dwAssemblyRef, buf,
5032                              m_manifestImport );
5033             buf.Append(W("!"));
5034         }
5035
5036         _ASSERTE(dependency->pImport);
5037         if( token == mdtTypeDef )
5038             buf.Append( W("No Token") );
5039         else
5040             AppendTokenName( token, buf, dependency->pImport );
5041
5042         if( mt->HasPerInstInfo() )
5043         {
5044             unsigned numDicts;
5045             if( hasCompleteExtents )
5046             {
5047                 numDicts = mt->GetNumDicts();
5048                 _ASSERTE(numDicts == CountDictionariesInClass(token, dependency->pImport));
5049             }
5050             else
5051             {
5052                 numDicts = (DWORD)CountDictionariesInClass(token, dependency->pImport);
5053             }
5054
5055             TADDR base = dac_cast<TADDR>(&(mt->GetPerInstInfo()[numDicts-1]));
5056
5057             PTR_Dictionary dictionary( MethodTable::PerInstInfoElem_t::GetValueAtPtr(base) );
5058             unsigned numArgs = mt->GetNumGenericArgs();
5059
5060             DictionaryToArgString( dictionary, numArgs, buf );
5061         }
5062     }
5063 }
5064
5065 mdToken NativeImageDumper::ConvertToTypeDef( mdToken typeToken, IMetaDataImport2* (&pImport) )
5066 {
5067     _ASSERTE( (TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5068               || (TypeFromToken(typeToken) == mdtTypeSpec) );
5069     if( mdtTypeDef == TypeFromToken(typeToken) )
5070         return typeToken;
5071     if( mdtTypeRef == TypeFromToken(typeToken) )
5072     {
5073         //convert the ref to a def.
5074         mdToken scope;
5075         WCHAR trName[MAX_CLASS_NAME];
5076         ULONG trNameLen;
5077         IfFailThrow(pImport->GetTypeRefProps(typeToken, &scope, trName, _countof(trName), &trNameLen));
5078         _ASSERTE(trName[trNameLen-1] == 0);
5079
5080         //scope is now a moduleRef or assemblyRef.  Find the IMetaData import for that Ref
5081         /* REVISIT_TODO Fri 10/6/2006
5082          * How do I handle moduleRefs?
5083          */
5084         _ASSERTE(TypeFromToken(scope) == mdtAssemblyRef);
5085         ReleaseHolder<IMetaDataAssemblyImport> pAssemblyImport;
5086         IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
5087                                             (void **)&pAssemblyImport));
5088         NativeImageDumper::Dependency * dep = GetDependency(scope, pAssemblyImport);
5089
5090         pImport = dep->pImport;
5091
5092         /* REVISIT_TODO Fri 10/6/2006
5093          * Does this work for inner types?
5094          */
5095         //now I have the correct MetaData.  Find the typeDef
5096         HRESULT hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5097         while (hr == CLDB_E_RECORD_NOTFOUND)
5098         {
5099             // No matching TypeDef, try ExportedType
5100             pAssemblyImport = NULL;
5101             IfFailThrow(pImport->QueryInterface(IID_IMetaDataAssemblyImport,
5102                                                 (void **)&pAssemblyImport));
5103             mdExportedType tkExportedType = mdExportedTypeNil;
5104             IfFailThrow(pAssemblyImport->FindExportedTypeByName(trName, mdExportedTypeNil, &tkExportedType));
5105             mdToken tkImplementation;
5106             IfFailThrow(pAssemblyImport->GetExportedTypeProps(tkExportedType, NULL, 0, NULL, &tkImplementation, NULL, NULL));
5107             dep = GetDependency(tkImplementation, pAssemblyImport);
5108
5109             pImport = dep->pImport;
5110             hr = pImport->FindTypeDefByName(trName, mdTypeDefNil, &typeToken);
5111         }
5112         IfFailThrow(hr);
5113     }
5114     else
5115     {
5116         PCCOR_SIGNATURE pSig;
5117         ULONG cbSig;
5118         IfFailThrow(pImport->GetTypeSpecFromToken(typeToken, &pSig, &cbSig));
5119         //GENERICINST (CLASS|VALUETYPE) typeDefOrRef
5120         CorElementType et = CorSigUncompressElementType(pSig);
5121         _ASSERTE(et == ELEMENT_TYPE_GENERICINST);
5122         et = CorSigUncompressElementType(pSig);
5123         _ASSERTE((et == ELEMENT_TYPE_CLASS) || (et == ELEMENT_TYPE_VALUETYPE));
5124         typeToken = CorSigUncompressToken(pSig);
5125     }
5126
5127     //we just removed one level of indirection.  We still might have a ref or spec.
5128     typeToken = ConvertToTypeDef(typeToken, pImport);
5129     _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5130     return typeToken;
5131 }
5132
5133 SIZE_T NativeImageDumper::CountDictionariesInClass( mdToken typeToken, IMetaDataImport2 * pImport )
5134 {
5135     SIZE_T myDicts; //either 0 or 1
5136
5137     _ASSERTE((TypeFromToken(typeToken) == mdtTypeDef) || (TypeFromToken(typeToken) == mdtTypeRef)
5138              || (TypeFromToken(typeToken) == mdtTypeSpec));
5139
5140
5141     //for refs and specs, convert to a def.  This is a nop for defs.
5142     typeToken = ConvertToTypeDef(typeToken, pImport);
5143
5144     _ASSERTE(TypeFromToken(typeToken) == mdtTypeDef);
5145
5146
5147     //count the number of generic arguments.  If there are any, then we have a dictionary.
5148     HCORENUM hEnum = NULL;
5149     mdGenericParam params[2];
5150     ULONG numParams = 0;
5151     IfFailThrow(pImport->EnumGenericParams(&hEnum, typeToken, params, _countof(params), &numParams));
5152     myDicts = (numParams > 0) ? 1 : 0;
5153
5154     pImport->CloseEnum(hEnum);
5155
5156     //get my parent for the recursive call.
5157     mdToken parent;
5158     IfFailThrow(pImport->GetTypeDefProps(typeToken, NULL, 0, NULL, NULL, &parent));
5159     return myDicts + (IsNilToken(parent) ? 0 : CountDictionariesInClass(parent, pImport));
5160 }
5161
5162 const NativeImageDumper::EnumMnemonics s_Subsystems[] =
5163 {
5164 #define S_ENTRY(f,v) NativeImageDumper::EnumMnemonics(f, 0, v)
5165     S_ENTRY(IMAGE_SUBSYSTEM_UNKNOWN, W("Unknown")),
5166     S_ENTRY(IMAGE_SUBSYSTEM_NATIVE, W("Native")),
5167     S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CUI, W("Windows CUI")),
5168     S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_GUI, W("Windows GUI")),
5169     S_ENTRY(IMAGE_SUBSYSTEM_OS2_CUI, W("OS/2 CUI")),
5170     S_ENTRY(IMAGE_SUBSYSTEM_POSIX_CUI, W("POSIX CUI")),
5171     S_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, W("WinCE GUI")),
5172     S_ENTRY(IMAGE_SUBSYSTEM_XBOX, W("XBox"))
5173 #undef S_ENTRY
5174 };
5175
5176 const NativeImageDumper::EnumMnemonics s_CorCompileHdrFlags[] = 
5177 {
5178 #define CCHF_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5179     CCHF_ENTRY(CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY),
5180     CCHF_ENTRY(CORCOMPILE_HEADER_IS_IBC_OPTIMIZED),
5181     CCHF_ENTRY(CORCOMPILE_HEADER_IS_READY_TO_RUN),
5182 #undef CCHF_ENTRY
5183 };
5184
5185 const NativeImageDumper::EnumMnemonics s_CorPEKind[] =
5186 {
5187 #define CPEK_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5188     CPEK_ENTRY(peNot),
5189     CPEK_ENTRY(peILonly),
5190     CPEK_ENTRY(pe32BitRequired),
5191     CPEK_ENTRY(pe32Plus),
5192     CPEK_ENTRY(pe32Unmanaged),
5193     CPEK_ENTRY(pe32BitPreferred)
5194 #undef CPEK_ENTRY
5195 };
5196 const NativeImageDumper::EnumMnemonics s_IFH_Machine[] =
5197 {
5198 #define IFH_ENTRY(f) NativeImageDumper::EnumMnemonics(f, 0, W(#f))
5199     IFH_ENTRY(IMAGE_FILE_MACHINE_UNKNOWN),
5200     IFH_ENTRY(IMAGE_FILE_MACHINE_I386),
5201     IFH_ENTRY(IMAGE_FILE_MACHINE_AMD64),
5202     IFH_ENTRY(IMAGE_FILE_MACHINE_ARMNT),
5203 #undef IFH_ENTRY
5204 };
5205
5206 const NativeImageDumper::EnumMnemonics s_IFH_Characteristics[] =
5207 {
5208 #define IFH_ENTRY(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5209     IFH_ENTRY(IMAGE_FILE_RELOCS_STRIPPED),
5210     IFH_ENTRY(IMAGE_FILE_EXECUTABLE_IMAGE),
5211     IFH_ENTRY(IMAGE_FILE_LINE_NUMS_STRIPPED),
5212     IFH_ENTRY(IMAGE_FILE_LOCAL_SYMS_STRIPPED),
5213     IFH_ENTRY(IMAGE_FILE_AGGRESIVE_WS_TRIM),
5214     IFH_ENTRY(IMAGE_FILE_LARGE_ADDRESS_AWARE),
5215     IFH_ENTRY(IMAGE_FILE_BYTES_REVERSED_LO),
5216     IFH_ENTRY(IMAGE_FILE_32BIT_MACHINE),
5217     IFH_ENTRY(IMAGE_FILE_DEBUG_STRIPPED),
5218     IFH_ENTRY(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
5219     IFH_ENTRY(IMAGE_FILE_NET_RUN_FROM_SWAP),
5220     IFH_ENTRY(IMAGE_FILE_SYSTEM),
5221     IFH_ENTRY(IMAGE_FILE_DLL),
5222     IFH_ENTRY(IMAGE_FILE_UP_SYSTEM_ONLY),
5223     IFH_ENTRY(IMAGE_FILE_BYTES_REVERSED_HI),
5224 #undef IFH_ENTRY
5225 };
5226
5227 const NativeImageDumper::EnumMnemonics s_ImportSectionType[] = 
5228 {
5229 #define IST_ENTRY(f) NativeImageDumper::EnumMnemonics(f, 0, W(#f))
5230     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_UNKNOWN),
5231     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD),
5232     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH),
5233     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_STRING_HANDLE),
5234     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE),
5235     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE),
5236     IST_ENTRY(CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD),
5237 #undef IST_ENTRY
5238 };
5239
5240 const NativeImageDumper::EnumMnemonics s_ImportSectionFlags[] = 
5241 {
5242 #define IST_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
5243     IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_EAGER),
5244     IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_CODE),
5245     IST_FLAGS(CORCOMPILE_IMPORT_FLAGS_PCODE),
5246 #undef IST_FLAGS
5247 };
5248
5249 void NativeImageDumper::DumpNativeHeader()
5250 {
5251     PTR_CORCOMPILE_HEADER nativeHeader(m_decoder.GetNativeHeader());
5252
5253     IF_OPT(NATIVE_INFO)
5254     {
5255
5256 #define WRITE_NATIVE_FIELD( name ) m_display->WriteFieldAddress(\
5257     # name, offsetof(CORCOMPILE_HEADER, name), \
5258     fieldsize(CORCOMPILE_HEADER, name), \
5259     RvaToDisplay( nativeHeader-> name . VirtualAddress ), \
5260     nativeHeader-> name . Size  )
5261
5262         m_display->StartStructure( "CORCOMPILE_HEADER",
5263                                    DPtrToPreferredAddr(nativeHeader),
5264                                    sizeof(*nativeHeader) );
5265
5266         DisplayWriteFieldUInt( Signature, nativeHeader->Signature, CORCOMPILE_HEADER, ALWAYS );
5267         DisplayWriteFieldUInt( MajorVersion, nativeHeader->MajorVersion, CORCOMPILE_HEADER, ALWAYS );
5268         DisplayWriteFieldUInt( MinorVersion, nativeHeader->MinorVersion, CORCOMPILE_HEADER, ALWAYS );
5269
5270         WRITE_NATIVE_FIELD(HelperTable);
5271
5272         WRITE_NATIVE_FIELD(ImportSections);
5273         PTR_CORCOMPILE_IMPORT_SECTION pImportSections =
5274             nativeHeader->ImportSections.VirtualAddress
5275             + PTR_TO_TADDR(m_decoder.GetBase());
5276         DisplayStartArray( "ImportSections", NULL, ALWAYS );
5277         for( COUNT_T i = 0; i < nativeHeader->ImportSections.Size
5278              / sizeof(*pImportSections); ++i )
5279         {
5280             DisplayStartStructure( "CORCOMPILE_IMPORT_SECTION",
5281                                    DPtrToPreferredAddr(pImportSections + i),
5282                                    sizeof(pImportSections[i]), ALWAYS );
5283             DisplayWriteElementAddress( "Section",
5284                                         RvaToDisplay(pImportSections[i].Section.VirtualAddress),
5285                                         pImportSections[i].Section.Size, ALWAYS );
5286
5287             DisplayWriteFieldEnumerated( Flags, pImportSections[i].Flags,
5288                                          CORCOMPILE_IMPORT_SECTION, s_ImportSectionFlags, W(", "), ALWAYS );
5289             DisplayWriteFieldEnumerated( Type, pImportSections[i].Type,
5290                                          CORCOMPILE_IMPORT_SECTION, s_ImportSectionType, W(""), ALWAYS );
5291             
5292             DisplayWriteFieldUInt( EntrySize, pImportSections[i].EntrySize,
5293                                    CORCOMPILE_IMPORT_SECTION, ALWAYS );
5294             DisplayWriteFieldUInt( Signatures, pImportSections[i].Signatures,
5295                                    CORCOMPILE_IMPORT_SECTION, ALWAYS );
5296             DisplayWriteFieldUInt( AuxiliaryData, pImportSections[i].AuxiliaryData,
5297                                     CORCOMPILE_IMPORT_SECTION, ALWAYS );
5298             DisplayEndStructure( ALWAYS ); //PTR_CORCOMPILE_IMPORT_SECTION
5299
5300         }
5301         DisplayEndArray( NULL, ALWAYS ); //delayLoads
5302
5303         WRITE_NATIVE_FIELD(VersionInfo);
5304         WRITE_NATIVE_FIELD(DebugMap);
5305         WRITE_NATIVE_FIELD(ModuleImage);
5306         WRITE_NATIVE_FIELD(CodeManagerTable);
5307         WRITE_NATIVE_FIELD(ProfileDataList);
5308         WRITE_NATIVE_FIELD(ManifestMetaData);
5309
5310         WRITE_NATIVE_FIELD(VirtualSectionsTable);
5311         DisplayStartArray( "VirtualSections", W("%-48s%s"), SLIM_MODULE_TBLS );
5312         PTR_CORCOMPILE_VIRTUAL_SECTION_INFO sects( nativeHeader->VirtualSectionsTable.VirtualAddress + PTR_TO_TADDR(m_decoder.GetBase()) );
5313         COUNT_T numVirtualSections = nativeHeader->VirtualSectionsTable.Size / sizeof (CORCOMPILE_VIRTUAL_SECTION_INFO);
5314         
5315         for( COUNT_T i = 0; i < numVirtualSections; ++i )
5316         {
5317             TempBuffer sectionNameBuf;
5318             TempBuffer sectionFlags;
5319             StackScratchBuffer scratch;
5320
5321             sectionNameBuf.Append(g_sectionNames[VirtualSectionData::VirtualSectionType(sects[i].SectionType)]);
5322
5323             EnumFlagsToString( sects[i].SectionType, s_virtualSectionFlags, dim(s_virtualSectionFlags),
5324                        W(" | "), sectionFlags);
5325
5326             sectionNameBuf.Append(W(" ["));
5327             sectionNameBuf.Append(sectionFlags);
5328             sectionNameBuf.Append(W("]"));
5329
5330             DisplayStartElement( "Section", SLIM_MODULE_TBLS );
5331             DisplayWriteElementString("Name", sectionNameBuf.GetANSI(scratch), SLIM_MODULE_TBLS);
5332
5333             DisplayWriteElementAddress( "Address",
5334                                         RvaToDisplay(sects[i].VirtualAddress),
5335                                         sects[i].Size,
5336                                         SLIM_MODULE_TBLS );
5337             DisplayEndElement( SLIM_MODULE_TBLS ); //Section
5338         }
5339         DisplayEndArray( "Total VirtualSections", SLIM_MODULE_TBLS );
5340
5341         WRITE_NATIVE_FIELD(EEInfoTable);
5342
5343 #undef WRITE_NATIVE_FIELD
5344         DisplayWriteFieldEnumerated( Flags, nativeHeader->Flags,
5345                                      CORCOMPILE_HEADER, s_CorCompileHdrFlags, W(", "),
5346                                      NATIVE_INFO );
5347
5348         DisplayWriteFieldEnumerated( PEKind, nativeHeader->PEKind,
5349                                      CORCOMPILE_HEADER, s_CorPEKind, W(", "),
5350                                      NATIVE_INFO );
5351
5352         DisplayWriteFieldEnumerated( COR20Flags, nativeHeader->COR20Flags,
5353                                      CORCOMPILE_HEADER, s_CorHdrFlags, W(", "),
5354                                      NATIVE_INFO );
5355
5356         DisplayWriteFieldEnumerated( Machine, nativeHeader->Machine,
5357                                      CORCOMPILE_HEADER, s_IFH_Machine,
5358                                      W(""), NATIVE_INFO );
5359         DisplayWriteFieldEnumerated( Characteristics,
5360                                      nativeHeader->Characteristics,
5361                                      CORCOMPILE_HEADER, s_IFH_Characteristics,
5362                                      W(", "), NATIVE_INFO );
5363
5364         m_display->EndStructure(); //CORCOMPILE_HEADER
5365     }
5366 }
5367
5368 const NativeImageDumper::EnumMnemonics s_RelocType[] =
5369 {
5370 #define REL_ENTRY(x) NativeImageDumper::EnumMnemonics( x, 0, W(#x))
5371     REL_ENTRY(IMAGE_REL_BASED_ABSOLUTE),
5372     REL_ENTRY(IMAGE_REL_BASED_HIGHLOW),
5373     REL_ENTRY(IMAGE_REL_BASED_DIR64),
5374     REL_ENTRY(IMAGE_REL_BASED_THUMB_MOV32),
5375 #undef REL_ENTRY
5376 };
5377
5378 void NativeImageDumper::DumpBaseRelocs()
5379 {
5380     COUNT_T size;
5381     TADDR data;
5382
5383     data = m_decoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_BASERELOC, &size);
5384
5385     if (size != 0)
5386     {
5387         DisplayStartStructure( "Relocations", DataPtrToDisplay(data), size,
5388                                     ALWAYS );
5389
5390         while (size != 0)
5391         {
5392             IMAGE_BASE_RELOCATION * pBaseRelocation = dac_cast<DPTR(IMAGE_BASE_RELOCATION)>(data);
5393             _ASSERTE(size >= pBaseRelocation->SizeOfBlock);
5394             
5395             SIZE_T rel = sizeof(IMAGE_BASE_RELOCATION);
5396             while (rel < pBaseRelocation->SizeOfBlock)
5397             {
5398                 USHORT typeOffset = *PTR_USHORT(data + rel);
5399
5400                 DisplayStartElement( "Entry", ALWAYS );
5401
5402                 DisplayWriteElementPointer( "Address", RvaToDisplay(pBaseRelocation->VirtualAddress + (typeOffset & 0xFFF)), ALWAYS );
5403
5404                 DisplayWriteElementEnumerated( "Type", (typeOffset >> 12),
5405                                         s_RelocType, W(", "), ALWAYS );
5406
5407                 DisplayEndElement( ALWAYS ); //Entry
5408
5409                 rel += sizeof(USHORT);
5410             }
5411
5412             data += pBaseRelocation->SizeOfBlock;
5413             size -= pBaseRelocation->SizeOfBlock;
5414         }
5415
5416         DisplayEndStructure( ALWAYS ); //Relocations
5417     }
5418 }
5419
5420 void NativeImageDumper::DumpHelperTable()
5421 {
5422     COUNT_T size;
5423     TADDR data;
5424
5425     data = TO_TADDR(m_decoder.GetNativeHelperTable(&size));
5426     if( size != 0 )
5427     {
5428         DisplayStartStructure( "HelperTable", DataPtrToDisplay(data), size,
5429                                     ALWAYS );
5430
5431         TADDR curEntry   = data;
5432         TADDR tableEnd   = data + size;
5433
5434         while (curEntry < tableEnd)
5435         {
5436             DWORD dwHelper = *PTR_DWORD(curEntry);
5437
5438             int iHelper = (USHORT)dwHelper;
5439             _ASSERTE(iHelper < CORINFO_HELP_COUNT);
5440
5441             DisplayStartStructure( "Helper",
5442                                    DataPtrToDisplay(curEntry), (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN,
5443                                    ALWAYS );
5444
5445             DisplayWriteElementUInt( "dwHelper", dwHelper, ALWAYS );
5446             DisplayWriteElementString( "Name", g_helperNames[iHelper], ALWAYS );
5447
5448             DisplayEndStructure( ALWAYS ); //Helper
5449
5450             curEntry += (dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN;
5451         }
5452
5453         DisplayEndStructure( ALWAYS ); //HelperTable
5454     }
5455 }
5456
5457 // TODO: fix these to work with the updated flags in MethodTable, AND to understand
5458 //       the new overloading of component size...
5459
5460 NativeImageDumper::EnumMnemonics s_MTFlagsLow[] =
5461 {
5462 #define MTFLAG_ENTRY(x) \
5463     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5464
5465     MTFLAG_ENTRY(UNUSED_ComponentSize_1),
5466     MTFLAG_ENTRY(StaticsMask),
5467     MTFLAG_ENTRY(StaticsMask_NonDynamic),
5468     MTFLAG_ENTRY(StaticsMask_Dynamic),
5469     MTFLAG_ENTRY(StaticsMask_Generics),
5470     MTFLAG_ENTRY(StaticsMask_CrossModuleGenerics),
5471     MTFLAG_ENTRY(NotInPZM),
5472     MTFLAG_ENTRY(GenericsMask),
5473     MTFLAG_ENTRY(GenericsMask_NonGeneric),
5474     MTFLAG_ENTRY(GenericsMask_GenericInst),
5475     MTFLAG_ENTRY(GenericsMask_SharedInst),
5476     MTFLAG_ENTRY(GenericsMask_TypicalInst),
5477     MTFLAG_ENTRY(HasVariance),
5478     MTFLAG_ENTRY(HasDefaultCtor),
5479     MTFLAG_ENTRY(HasPreciseInitCctors),
5480 #if defined(FEATURE_HFA)
5481     MTFLAG_ENTRY(IsHFA),
5482 #endif // FEATURE_HFA
5483 #if defined(UNIX_AMD64_ABI)
5484     MTFLAG_ENTRY(IsRegStructPassed),
5485 #endif // UNIX_AMD64_ABI
5486     MTFLAG_ENTRY(IsByRefLike),
5487     MTFLAG_ENTRY(UNUSED_ComponentSize_5),
5488     MTFLAG_ENTRY(UNUSED_ComponentSize_6),
5489     MTFLAG_ENTRY(UNUSED_ComponentSize_7),
5490 #undef MTFLAG_ENTRY
5491 };
5492
5493 NativeImageDumper::EnumMnemonics s_MTFlagsHigh[] =
5494 {
5495 #define MTFLAG_ENTRY(x) \
5496     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5497
5498 #define MTFLAG_CATEGORY_ENTRY(x) \
5499     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_Mask, W("Category_") W(#x))
5500
5501 #define MTFLAG_CATEGORY_ENTRY_WITH_MASK(x, m) \
5502     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_Category_ ## x, MethodTable::enum_flag_Category_ ## m, W("Category_") W(#x))
5503
5504     MTFLAG_CATEGORY_ENTRY(Class),
5505     MTFLAG_CATEGORY_ENTRY(Unused_1),
5506     MTFLAG_CATEGORY_ENTRY(Unused_2),
5507     MTFLAG_CATEGORY_ENTRY(Unused_3),
5508     MTFLAG_CATEGORY_ENTRY(ValueType),
5509     MTFLAG_CATEGORY_ENTRY(Nullable),
5510     MTFLAG_CATEGORY_ENTRY(PrimitiveValueType),
5511     MTFLAG_CATEGORY_ENTRY(TruePrimitive),
5512
5513     MTFLAG_CATEGORY_ENTRY(Interface),
5514     MTFLAG_CATEGORY_ENTRY(Unused_4),
5515     MTFLAG_CATEGORY_ENTRY(Unused_5),
5516     MTFLAG_CATEGORY_ENTRY(Unused_6),
5517
5518     MTFLAG_CATEGORY_ENTRY_WITH_MASK(Array, Array_Mask),
5519     MTFLAG_CATEGORY_ENTRY_WITH_MASK(IfArrayThenSzArray, IfArrayThenSzArray),
5520
5521 #undef MTFLAG_CATEGORY_ENTRY_WITH_MASK
5522 #undef MTFLAG_CATEGORY_ENTRY
5523
5524     MTFLAG_ENTRY(HasFinalizer),
5525     MTFLAG_ENTRY(IfNotInterfaceThenMarshalable),
5526 #if defined(FEATURE_COMINTEROP)
5527     MTFLAG_ENTRY(IfInterfaceThenHasGuidInfo),
5528 #endif
5529 #if defined(FEATURE_ICASTABLE)    
5530     MTFLAG_ENTRY(ICastable),
5531 #endif    
5532     MTFLAG_ENTRY(HasIndirectParent),
5533     MTFLAG_ENTRY(ContainsPointers),
5534     MTFLAG_ENTRY(HasTypeEquivalence),
5535 #if defined(FEATURE_COMINTEROP)
5536     MTFLAG_ENTRY(HasRCWPerTypeData),
5537 #endif
5538     MTFLAG_ENTRY(HasCriticalFinalizer),
5539     MTFLAG_ENTRY(Collectible),
5540     MTFLAG_ENTRY(ContainsGenericVariables),
5541 #if defined(FEATURE_COMINTEROP)
5542     MTFLAG_ENTRY(ComObject),
5543 #endif
5544     MTFLAG_ENTRY(HasComponentSize),
5545 #undef MTFLAG_ENTRY
5546 };
5547
5548
5549 NativeImageDumper::EnumMnemonics s_MTFlags2[] =
5550 {
5551 #define MTFLAG2_ENTRY(x) \
5552     NativeImageDumper::EnumMnemonics(MethodTable::enum_flag_ ## x, W(#x))
5553     MTFLAG2_ENTRY(HasPerInstInfo),
5554     MTFLAG2_ENTRY(HasInterfaceMap),
5555     MTFLAG2_ENTRY(HasDispatchMapSlot),
5556     MTFLAG2_ENTRY(HasNonVirtualSlots),
5557     MTFLAG2_ENTRY(HasModuleOverride),
5558     MTFLAG2_ENTRY(IsZapped),
5559     MTFLAG2_ENTRY(IsPreRestored),
5560     MTFLAG2_ENTRY(HasModuleDependencies),
5561     MTFLAG2_ENTRY(IsIntrinsicType),
5562     MTFLAG2_ENTRY(RequiresDispatchTokenFat),
5563     MTFLAG2_ENTRY(HasCctor),
5564     MTFLAG2_ENTRY(HasCCWTemplate),
5565 #ifdef FEATURE_64BIT_ALIGNMENT
5566     MTFLAG2_ENTRY(RequiresAlign8),
5567 #endif
5568     MTFLAG2_ENTRY(HasBoxedRegularStatics),
5569     MTFLAG2_ENTRY(HasSingleNonVirtualSlot),
5570     MTFLAG2_ENTRY(DependsOnEquivalentOrForwardedStructs),
5571 #undef MTFLAG2_ENTRY
5572 };
5573
5574 NativeImageDumper::EnumMnemonics s_WriteableMTFlags[] =
5575 {
5576 #define WMTFLAG_ENTRY(x) \
5577     NativeImageDumper::EnumMnemonics(MethodTableWriteableData::enum_flag_ ## x,\
5578                                      W(#x))
5579
5580         WMTFLAG_ENTRY(Unrestored),
5581         WMTFLAG_ENTRY(HasApproxParent),
5582         WMTFLAG_ENTRY(UnrestoredTypeKey),
5583         WMTFLAG_ENTRY(IsNotFullyLoaded),
5584         WMTFLAG_ENTRY(DependenciesLoaded),
5585
5586 #ifdef _DEBUG
5587         WMTFLAG_ENTRY(ParentMethodTablePointerValid),
5588 #endif
5589
5590         WMTFLAG_ENTRY(NGEN_IsFixedUp),
5591         WMTFLAG_ENTRY(NGEN_IsNeedsRestoreCached),
5592         WMTFLAG_ENTRY(NGEN_CachedNeedsRestore),
5593 #undef WMTFLAG_ENTRY
5594 };
5595
5596 static NativeImageDumper::EnumMnemonics s_CorElementType[] =
5597 {
5598 #define CET_ENTRY(x) NativeImageDumper::EnumMnemonics(ELEMENT_TYPE_ ## x, 0, W("ELEMENT_TYPE_") W(#x))
5599     CET_ENTRY(END),
5600     CET_ENTRY(VOID),
5601     CET_ENTRY(BOOLEAN),
5602     CET_ENTRY(CHAR),
5603     CET_ENTRY(I1),
5604     CET_ENTRY(U1),
5605     CET_ENTRY(I2),
5606     CET_ENTRY(U2),
5607     CET_ENTRY(I4),
5608     CET_ENTRY(U4),
5609     CET_ENTRY(I8),
5610     CET_ENTRY(U8),
5611     CET_ENTRY(R4),
5612     CET_ENTRY(R8),
5613     CET_ENTRY(STRING),
5614     CET_ENTRY(PTR),
5615     CET_ENTRY(BYREF),
5616     CET_ENTRY(VALUETYPE),
5617     CET_ENTRY(CLASS),
5618     CET_ENTRY(VAR),
5619     CET_ENTRY(ARRAY),
5620     CET_ENTRY(GENERICINST),
5621     CET_ENTRY(TYPEDBYREF),
5622     CET_ENTRY(VALUEARRAY_UNSUPPORTED),
5623     CET_ENTRY(I),
5624     CET_ENTRY(U),
5625     CET_ENTRY(R_UNSUPPORTED),
5626     CET_ENTRY(FNPTR),
5627     CET_ENTRY(OBJECT),
5628     CET_ENTRY(SZARRAY),
5629     CET_ENTRY(MVAR),
5630     CET_ENTRY(CMOD_REQD),
5631     CET_ENTRY(CMOD_OPT),
5632     CET_ENTRY(INTERNAL),
5633
5634     CET_ENTRY(SENTINEL),
5635     CET_ENTRY(PINNED),
5636 #undef CET_ENTRY
5637 };
5638
5639 void NativeImageDumper::DoWriteFieldCorElementType( const char * name,
5640                                                     unsigned offset,
5641                                                     unsigned fieldSize,
5642                                                     CorElementType type )
5643 {
5644     TempBuffer buf;
5645     EnumFlagsToString( (int)type, s_CorElementType, dim(s_CorElementType),
5646                        W(""), buf );
5647     m_display->WriteFieldEnumerated( name, offset, fieldSize, (unsigned)type,
5648                                      (const WCHAR *) buf );
5649
5650 }
5651
5652 static NativeImageDumper::EnumMnemonics s_CorTypeAttr[] =
5653 {
5654 #define CTA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5655
5656 #define CTA_VISIBILITY_ENTRY(x) NativeImageDumper::EnumMnemonics( x, tdVisibilityMask, W(#x) )
5657     CTA_VISIBILITY_ENTRY(tdNotPublic),
5658     CTA_VISIBILITY_ENTRY(tdPublic),
5659     CTA_VISIBILITY_ENTRY(tdNestedPublic),
5660     CTA_VISIBILITY_ENTRY(tdNestedPrivate),
5661     CTA_VISIBILITY_ENTRY(tdNestedFamily),
5662     CTA_VISIBILITY_ENTRY(tdNestedAssembly),
5663     CTA_VISIBILITY_ENTRY(tdNestedFamANDAssem),
5664     CTA_VISIBILITY_ENTRY(tdNestedFamORAssem),
5665 #undef CTA_VISIBILITY_ENTRY
5666
5667     CTA_ENTRY(tdSequentialLayout),
5668     CTA_ENTRY(tdExplicitLayout),
5669
5670     CTA_ENTRY(tdInterface),
5671
5672     CTA_ENTRY(tdAbstract),
5673     CTA_ENTRY(tdSealed),
5674     CTA_ENTRY(tdSpecialName),
5675
5676     CTA_ENTRY(tdImport),
5677     CTA_ENTRY(tdSerializable),
5678
5679     CTA_ENTRY(tdUnicodeClass),
5680     CTA_ENTRY(tdAutoClass),
5681     CTA_ENTRY(tdCustomFormatClass),
5682     CTA_ENTRY(tdCustomFormatMask),
5683
5684     CTA_ENTRY(tdBeforeFieldInit),
5685     CTA_ENTRY(tdForwarder),
5686
5687     CTA_ENTRY(tdRTSpecialName),
5688     CTA_ENTRY(tdHasSecurity)
5689 #undef CTA_ENTRY
5690 };
5691 static NativeImageDumper::EnumMnemonics s_VMFlags[] =
5692 {
5693 #define VMF_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClass::VMFLAG_ ## x, W(#x) )
5694
5695 #ifdef FEATURE_READYTORUN
5696         VMF_ENTRY(LAYOUT_DEPENDS_ON_OTHER_MODULES),
5697 #endif
5698         VMF_ENTRY(DELEGATE),
5699         VMF_ENTRY(FIXED_ADDRESS_VT_STATICS),
5700         VMF_ENTRY(HASLAYOUT),
5701         VMF_ENTRY(ISNESTED),
5702         VMF_ENTRY(IS_EQUIVALENT_TYPE),
5703
5704         VMF_ENTRY(HASOVERLAYEDFIELDS),
5705         VMF_ENTRY(HAS_FIELDS_WHICH_MUST_BE_INITED),
5706         VMF_ENTRY(UNSAFEVALUETYPE),
5707
5708         VMF_ENTRY(BESTFITMAPPING_INITED),
5709         VMF_ENTRY(BESTFITMAPPING),
5710         VMF_ENTRY(THROWONUNMAPPABLECHAR),
5711
5712         VMF_ENTRY(NO_GUID),
5713         VMF_ENTRY(HASNONPUBLICFIELDS),
5714         VMF_ENTRY(PREFER_ALIGN8),
5715
5716 #ifdef FEATURE_COMINTEROP
5717         VMF_ENTRY(SPARSE_FOR_COMINTEROP),
5718         VMF_ENTRY(HASCOCLASSATTRIB),
5719         VMF_ENTRY(COMEVENTITFMASK),
5720         VMF_ENTRY(PROJECTED_FROM_WINRT),
5721         VMF_ENTRY(EXPORTED_TO_WINRT),
5722 #endif // FEATURE_COMINTEROP
5723
5724         VMF_ENTRY(NOT_TIGHTLY_PACKED),
5725         VMF_ENTRY(CONTAINS_METHODIMPLS),
5726 #ifdef FEATURE_COMINTEROP
5727         VMF_ENTRY(MARSHALINGTYPE_MASK),
5728         VMF_ENTRY(MARSHALINGTYPE_INHIBIT),
5729         VMF_ENTRY(MARSHALINGTYPE_FREETHREADED),
5730         VMF_ENTRY(MARSHALINGTYPE_STANDARD),
5731 #endif        
5732 #undef VMF_ENTRY
5733 };
5734 static NativeImageDumper::EnumMnemonics s_CorFieldAttr[] =
5735 {
5736 #define CFA_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5737
5738 #define CFA_ACCESS_ENTRY(x) NativeImageDumper::EnumMnemonics( x, fdFieldAccessMask, W(#x) )
5739     CFA_ENTRY(fdPrivateScope),
5740     CFA_ENTRY(fdPrivate),
5741     CFA_ENTRY(fdFamANDAssem),
5742     CFA_ENTRY(fdAssembly),
5743     CFA_ENTRY(fdFamily),
5744     CFA_ENTRY(fdFamORAssem),
5745     CFA_ENTRY(fdPublic),
5746 #undef CFA_ACCESS_ENTRY
5747
5748     CFA_ENTRY(fdStatic),
5749     CFA_ENTRY(fdInitOnly),
5750     CFA_ENTRY(fdLiteral),
5751     CFA_ENTRY(fdNotSerialized),
5752
5753     CFA_ENTRY(fdSpecialName),
5754
5755     CFA_ENTRY(fdPinvokeImpl),
5756
5757     CFA_ENTRY(fdRTSpecialName),
5758     CFA_ENTRY(fdHasFieldMarshal),
5759     CFA_ENTRY(fdHasDefault),
5760     CFA_ENTRY(fdHasFieldRVA),
5761 #undef CFA_ENTRY
5762 };
5763
5764 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDFlag2[] =
5765 {
5766 #define MDF2_ENTRY(x) NativeImageDumper::EnumMnemonics( MethodDesc::enum_flag2_ ## x, W("enum_flag2_") W(#x) )
5767     MDF2_ENTRY(HasStableEntryPoint),
5768     MDF2_ENTRY(HasPrecode),
5769     MDF2_ENTRY(IsUnboxingStub),
5770     MDF2_ENTRY(HasNativeCodeSlot),
5771 #undef MDF2_ENTRY
5772 };
5773
5774 NativeImageDumper::EnumMnemonics NativeImageDumper::s_MDC[] =
5775 {
5776 #define MDC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
5777
5778 #define MDC_ENTRY_CLASSIFICATION(x) NativeImageDumper::EnumMnemonics( x, mdcClassification, W(#x) )
5779     MDC_ENTRY_CLASSIFICATION(mcIL),
5780     MDC_ENTRY_CLASSIFICATION(mcFCall),
5781     MDC_ENTRY_CLASSIFICATION(mcNDirect),
5782     MDC_ENTRY_CLASSIFICATION(mcEEImpl),
5783     MDC_ENTRY_CLASSIFICATION(mcArray),
5784     MDC_ENTRY_CLASSIFICATION(mcInstantiated),
5785 #ifdef FEATURE_COMINTEROP
5786     MDC_ENTRY_CLASSIFICATION(mcComInterop),
5787 #endif // FEATURE_COMINTEROP
5788     MDC_ENTRY_CLASSIFICATION(mcDynamic),
5789 #undef MDC_ENTRY_CLASSIFICATION
5790
5791     MDC_ENTRY(mdcHasNonVtableSlot),
5792     MDC_ENTRY(mdcMethodImpl),
5793
5794     // Method is static
5795     MDC_ENTRY(mdcStatic),
5796
5797     MDC_ENTRY(mdcDuplicate),
5798     MDC_ENTRY(mdcVerifiedState),
5799     MDC_ENTRY(mdcVerifiable),
5800     MDC_ENTRY(mdcNotInline),
5801     MDC_ENTRY(mdcSynchronized),
5802     MDC_ENTRY(mdcRequiresFullSlotNumber),
5803 #undef MDC_ENTRY
5804 };
5805
5806
5807
5808 void NativeImageDumper::DumpTypes(PTR_Module module)
5809 {
5810     _ASSERTE(CHECK_OPT(EECLASSES) || CHECK_OPT(METHODTABLES)
5811              || CHECK_OPT(TYPEDESCS));
5812
5813     IF_OPT_OR3(METHODTABLES, EECLASSES, TYPEDESCS)
5814         m_display->StartCategory( "Types" );
5815     IF_OPT(METHODTABLES)
5816     {
5817         //there may be duplicates in the list.  Remove them before moving on.
5818         COUNT_T mtCount = m_discoveredMTs.GetCount();
5819
5820 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5821         std::sort(&*m_discoveredMTs.Begin(),
5822                   (&*m_discoveredMTs.Begin())
5823                   + (m_discoveredMTs.End() - m_discoveredMTs.Begin()));
5824         PTR_MethodTable* newEnd = std::unique(&*m_discoveredMTs.Begin(),
5825                                               (&*m_discoveredMTs.Begin())
5826                                               + (m_discoveredMTs.End()
5827                                                  - m_discoveredMTs.Begin()));
5828         mtCount = (COUNT_T)(newEnd - &*m_discoveredMTs.Begin());
5829 #endif
5830
5831         DisplayStartArray( "MethodTables", NULL, METHODTABLES );
5832         for(COUNT_T i = 0; i < mtCount; ++i )
5833         {
5834             PTR_MethodTable mt = m_discoveredMTs[i];
5835             if( mt == NULL )
5836                 continue;
5837             DumpMethodTable( mt, "MethodTable", module );
5838         }
5839
5840         DisplayEndArray( "Total MethodTables", METHODTABLES );
5841
5842         DisplayStartArray( "MethodTableSlotChunks", NULL, METHODTABLES );
5843         {
5844             COUNT_T slotChunkCount = m_discoveredSlotChunks.GetCount();
5845 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5846             std::sort(&*m_discoveredSlotChunks.Begin(),
5847                       (&*m_discoveredSlotChunks.Begin())
5848                       + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin()));
5849             SlotChunk *newEndChunks = std::unique(&*m_discoveredSlotChunks.Begin(),
5850                                               (&*m_discoveredSlotChunks.Begin())
5851                                               + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin()));
5852             slotChunkCount = (COUNT_T)(newEndChunks - &*m_discoveredSlotChunks.Begin());
5853 #endif
5854             
5855             for (COUNT_T i = 0; i < slotChunkCount; ++i)
5856             {
5857                 DumpMethodTableSlotChunk(m_discoveredSlotChunks[i].addr,
5858                                          m_discoveredSlotChunks[i].nSlots,
5859                                          m_discoveredSlotChunks[i].isRelative);
5860             }
5861         }
5862         DisplayEndArray( "Total MethodTableSlotChunks", METHODTABLES );
5863     }
5864     IF_OPT(EECLASSES)
5865     {
5866         DisplayStartArray( "EEClasses", NULL, EECLASSES );
5867
5868         //there may be duplicates in the list.  Remove them before moving on.
5869         COUNT_T clazzCount = m_discoveredClasses.GetCount();
5870 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5871         std::sort(&*m_discoveredClasses.Begin(),
5872                   (&*m_discoveredClasses.Begin())
5873                   + (m_discoveredClasses.End() - m_discoveredClasses.Begin()));
5874         PTR_MethodTable * newEndClazz = std::unique(&*m_discoveredClasses.Begin(),
5875                                                (&*m_discoveredClasses.Begin())
5876                                                +(m_discoveredClasses.End()
5877                                                  -m_discoveredClasses.Begin()));
5878         clazzCount = (COUNT_T)(newEndClazz - &*m_discoveredClasses.Begin());
5879 #endif
5880
5881         for(COUNT_T i = 0; i < clazzCount; ++i )
5882         {
5883             PTR_MethodTable mt = m_discoveredClasses[i];
5884             if( mt == NULL )
5885                 continue;
5886             DumpEEClassForMethodTable( mt );
5887         }
5888
5889         DisplayEndArray( "Total EEClasses", EECLASSES ); //EEClasses
5890
5891     }
5892     IF_OPT(TYPEDESCS)
5893     {
5894         DisplayStartArray( "TypeDescs", NULL, TYPEDESCS );
5895
5896         //there may be duplicates in the list.  Remove them before moving on.
5897         COUNT_T tdCount = m_discoveredTypeDescs.GetCount();
5898 #if !defined(FEATURE_CORESYSTEM) // no STL right now
5899         std::sort(&*m_discoveredTypeDescs.Begin(),
5900                   (&*m_discoveredTypeDescs.Begin())
5901                   + (m_discoveredTypeDescs.End()
5902                      - m_discoveredTypeDescs.Begin()));
5903         PTR_TypeDesc* newEndTD = std::unique(&*m_discoveredTypeDescs.Begin(),
5904                                              (&*m_discoveredTypeDescs.Begin())
5905                                              +(m_discoveredTypeDescs.End()
5906                                                -m_discoveredTypeDescs.Begin()));
5907         tdCount = (COUNT_T)(newEndTD - &*m_discoveredTypeDescs.Begin());
5908 #endif
5909
5910         for(COUNT_T i = 0; i < tdCount; ++i )
5911         {
5912             PTR_TypeDesc td = m_discoveredTypeDescs[i];
5913             if( td == NULL )
5914                 continue;
5915             DumpTypeDesc( td );
5916         }
5917
5918         DisplayEndArray( "Total TypeDescs", TYPEDESCS ); //EEClasses
5919
5920     }
5921     IF_OPT_OR3(EECLASSES, METHODTABLES, TYPEDESCS)
5922         m_display->EndCategory(); //Types
5923 }
5924
5925 PTR_EEClass NativeImageDumper::GetClassFromMT( PTR_MethodTable mt )
5926 {
5927     /* REVISIT_TODO Tue 10/11/2005
5928      * Handle fixups
5929      */
5930     _ASSERTE( mt->IsClassPointerValid() );
5931     PTR_EEClass clazz( mt->GetClass() );
5932     return clazz;
5933 }
5934 PTR_MethodTable NativeImageDumper::GetParent( PTR_MethodTable mt )
5935 {
5936     /* REVISIT_TODO Thu 12/01/2005
5937      * Handle fixups
5938      */
5939     PTR_MethodTable parent( ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent()) );
5940     _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(parent)));
5941     return parent;
5942 }
5943
5944 //Counts the FieldDescs in a class.  This is all of the non-static and static
5945 //non-literal fields.
5946 SIZE_T NativeImageDumper::CountFields( PTR_MethodTable mt )
5947 {
5948     SIZE_T fieldCount = 0;
5949
5950     HCORENUM hEnum = NULL;
5951
5952     const Dependency * dep = GetDependencyFromMT(mt);
5953     mdToken classToken = mt->GetCl();
5954
5955     _ASSERTE(dep);
5956     _ASSERTE(dep->pImport);
5957
5958     //Arrays have no token.
5959     if( RidFromToken(classToken) == 0 )
5960         return 0;
5961
5962     for (;;)
5963     {
5964         mdToken fields[1];
5965         ULONG numFields;
5966
5967         IfFailThrow(dep->pImport->EnumFields( &hEnum, classToken, fields,
5968                                        1, &numFields));
5969
5970         if (numFields == 0)
5971             break;
5972
5973         DWORD dwAttr;
5974         IfFailThrow(dep->pImport->GetFieldProps( fields[0], NULL, NULL, 0,
5975                                                  NULL, & dwAttr, NULL, NULL,
5976                                                  NULL, NULL, NULL ) );
5977         if( !IsFdStatic(dwAttr) || !IsFdLiteral(dwAttr) )
5978             ++fieldCount;
5979     }
5980     dep->pImport->CloseEnum(hEnum);
5981     return fieldCount;
5982 }
5983 const NativeImageDumper::Dependency*
5984 NativeImageDumper::GetDependencyFromMT( PTR_MethodTable mt )
5985 {
5986     if( !mt->IsClassPointerValid() )
5987     {
5988         //This code will not work for out of module dependencies.
5989         _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(mt))));
5990
5991         //the EEClass is a fixup.  The home for that fixup tells us the
5992         //home for the metadata.
5993         unsigned rva = CORCOMPILE_UNTAG_TOKEN(mt->GetCanonicalMethodTableFixup());
5994         return GetDependencyForFixup(rva);
5995     }
5996     PTR_Module module = mt->GetModule();
5997     if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
5998     {
5999         unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
6000         return GetDependencyForFixup(rva);
6001     }
6002     return GetDependencyForModule(module);
6003 }
6004 const NativeImageDumper::Dependency*
6005 NativeImageDumper::GetDependencyFromFD( PTR_FieldDesc fd )
6006 {
6007     PTR_MethodTable mt = fd->GetApproxEnclosingMethodTable();
6008     if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6009     {
6010         //This code will not work for out of module dependencies.
6011         _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(fd))));
6012
6013         //the MethodTable has a fixup.  The home for that fixup tells us the
6014         //home for the metadata.
6015         unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6016         return GetDependencyForFixup(rva);
6017     }
6018     return GetDependencyFromMT(mt);
6019 }
6020 const NativeImageDumper::Dependency*
6021 NativeImageDumper::GetDependencyFromMD( PTR_MethodDesc md )
6022 {
6023     PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
6024     PTR_MethodTable mt = chunk->GetMethodTable();
6025     if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6026     {
6027         //This code will not work for out of module dependencies.
6028         _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6029
6030         //the MethodTable has a fixup.  The home for that fixup tells us the
6031         //home for the metadata.
6032         unsigned rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6033         return GetDependencyForFixup(rva);
6034     }
6035     return GetDependencyFromMT(mt);
6036 }
6037
6038 BOOL NativeImageDumper::DoWriteFieldAsFixup( const char * name,
6039                                              unsigned offset,
6040                                              unsigned fieldSize, TADDR fixup)
6041 {
6042     if( !CORCOMPILE_IS_POINTER_TAGGED(fixup) )
6043         return FALSE;
6044     if( UINT_MAX == offset )
6045         m_display->StartVStructure( name );
6046     else
6047         m_display->StartVStructureWithOffset( name, offset, fieldSize );
6048
6049     WriteElementsFixupBlob( NULL, fixup );
6050     m_display->EndVStructure(); //name
6051     return TRUE;
6052 }
6053
6054 void AppendTypeQualifier( CorElementType kind, DWORD rank, SString& buf )
6055 {
6056     switch( kind )
6057     {
6058     case ELEMENT_TYPE_BYREF :
6059         buf.Append( W("&") );
6060         break;
6061     case ELEMENT_TYPE_PTR :
6062         buf.Append( W("*") );
6063         break;
6064     case ELEMENT_TYPE_SZARRAY :
6065         buf.Append( W("[]") );
6066         break;
6067     case ELEMENT_TYPE_ARRAY :        
6068         if( rank == 1 )
6069         {
6070             buf.Append( W("[*]") );
6071         }
6072         else
6073         {
6074             buf.Append( W("[") );
6075             for( COUNT_T i = 0; i < rank; ++i )
6076                 buf.Append( W(","));
6077             buf.Append( W("]") );
6078         }
6079         break;
6080     default :
6081         break;
6082     }
6083 }
6084 void NativeImageDumper::TypeDescToString( PTR_TypeDesc td, SString& buf )
6085 {
6086     _ASSERTE(!(PTR_TO_TADDR(td) & 0x2));
6087     if( td->IsGenericVariable() )
6088     {
6089         PTR_TypeVarTypeDesc tvtd( PTR_TO_TADDR(td) );
6090         //From code:TypeString::AppendType
6091         mdGenericParam token = tvtd->GetToken();
6092         PTR_Module module(tvtd->GetModule());
6093         IMetaDataImport2 * pImport;
6094         if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module)) )
6095         {
6096             if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(td))))
6097             {
6098                 //this is an RVA from another hardbound dependency.  We cannot decode it
6099                 buf.Append(W("OUT_OF_MODULE_FIXUP"));
6100                 return;
6101             }
6102             else
6103             {
6104                 RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(module));
6105                 pImport = GetDependencyForFixup(rva)->pImport;
6106             }
6107         }
6108         else
6109         {
6110             pImport = GetDependencyForModule(module)->pImport;
6111         }
6112         AppendTokenName(token, buf, pImport);
6113     }
6114     else if( ELEMENT_TYPE_FNPTR == td->GetInternalCorElementType() )
6115     {
6116         PTR_FnPtrTypeDesc fptd( PTR_TO_TADDR(td) );
6117         buf.Append( W("(fnptr)") );
6118     }
6119     else if( td->HasTypeParam() || td->IsArray() )
6120     {
6121         //either a Parameter or an Array.
6122         PTR_ParamTypeDesc ptd(PTR_TO_TADDR(td));
6123         TypeHandle elemType;
6124         /* REVISIT_TODO Thu 10/5/2006
6125          * Do I need to find a rank somewhere in the TypeDesc?
6126          */
6127         unsigned rank;
6128         if( td->IsArray()  )
6129         {
6130             //td->HasTypeParam() may also be true.
6131             PTR_MethodTable mt = ptd->GetTemplateMethodTableInternal();
6132             _ASSERTE( PTR_TO_TADDR(mt) );
6133             if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6134             {
6135                 if (!isSelf(GetDependencyForPointer(PTR_TO_TADDR(ptd))))
6136                 {
6137                     //this is an RVA from another hardbound dependency.  We cannot decode it
6138                     buf.Append(W("OUT_OF_MODULE_FIXUP"));
6139                 }
6140                 else
6141                 {
6142                     RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6143                     FixupBlobToString(rva, buf);
6144                 }
6145                 return;
6146             }
6147             else
6148             {
6149                 _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) );
6150                 MethodTableToString( mt, buf );
6151                 rank = PTR_ArrayTypeDesc(PTR_TO_TADDR(ptd))->GetRank();
6152             }
6153         }
6154         else
6155         {
6156             _ASSERTE(td->HasTypeParam());
6157             TypeHandle th(ptd->GetTypeParam());
6158             _ASSERTE( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) );
6159             _ASSERTE( th.AsTAddr() );
6160             TypeHandleToString(th, buf);
6161             rank = 0;
6162         }
6163         AppendTypeQualifier( td->GetInternalCorElementType(), rank, buf );
6164     }
6165     else
6166     {
6167         //generic typedesc?
6168         EnumFlagsToString( (int)td->GetInternalCorElementType(), s_CorElementType, dim(s_CorElementType),
6169                            W(""), buf );
6170     }
6171 }
6172 void NativeImageDumper::TypeHandleToString( TypeHandle th, SString& buf )
6173 {
6174     TADDR arg = th.AsTAddr();
6175     /* REVISIT_TODO Thu 10/5/2006
6176      * Is this constant somewhere?
6177      */
6178     //0x2 is the subtle hint that this is a typedesc.  code:TypeHandle::AsTypeDesc
6179     if( arg & 0x2 )
6180     {
6181         PTR_TypeDesc argTD( arg & ~0x2 );
6182         TypeDescToString( argTD, buf );
6183     }
6184     else
6185     {
6186         PTR_MethodTable argMT( th.AsTAddr() );
6187         MethodTableToString( argMT, buf );
6188     }
6189 }
6190
6191 void NativeImageDumper::DoWriteFieldTypeHandle( const char * name,
6192                                                 unsigned offset,
6193                                                 unsigned fieldSize,
6194                                                 TypeHandle th )
6195 {
6196     TempBuffer buf;
6197     TADDR ptr = th.AsTAddr();
6198     if( DoWriteFieldAsFixup(name, offset, fieldSize, th.AsTAddr() ) )
6199         return;
6200     else
6201     {
6202         TypeHandleToString(th, buf);
6203
6204         buf.Append( W(" (from TypeHandle)") );
6205         /* REVISIT_TODO Fri 10/14/2005
6206          * Do a better job of this
6207          */
6208         if( offset == UINT_MAX )
6209         {
6210             m_display->WriteElementPointerAnnotated( name,
6211                                                      DataPtrToDisplay(ptr),
6212                                                      (const WCHAR*) buf );
6213         }
6214         else
6215         {
6216             m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6217                                                    DataPtrToDisplay(ptr),
6218                                                    (const WCHAR*) buf );
6219         }
6220     }
6221 }
6222 void NativeImageDumper::WriteElementTypeHandle( const char * name,
6223                                                 TypeHandle th )
6224 {
6225     DoWriteFieldTypeHandle( name, UINT_MAX, UINT_MAX, th );
6226 }
6227
6228 void NativeImageDumper::DoDumpFieldStub( PTR_Stub stub, unsigned offset,
6229                                          unsigned fieldSize, const char * name )
6230 {
6231     _ASSERTE(CHECK_OPT(EECLASSES));
6232     if( stub == NULL )
6233     {
6234         m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6235     }
6236     else
6237     {
6238         m_display->StartStructureWithOffset( name, offset, fieldSize,
6239                                              DPtrToPreferredAddr(stub),
6240                                              sizeof(*stub) );
6241         /* REVISIT_TODO Fri 10/14/2005
6242          * Dump stub
6243          */
6244         m_display->EndStructure();
6245     }
6246 }
6247
6248 #ifdef FEATURE_COMINTEROP
6249 void NativeImageDumper::DoDumpComPlusCallInfo( PTR_ComPlusCallInfo compluscall )
6250 {
6251     m_display->StartStructure( "ComPlusCallInfo",
6252                                DPtrToPreferredAddr(compluscall),
6253                                sizeof(*compluscall) );
6254
6255     DisplayWriteFieldPointer( m_pILStub, compluscall->m_pILStub,
6256                    ComPlusCallInfo, ALWAYS);
6257     /* REVISIT_TODO Fri 12/16/2005
6258      * Coverage read stub?
6259      */
6260     WriteFieldMethodTable(m_pInterfaceMT,
6261                           compluscall->m_pInterfaceMT,
6262                           ComPlusCallInfo, ALWAYS);
6263
6264     PTR_MethodDesc pEventProviderMD = PTR_MethodDesc((TADDR)compluscall->m_pEventProviderMD);
6265     WriteFieldMethodDesc(m_pEventProviderMD,
6266                          pEventProviderMD,
6267                          ComPlusCallInfo, ALWAYS);
6268     DisplayWriteFieldInt( m_cachedComSlot, compluscall->m_cachedComSlot,
6269                           ComPlusCallInfo, ALWAYS );
6270
6271     /* REVISIT_TODO Fri 12/16/2005
6272      * Dump these as mnemonics
6273      */
6274     DisplayWriteFieldInt( m_flags, compluscall->m_flags,
6275                           ComPlusCallInfo, ALWAYS );
6276     WriteFieldMethodDesc( m_pStubMD,
6277                           compluscall->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(ComPlusCallInfo, compluscall, m_pStubMD)),
6278                           ComPlusCallInfo, ALWAYS );
6279
6280 #ifdef _TARGET_X86_
6281     DisplayWriteFieldInt( m_cbStackArgumentSize, compluscall->m_cbStackArgumentSize,
6282                           ComPlusCallInfo, ALWAYS );
6283
6284     DisplayWriteFieldPointer( m_pRetThunk,
6285                               DataPtrToDisplay((TADDR)compluscall->m_pRetThunk),
6286                               ComPlusCallInfo, ALWAYS );
6287 #endif
6288     m_display->EndStructure(); //ComPlusCallInfo
6289 }
6290 #endif // FEATURE_COMINTEROP
6291
6292 void NativeImageDumper::DoWriteFieldStr( PTR_BYTE ptr, const char * name,
6293                                          unsigned offset, unsigned fieldSize )
6294 {
6295     if( ptr == NULL )
6296     {
6297         if( UINT_MAX == offset )
6298             m_display->WriteElementPointer( name, NULL );
6299         else
6300             m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6301     }
6302     else
6303     {
6304         /* REVISIT_TODO Wed 03/22/2006
6305          * Obviously this does the wrong thing for UTF-8.
6306          */
6307         TempBuffer buf;
6308         BYTE b;
6309         TADDR taddr = DPtrToPreferredAddr(ptr);
6310         PTR_BYTE current = ptr;
6311         /* REVISIT_TODO Mon 03/27/2006
6312          * Actually handle UTF-8 properly
6313          */
6314         while( (b = *current++) != 0 )
6315             buf.Append( (WCHAR)b );
6316         /* REVISIT_TODO Wed 03/22/2006
6317          * This seems way way way more verbose than it needs to be.
6318          */
6319         if( UINT_MAX == offset )
6320         {
6321             m_display->StartStructure( name, DataPtrToDisplay(taddr),
6322                                        current - ptr );
6323         }
6324         else
6325         {
6326             m_display->StartStructureWithOffset( name, offset, fieldSize,
6327                                                  DataPtrToDisplay(taddr),
6328                                                  current - ptr );
6329         }
6330         DisplayWriteElementStringW( "Value", (const WCHAR *)buf, ALWAYS );
6331         m_display->EndStructure();
6332         /*
6333         m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6334                                                taddr, (const WCHAR *)buf );
6335                                                */
6336     }
6337 }
6338 void NativeImageDumper::WriteFieldDictionaryLayout(const char * name,
6339                                                    unsigned offset,
6340                                                    unsigned fieldSize,
6341                                                    PTR_DictionaryLayout layout,
6342                                                    IMetaDataImport2 * import)
6343 {
6344     if( layout == NULL )
6345     {
6346         m_display->WriteFieldPointer(name, NULL, offset, fieldSize);
6347         return;
6348     }
6349     m_display->StartVStructureWithOffset( name, offset, fieldSize );
6350     DisplayStartArray( "DictionaryLayouts", NULL, ALWAYS );
6351     do
6352     {
6353         DisplayStartStructure( "DictionaryLayout", DPtrToPreferredAddr(layout),
6354                                sizeof(DictionaryLayout)
6355                                + sizeof(DictionaryEntryLayout)
6356                                * (layout->m_numSlots - 1), ALWAYS );
6357
6358
6359         DisplayWriteFieldPointer( m_pNext, DataPtrToDisplay((TADDR)layout->m_pNext),
6360                                   DictionaryLayout, ALWAYS );
6361         DisplayWriteFieldInt( m_numSlots, layout->m_numSlots,
6362                               DictionaryLayout, ALWAYS );
6363         DisplayStartArrayWithOffset( m_slots, NULL, DictionaryLayout, ALWAYS );
6364         for( unsigned i = 0; i < layout->m_numSlots; ++i )
6365         {
6366             PTR_DictionaryEntryLayout entry( PTR_HOST_MEMBER_TADDR(DictionaryLayout, layout, m_slots) + (i * sizeof(DictionaryEntryLayout)) );
6367             DisplayStartStructure( "DictionaryEntryLayout",
6368                                    DPtrToPreferredAddr(entry), sizeof(*entry),
6369                                    ALWAYS );
6370             const char * kind = NULL;
6371             switch( entry->GetKind() )
6372             {
6373 #define KIND_ENTRY(x) case x : kind = # x ; break
6374                 KIND_ENTRY(EmptySlot);
6375                 KIND_ENTRY(TypeHandleSlot);
6376                 KIND_ENTRY(MethodDescSlot);
6377                 KIND_ENTRY(MethodEntrySlot);
6378                 KIND_ENTRY(ConstrainedMethodEntrySlot);
6379                 KIND_ENTRY(DispatchStubAddrSlot);
6380                 KIND_ENTRY(FieldDescSlot);
6381 #undef KIND_ENTRY
6382             default:
6383                 _ASSERTE( !"unreachable" );
6384             }
6385             DisplayWriteElementString( "Kind", kind, ALWAYS );
6386             DisplayWriteElementPointer( "Signature", DPtrToPreferredAddr(entry->m_signature), ALWAYS );
6387             DisplayEndStructure( ALWAYS ); //DictionaryEntryLayout
6388         }
6389         DisplayEndArray( "Total Dictionary Entries",  ALWAYS ); //m_slots
6390         DisplayEndStructure( ALWAYS ); //Layout
6391         layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
6392     }while( layout != NULL );
6393     DisplayEndArray( "Total Dictionary Layouts", ALWAYS ); //DictionaryLayouts
6394
6395
6396     DisplayEndVStructure( ALWAYS ); // name
6397 }
6398 void NativeImageDumper::DoWriteFieldFieldDesc( const char * name,
6399                                                unsigned offset,
6400                                                unsigned fieldSize,
6401                                                PTR_FieldDesc fd )
6402 {
6403     if( fd == NULL )
6404     {
6405         m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6406     }
6407     else
6408     {
6409         TempBuffer buf;
6410         FieldDescToString( fd, buf );
6411         m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6412                                                DPtrToPreferredAddr(fd),
6413                                                (const WCHAR*) buf );
6414     }
6415
6416 }
6417 void NativeImageDumper::DoWriteFieldMethodDesc( const char * name,
6418                                                 unsigned offset,
6419                                                 unsigned fieldSize,
6420                                                 PTR_MethodDesc md )
6421 {
6422     if( md == NULL )
6423     {
6424         m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6425     }
6426     else if( DoWriteFieldAsFixup(name, offset, fieldSize, PTR_TO_TADDR(md)) )
6427     {
6428         return;
6429     }
6430     else
6431     {
6432         TempBuffer buf;
6433         MethodDescToString( md, buf );
6434         m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6435                                                DPtrToPreferredAddr(md),
6436                                                (const WCHAR*) buf );
6437     }
6438 }
6439
6440 void NativeImageDumper::EntryPointToString( TADDR pEntryPoint,
6441                                             SString& buf )
6442 {
6443     const Dependency * dependency = GetDependencyForPointer(pEntryPoint);
6444
6445     PTR_MethodDesc md;
6446     if (dependency->pModule->IsZappedPrecode(pEntryPoint))
6447     {
6448         md = dac_cast<PTR_MethodDesc>(Precode::GetPrecodeFromEntryPoint(pEntryPoint)->GetMethodDesc());
6449     }
6450     else
6451     {
6452         PTR_Module module = (TADDR)m_decoder.GetPersistedModuleImage();
6453         PTR_NGenLayoutInfo pNgenLayout = module->GetNGenLayoutInfo();
6454         DWORD rva = (DWORD)(pEntryPoint - PTR_TO_TADDR(m_decoder.GetBase()));
6455
6456         for (int iRange = 0; iRange < 2; iRange++)
6457         {
6458             if (pNgenLayout->m_CodeSections[iRange].IsInRange(pEntryPoint))
6459             {
6460                 int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1);
6461                 if (MethodIndex >= 0)
6462                 {
6463 #ifdef WIN64EXCEPTIONS
6464                     while (pNgenLayout->m_MethodDescs[iRange][MethodIndex] == 0)
6465                         MethodIndex--;
6466 #endif
6467
6468                     PTR_RUNTIME_FUNCTION pRuntimeFunction = pNgenLayout->m_pRuntimeFunctions[iRange] + MethodIndex;
6469
6470                     md = NativeUnwindInfoLookupTable::GetMethodDesc(pNgenLayout, pRuntimeFunction, PTR_TO_TADDR(m_decoder.GetBase())); 
6471                     break;
6472                 }
6473             }
6474         }
6475     }
6476
6477     MethodDescToString(md, buf);
6478 }
6479
6480 void NativeImageDumper::MethodDescToString( PTR_MethodDesc md,
6481                                             SString& buf )
6482 {
6483     if( md == NULL )
6484         buf.Append( W("mdMethodDefNil") );
6485     else if( md->IsILStub() )
6486         buf.AppendUTF8(md->AsDynamicMethodDesc()->GetName());
6487     else
6488     {
6489         //write the name to a temporary location, since I'm going to insert it
6490         //into the middle of a signature.
6491         TempBuffer tempName;
6492
6493         _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(md)));
6494         //work back to the EEClass.  That gives us the context for the token.
6495         PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
6496         //chunk is implicitly remapped because it's calculated from the pointer
6497         //to MD.
6498         PTR_MethodTable mt = chunk->GetMethodTable();
6499         const Dependency * dependency;
6500         if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
6501         {
6502             //This code will not work for out of module dependencies.
6503             _ASSERTE(isSelf(GetDependencyForPointer(PTR_TO_TADDR(md))));
6504
6505             RVA rva = CORCOMPILE_UNTAG_TOKEN(PTR_TO_TADDR(mt));
6506             dependency = GetDependencyForFixup(rva);
6507             mt = NULL; //make sure we don't use this for anything.
6508         }
6509         else
6510             dependency = GetDependencyFromMT(mt);
6511
6512         _ASSERTE(dependency);
6513
6514
6515         /* REVISIT_TODO Fri 10/13/2006
6516          * Don't I need the array type name here?
6517          */
6518         _ASSERTE(dependency->pImport);
6519         if( md->GetClassification() == mcArray )
6520         {
6521
6522             //We don't need to append the dependency all the time.
6523             //MethodTableToString() already appends it to the MethodTable.
6524             //Only do it in cases where we don't call MethodTableToString.
6525             if( !isSelf(dependency) )
6526             {
6527                 AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6528                                  m_manifestImport );
6529                 tempName.Append(W("!"));
6530             }
6531
6532             _ASSERTE(PTR_TO_TADDR(mt));
6533             MethodTableToString( mt, tempName );
6534             tempName.Append( W("::") );
6535
6536             //there are four hard coded names for array method descs, use these
6537             //instead of the token.
6538             PTR_ArrayMethodDesc amd(PTR_TO_TADDR(md));
6539             tempName.AppendUTF8( amd->GetMethodName() );
6540         }
6541         else
6542         {
6543             //if we have a MethodTable, use that and compose the name
6544             //ourselves.  That way we can get generic arguments.
6545             if( mt )
6546             {
6547                 ULONG size;
6548                 MethodTableToString( mt, tempName );
6549                 tempName.Append( W("::") );
6550                 IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(), NULL, bigBuffer,
6551                                                                 bigBufferSize, &size, NULL, NULL, NULL, NULL,
6552                                                                 NULL));
6553                 tempName.Append(bigBuffer);
6554             }
6555             else
6556             {
6557                 //We don't need to append the dependency all the time.
6558                 //MethodTableToString() already appends it to the MethodTable.
6559                 //Only do it in cases where we don't call MethodTableToString.
6560                 if( !isSelf(dependency) )
6561                 {
6562                     AppendTokenName( dependency->entry->dwAssemblyRef, tempName,
6563                                      m_manifestImport );
6564                     tempName.Append(W("!"));
6565                 }
6566                 AppendTokenName( md->GetMemberDef(), tempName, dependency->pImport );
6567             }
6568
6569             if( mcInstantiated == md->GetClassification() )
6570             {
6571                 PTR_InstantiatedMethodDesc imd(PTR_TO_TADDR(md));
6572                 unsigned numArgs = imd->m_wNumGenericArgs;
6573                 PTR_Dictionary dict(imd->IMD_GetMethodDictionary());
6574                 if( dict != NULL )
6575                 {
6576                     DictionaryToArgString( dict, numArgs, tempName );
6577                 }
6578             }
6579
6580             PCCOR_SIGNATURE pvSigBlob;
6581             ULONG cbSigBlob;
6582             IfFailThrow(dependency->pImport->GetMethodProps(md->GetMemberDef(),
6583                                                             NULL,
6584                                                             NULL,
6585                                                             0,
6586                                                             NULL,
6587                                                             NULL,
6588                                                             &pvSigBlob,
6589                                                             &cbSigBlob,
6590                                                             NULL,
6591                                                             NULL));
6592
6593
6594             CQuickBytes prettySig;
6595             ReleaseHolder<IMDInternalImport> pInternal;
6596             IfFailThrow(GetMDInternalInterfaceFromPublic(dependency->pImport, IID_IMDInternalImport,
6597                                                                (void**)&pInternal));
6598             StackScratchBuffer buffer;
6599             const ANSI * ansi = tempName.GetANSI(buffer);
6600             ansi = PrettyPrintSig(pvSigBlob, cbSigBlob, ansi, &prettySig, pInternal, NULL);
6601             tempName.SetANSI( ansi );
6602         }
6603         buf.Append(tempName);
6604     }
6605 }
6606 void NativeImageDumper::WriteElementMethodDesc( const char * name,
6607                                                 PTR_MethodDesc md )
6608 {
6609     if( md == NULL )
6610     {
6611         m_display->WriteElementPointer( name, NULL );
6612     }
6613     else
6614     {
6615         TempBuffer buf;
6616         MethodDescToString( md, buf );
6617         m_display->WriteElementPointerAnnotated( name, DPtrToPreferredAddr(md),
6618                                                  (const WCHAR*) buf );
6619     }
6620 }
6621 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, SString& buf )
6622 {
6623     FieldDescToString( fd, mdFieldDefNil, buf );
6624 }
6625 void NativeImageDumper::FieldDescToString( PTR_FieldDesc fd, mdFieldDef tok,
6626                                            SString& buf )
6627 {
6628     IF_OPT(DISABLE_NAMES)
6629     {
6630         buf.Append( W("Disabled") );
6631         return;
6632     }
6633     if( fd == NULL )
6634     {
6635         if( tok == mdFieldDefNil )
6636             buf.Append( W("mdFieldDefNil") );
6637         else
6638             AppendTokenName( tok, buf );
6639     }
6640     else
6641     {
6642         _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(fd)));
6643         IMetaDataImport2 * importMD = NULL;
6644         if( !isInRange(PTR_TO_TADDR(fd)) )
6645         {
6646             const Dependency * dependency = GetDependencyFromFD(fd);
6647             _ASSERTE(dependency);
6648             AppendTokenName( dependency->entry->dwAssemblyRef, buf,
6649                              m_manifestImport );
6650             buf.Append(W("!"));
6651             importMD = dependency->pImport;
6652             _ASSERTE(importMD);
6653
6654         }
6655         else
6656         {
6657             importMD = m_import;
6658         }
6659         AppendTokenName( fd->GetMemberDef(), buf, importMD );
6660     }
6661 }
6662
6663 void NativeImageDumper::DoWriteFieldAsHex( const char * name, unsigned offset,
6664                                            unsigned fieldSize, PTR_BYTE ptr,
6665                                            unsigned dataLen )
6666 {
6667     TempBuffer buffer;
6668     for( unsigned i = 0; i < dataLen; ++i )
6669     {
6670         unsigned char b = ptr[i];
6671         buffer.AppendPrintf( W("%02x%02x"), (b & 0xf0) >> 4, b & 0xf );
6672     }
6673     if( offset == UINT_MAX )
6674     {
6675         m_display->WriteElementStringW( name, (const WCHAR *)buffer );
6676     }
6677     else
6678     {
6679         m_display->WriteFieldStringW( name, offset, fieldSize,
6680                                       (const WCHAR *)buffer );
6681     }
6682 }
6683 void NativeImageDumper::WriteElementMDToken( const char * name, mdToken token )
6684 {
6685     DoWriteFieldMDToken( name, UINT_MAX, UINT_MAX, token );
6686 }
6687 void NativeImageDumper::DoWriteFieldMDToken( const char * name, unsigned offset,
6688                                              unsigned fieldSize, mdToken token,
6689                                              IMetaDataImport2 * import )
6690 {
6691     TempBuffer buf;
6692     if( RidFromToken(token) == mdTokenNil )
6693     {
6694         AppendNilToken( token, buf );
6695     }
6696     else
6697     {
6698         AppendToken( token, buf, import );
6699     }
6700     if( UINT_MAX == offset )
6701         m_display->WriteElementEnumerated( name, token, (const WCHAR *)buf );
6702     else
6703     {
6704         m_display->WriteFieldEnumerated(name, offset, fieldSize, token,
6705                                         (const WCHAR*)buf);
6706     }
6707 }
6708
6709 void NativeImageDumper::WriteElementMethodTable( const char * name,
6710                                                  PTR_MethodTable mt )
6711 {
6712     DoWriteFieldMethodTable( name, UINT_MAX, UINT_MAX, mt );
6713 }
6714 void NativeImageDumper::DoWriteFieldMethodTable( const char * name,
6715                                                  unsigned offset, 
6716                                                  unsigned fieldSize, 
6717                                                  PTR_MethodTable mt )
6718 {
6719     if( mt == NULL )
6720     {
6721         if( UINT_MAX == offset )
6722             m_display->WriteElementPointer( name, NULL );
6723         else
6724             m_display->WriteFieldPointer( name, offset, fieldSize, NULL );
6725     }
6726     else if( DoWriteFieldAsFixup( name, offset, fieldSize, PTR_TO_TADDR(mt) ) )
6727     {
6728         return;
6729     }
6730     else
6731     {
6732         TempBuffer buf;
6733         MethodTableToString( mt, buf );
6734         if( UINT_MAX == offset )
6735         {
6736
6737             m_display->WriteElementPointerAnnotated( name,
6738                                                      DPtrToPreferredAddr(mt),
6739                                                      (const WCHAR*) buf );
6740         }
6741         else
6742         {
6743             m_display->WriteFieldPointerAnnotated( name, offset, fieldSize,
6744                                                    DPtrToPreferredAddr(mt),
6745                                                    (const WCHAR*) buf );
6746         }
6747     }
6748 }
6749
6750 const char * s_VTSCallbackNames[] =
6751 {
6752 #define VTSCB_ENTRY(x) # x
6753     VTSCB_ENTRY(VTS_CALLBACK_ON_SERIALIZING),
6754     VTSCB_ENTRY(VTS_CALLBACK_ON_SERIALIZED),
6755     VTSCB_ENTRY(VTS_CALLBACK_ON_DESERIALIZING),
6756     VTSCB_ENTRY(VTS_CALLBACK_ON_DESERIALIZED),
6757 #undef VTSCB_ENTRY
6758 };
6759 void NativeImageDumper::DumpFieldDesc( PTR_FieldDesc fd, const char * name )
6760 {
6761     DisplayStartStructure( name, DPtrToPreferredAddr(fd), sizeof(*fd),
6762                            ALWAYS );
6763     WriteFieldMethodTable( m_pMTOfEnclosingClass,
6764                            fd->GetApproxEnclosingMethodTable(), FieldDesc, ALWAYS );
6765     m_display->WriteFieldUInt( "m_mb", offsetof(FieldDesc, m_dword1),
6766                                fieldsize(FieldDesc, m_dword1),
6767                                fd->GetMemberDef() );
6768     m_display->WriteFieldFlag( "m_isStatic",
6769                                offsetof(FieldDesc, m_dword1),
6770                                fieldsize(FieldDesc, m_dword1),
6771                                fd->m_isStatic );
6772     m_display->WriteFieldFlag( "m_isThreadLocal",
6773                                offsetof(FieldDesc, m_dword1),
6774                                fieldsize(FieldDesc, m_dword1),
6775                                fd->m_isThreadLocal );
6776     m_display->WriteFieldFlag( "m_isRVA", offsetof(FieldDesc, m_dword1),
6777                                fieldsize(FieldDesc, m_dword1),
6778                                fd->m_isRVA );
6779
6780     {
6781         TempBuffer buf;
6782         EnumFlagsToString( fd->m_prot, s_CorFieldAttr,
6783                            _countof(s_CorFieldAttr), W(" "), buf );
6784         m_display->WriteFieldEnumerated( "m_prot",
6785                                          offsetof(FieldDesc, m_dword1),
6786                                          fieldsize(FieldDesc, m_dword1),
6787                                          fd->m_prot, (const WCHAR *)buf );
6788     }
6789     m_display->WriteFieldFlag( "m_requiresFullMbValue",
6790                                offsetof(FieldDesc, m_dword1),
6791                                fieldsize(FieldDesc, m_dword1),
6792                                fd->m_requiresFullMbValue );
6793     m_display->WriteFieldInt( "m_dwOffset",
6794                               offsetof(FieldDesc, m_dword2),
6795                               fieldsize(FieldDesc, m_dword2),
6796                               fd->m_dwOffset );
6797     DoWriteFieldCorElementType( "m_type",
6798                                 offsetof(FieldDesc, m_dword2),
6799                                 fieldsize(FieldDesc, m_dword2),
6800                                 (CorElementType)fd->m_type );
6801 #ifdef _DEBUG
6802     WriteFieldStr( m_debugName, PTR_BYTE(TO_TADDR(fd->m_debugName)),
6803                    FieldDesc, ALWAYS );
6804 #endif
6805     DisplayEndStructure( ALWAYS ); //name
6806 }
6807
6808 #ifdef _PREFAST_
6809 #pragma warning(push)
6810 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
6811 #endif
6812 void
6813 NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, 
6814                                     PTR_Module module )
6815 {
6816     _ASSERTE(NULL != mt);
6817     TADDR start, end;
6818     bool haveCompleteExtents = true;
6819     PTR_EEClass clazz = NULL;
6820     if( !mt->IsCanonicalMethodTable() && CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt->GetCanonicalMethodTable())) )
6821     {
6822         /* REVISIT_TODO Wed 02/01/2006
6823          * GetExtent requires the class in order to compute GetInstAndDictSize.
6824          * If the EEClass isn't present, I cannot compute the size.  If we are
6825          * in this case, skip all of the generic dictionaries.
6826          */
6827         haveCompleteExtents = false;
6828         TempBuffer buf;
6829         MethodTableToString( mt, buf );
6830         m_display->ErrorPrintF( "WARNING! MethodTable %S is generic but is not hard bound to its EEClass.  Cannot compute generic dictionary sizes.\n", (const WCHAR *)buf );
6831     }
6832     else if( !m_isMscorlibHardBound )
6833     {
6834         /* REVISIT_TODO Mon 8/20/2007
6835          * If we're not hard bound to mscorlib, most things don't work.  They depend on knowing what
6836          * g_pObjectClass is.  Without the hard binding to mscorlib, I can't figure that out.
6837          */
6838         haveCompleteExtents = false;
6839     }
6840     if( haveCompleteExtents )
6841     {
6842         mt->GetSavedExtent(&start, &end);
6843         clazz = mt->GetClass();
6844     }
6845     else
6846     {
6847         start = PTR_TO_TADDR(mt);
6848         end = start + sizeof(*mt);
6849     }
6850     IF_OPT(METHODTABLES)
6851     {
6852         m_display->StartStructureWithNegSpace( name, DPtrToPreferredAddr(mt),
6853                                                DataPtrToDisplay(start), end - start );
6854     }
6855
6856     IF_OPT(METHODTABLES)
6857     {
6858         {
6859             TempBuffer buf;
6860             MethodTableToString( mt, buf );
6861             DisplayWriteElementStringW( "Name", (const WCHAR *)buf, ALWAYS );
6862         }
6863         if( mt->ContainsPointers() )
6864         {
6865             PTR_CGCDesc cgc = CGCDesc::GetCGCDescFromMT(mt);
6866             unsigned size = (unsigned)cgc->GetSize();
6867             /* REVISIT_TODO Tue 12/13/2005
6868              * Does anyone actually care about what's inside here?
6869              */
6870             m_display->WriteFieldEmpty( "CGCDesc", ~size + 1, size );
6871         }
6872     }
6873
6874     /* XXX Mon 10/24/2005
6875      * The MT might have a component size as the low WORD of the m_dwFlags
6876      * field, if it doesn't then that field instead represents a number of
6877      * flags, which we know as the "low flags"
6878      */
6879     if (mt->HasComponentSize())
6880     {
6881         DisplayWriteElementInt( "ComponentSize", mt->RawGetComponentSize(),
6882                                 METHODTABLES );
6883     }
6884     else
6885     {
6886         DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & 0xFFFF, MethodTable,
6887                                      s_MTFlagsLow, W(", "), METHODTABLES );
6888     }
6889
6890     /* XXX Fri 10/07/2005
6891      * The low WORD of the flags is used for either a component size or flags
6892      * (see above), the high WORD is always flags. If this changes then this
6893      * might be busted.
6894      */
6895     DisplayWriteFieldEnumerated( m_dwFlags, mt->m_dwFlags & ~0xFFFF, MethodTable,
6896                                  s_MTFlagsHigh, W(", "), METHODTABLES );
6897
6898     DisplayWriteFieldInt( m_BaseSize, mt->m_BaseSize, MethodTable,
6899                           METHODTABLES );
6900
6901     DisplayWriteFieldEnumerated( m_wFlags2, mt->m_wFlags2, MethodTable,
6902                                  s_MTFlags2, W(", "), METHODTABLES );
6903
6904     DisplayWriteFieldInt( m_wToken, mt->m_wToken, MethodTable,
6905                           METHODTABLES );
6906     DisplayWriteFieldInt( m_wNumVirtuals, mt->m_wNumVirtuals, MethodTable,
6907                           METHODTABLES );
6908     DisplayWriteFieldInt( m_wNumInterfaces, mt->m_wNumInterfaces, MethodTable,
6909                           METHODTABLES );
6910
6911
6912
6913     PTR_MethodTable parent = ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent());
6914     if( parent == NULL )
6915     {
6916         DisplayWriteFieldPointer( m_pParentMethodTable, NULL, MethodTable,
6917                                   METHODTABLES );
6918     }
6919     else
6920     {
6921         IF_OPT(METHODTABLES)
6922         {
6923             DoWriteFieldMethodTable( "m_pParentMethodTable",
6924                                      offsetof(MethodTable, m_pParentMethodTable), 
6925                                      fieldsize(MethodTable, m_pParentMethodTable), 
6926                                      mt->GetParentMethodTable() );
6927         }
6928     }
6929     DisplayWriteFieldPointer( m_pLoaderModule,
6930                               DPtrToPreferredAddr(mt->GetLoaderModule()),
6931                               MethodTable, METHODTABLES );
6932
6933     PTR_MethodTableWriteableData wd = ReadPointer((MethodTable *)mt, &MethodTable::m_pWriteableData);
6934     _ASSERTE(wd != NULL);
6935     DisplayStartStructureWithOffset( m_pWriteableData, DPtrToPreferredAddr(wd),
6936                                      sizeof(*wd), MethodTable, METHODTABLES );
6937     DisplayWriteFieldEnumerated( m_dwFlags, wd->m_dwFlags,
6938                                  MethodTableWriteableData, s_WriteableMTFlags,
6939                                  W(", "), METHODTABLES );
6940     DisplayWriteFieldPointer( m_hExposedClassObject,
6941                               DataPtrToDisplay(wd->m_hExposedClassObject),
6942                               MethodTableWriteableData, METHODTABLES );
6943     _ASSERTE(wd->m_hExposedClassObject == 0);
6944     DisplayEndStructure( METHODTABLES ); //m_pWriteableData
6945
6946     if( !mt->IsCanonicalMethodTable() )
6947     {
6948         WriteFieldMethodTable( m_pCanonMT, mt->GetCanonicalMethodTable(),
6949                                MethodTable, METHODTABLES );
6950     }
6951     else
6952     {
6953         DisplayWriteFieldPointer( m_pEEClass, DPtrToPreferredAddr(mt->GetClass()),
6954                                   MethodTable, METHODTABLES );
6955     }
6956
6957     if( mt->IsArray() )
6958     {
6959         WriteFieldTypeHandle( m_ElementTypeHnd,
6960                               mt->GetApproxArrayElementTypeHandle(),
6961                               MethodTable, METHODTABLES );
6962     }
6963
6964     if( mt->HasPerInstInfo() && haveCompleteExtents )
6965     {
6966         //print out the generics dictionary info, and then print out
6967         //the contents of those dictionaries.
6968         PTR_GenericsDictInfo di = mt->GetGenericsDictInfo();
6969         _ASSERTE(NULL != di);
6970
6971         DisplayStartStructure("GenericsDictInfo", DPtrToPreferredAddr(di), sizeof(*di), METHODTABLES);
6972
6973         DisplayWriteFieldInt( m_wNumDicts, di->m_wNumDicts, GenericsDictInfo,
6974                                 METHODTABLES );
6975         DisplayWriteFieldInt( m_wNumTyPars, di->m_wNumTyPars,
6976                                 GenericsDictInfo, METHODTABLES);
6977         DisplayEndStructure( METHODTABLES ); //GenericsDictInfo
6978
6979         DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo();
6980
6981         DisplayStartStructure( "PerInstInfo",
6982                                DPtrToPreferredAddr(perInstInfo),
6983                                mt->GetPerInstInfoSize(),
6984                                METHODTABLES );
6985         /* XXX Tue 10/11/2005
6986          * Only dump this type's dictionary, rather than the inherited
6987          * dictionaries. (there are multiple entries in m_pPerInstInfo, but
6988          * only print the last one, which is the one for this class).
6989          * cloned from Genericdict.cpp
6990          */
6991         PTR_Dictionary currentDictionary(mt->GetDictionary());
6992         if( currentDictionary != NULL )
6993         {
6994             PTR_DictionaryEntry entry(currentDictionary->EntryAddr(0));
6995             
6996             PTR_DictionaryLayout layout( clazz->GetDictionaryLayout() );
6997
6998             DisplayStartStructure( "Dictionary",
6999                                    DPtrToPreferredAddr(currentDictionary),
7000                                    //if there is a layout, use it to compute
7001                                    //the size, otherwise there is just the one
7002                                    //entry.
7003                                    DictionaryLayout::GetFirstDictionaryBucketSize(mt->GetNumGenericArgs(), layout),
7004                                    METHODTABLES );
7005
7006             DisplayStartArrayWithOffset( m_pEntries, NULL, Dictionary,
7007                                          METHODTABLES );
7008
7009             /* REVISIT_TODO Thu 12/15/2005
7010              * use VERBOSE_TYPES here.
7011              */
7012             _ASSERTE(CHECK_OPT(METHODTABLES));
7013
7014             //for each generic arg, there is a type handle slot
7015             for( unsigned i = 0; i < mt->GetNumGenericArgs(); ++i )
7016                 DumpDictionaryEntry("Entry", TypeHandleSlot, entry + i);
7017
7018             //now check for a layout.  If it is present, then there are more
7019             //entries.
7020             if( layout != NULL && (layout->GetNumUsedSlots() > 0) )
7021             {
7022                 unsigned numUsedSlots = layout->GetNumUsedSlots();
7023                 for( unsigned i = 0; i < numUsedSlots; ++i )
7024                 {
7025                     //DictionaryLayout::GetEntryLayout
7026                     PTR_DictionaryEntryLayout entryLayout(layout->GetEntryLayout(i));
7027
7028                     //Dictionary::GetSlotAddr
7029                     PTR_DictionaryEntry ent(currentDictionary->EntryAddr(mt->GetNumGenericArgs() + i));
7030
7031                     DumpDictionaryEntry( "Entry", entryLayout->GetKind(), ent );
7032                 }
7033             }
7034             if( layout != NULL )
7035             {
7036                 /* REVISIT_TODO Thu 12/15/2005
7037                  * Where is this data?
7038                  */
7039             }
7040             DisplayEndArray( "Total Per instance Info",
7041                              METHODTABLES ); //m_pEntries
7042             DisplayEndStructure( METHODTABLES ); //Dictionary
7043         }
7044         DisplayEndStructure( METHODTABLES ); //m_pPerInstInfo
7045     }
7046
7047 #ifdef _DEBUG
7048     WriteFieldStr( debug_m_szClassName,
7049                    PTR_BYTE(TO_TADDR(mt->debug_m_szClassName)), MethodTable,
7050                    METHODTABLES );
7051 #if 0 //already dumping the optional member
7052     PTR_InterfaceInfo imap( TO_TADDR(mt->m_pIMapDEBUG) );
7053     /* REVISIT_TODO Mon 10/24/2005
7054      * Dump interface map
7055      */
7056     DisplayStartArrayWithOffset( m_pIMapDEBUG, NULL, MethodTable,
7057                                  METHODTABLES );
7058     DisplayEndArray( "Total Interfaces", METHODTABLES );
7059 #endif
7060 #endif
7061
7062     if( mt->HasDispatchMapSlot() )
7063     {
7064         PTR_DispatchMap dispatchMap(mt->GetDispatchMap());
7065
7066         DisplayStartStructure( "DispatchMap",
7067                                DPtrToPreferredAddr(dispatchMap),
7068                                DispatchMap::GetObjectSize(dispatchMap->GetMapSize()),
7069                                METHODTABLES );
7070
7071         IF_OPT(VERBOSE_TYPES )
7072         {
7073             DispatchMap::Iterator iter(mt);
7074             DisplayStartArray( "DispatchMap", NULL, VERBOSE_TYPES );
7075             while( iter.Next() )
7076             {
7077                 DispatchMapEntry * ent = iter.Entry();
7078
7079                 DisplayStartElement( "Entry", METHODTABLES );
7080                 DisplayStartVStructure( "TypeID", METHODTABLES );
7081                 DispatchMapTypeID typeID = ent->GetTypeID();
7082                 if( typeID.IsThisClass() )
7083                     DisplayWriteElementFlag("IsThisClass", true, METHODTABLES );
7084                 else if( typeID.IsImplementedInterface() )
7085                 {
7086                     DisplayWriteElementFlag( "IsImplementedInterface",
7087                                              true, METHODTABLES );
7088                     DisplayWriteElementInt( "GetInterfaceNum",
7089                                             typeID.GetInterfaceNum(), METHODTABLES );
7090                 }
7091                 DisplayEndStructure( METHODTABLES ); //TypeID
7092                 m_display->WriteElementInt( "SlotNumber",
7093                                             ent->GetSlotNumber() );
7094                 DisplayWriteElementInt( "TargetSlotNumber",
7095                                         ent->GetSlotNumber(), METHODTABLES );
7096
7097                 m_display->EndElement(); //Entry
7098             }
7099             //DispatchMap
7100             DisplayEndArray("Total Dispatch Map Entries", METHODTABLES );
7101         }
7102         else
7103         {
7104             CoverageRead(PTR_TO_TADDR(dispatchMap),
7105                          DispatchMap::GetObjectSize(dispatchMap->GetMapSize()));
7106         }
7107
7108         DisplayEndStructure( METHODTABLES ); //DispatchMap
7109     }
7110
7111     IF_OPT( METHODTABLES )
7112     {
7113         m_display->StartStructureWithOffset("Vtable",
7114                                             mt->GetVtableOffset(),
7115                                             mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t),
7116                                             DataPtrToDisplay(PTR_TO_TADDR(mt) + mt->GetVtableOffset()),
7117                                             mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t));
7118
7119
7120         MethodTable::VtableIndirectionSlotIterator itIndirect = mt->IterateVtableIndirectionSlots();
7121         while (itIndirect.Next())
7122         {
7123             SlotChunk sc;
7124             sc.addr = dac_cast<TADDR>(itIndirect.GetIndirectionSlot());
7125             sc.nSlots = (WORD)itIndirect.GetNumSlots();
7126             sc.isRelative = MethodTable::VTableIndir2_t::isRelative;
7127             m_discoveredSlotChunks.AppendEx(sc);
7128         }
7129
7130         IF_OPT(VERBOSE_TYPES)
7131         {
7132             DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7133             for( unsigned i = 0; i < mt->GetNumVtableIndirections(); ++i )
7134             {
7135                 DisplayStartElement( "Slot", ALWAYS );
7136                 DisplayWriteElementInt( "Index", i, ALWAYS );
7137                 TADDR base = dac_cast<TADDR>(&(mt->GetVtableIndirections()[i]));
7138                 DPTR(MethodTable::VTableIndir2_t) tgt = MethodTable::VTableIndir_t::GetValueMaybeNullAtPtr(base);
7139                 DisplayWriteElementPointer( "Pointer",
7140                                             DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7141                                             ALWAYS );
7142                 DisplayWriteElementString( "Type", "chunk indirection",
7143                                            ALWAYS );
7144                 DisplayEndElement( ALWAYS ); //Slot
7145             }
7146
7147             if (mt->HasNonVirtualSlotsArray())
7148             {
7149                 DisplayStartElement( "Slot", ALWAYS );
7150                 DisplayWriteElementInt( "Index", -1, ALWAYS );
7151                 PTR_PCODE tgt = mt->GetNonVirtualSlotsArray();
7152                 DisplayWriteElementPointer( "Pointer",
7153                                             DataPtrToDisplay(dac_cast<TADDR>(tgt)),
7154                                             ALWAYS );
7155                 DisplayWriteElementString( "Type", "non-virtual chunk indirection",
7156                                            ALWAYS );
7157                 DisplayEndElement( ALWAYS ); //Slot
7158
7159                 SlotChunk sc;
7160                 sc.addr = dac_cast<TADDR>(tgt);
7161                 sc.nSlots = (mt->GetNumVtableSlots() - mt->GetNumVirtuals());
7162                 sc.isRelative = false;
7163                 m_discoveredSlotChunks.AppendEx(sc);
7164             } 
7165             else if (mt->HasSingleNonVirtualSlot())
7166             {
7167                 DumpSlot((unsigned)-1, mt->GetSlot(mt->GetNumVirtuals()));
7168             }
7169
7170             DisplayEndList( ALWAYS ); //vtable
7171         }
7172         else
7173         {
7174             CoverageRead( PTR_TO_TADDR(mt) + mt->GetVtableOffset(),
7175                           mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t) );
7176
7177             if (mt->HasNonVirtualSlotsArray())
7178             {
7179                 CoverageRead( PTR_TO_TADDR(mt->GetNonVirtualSlotsArray()),
7180                               mt->GetNonVirtualSlotsArraySize() );
7181             }
7182             
7183         }
7184         DisplayEndStructure(ALWAYS); //Vtable
7185     }
7186
7187     if( mt->HasInterfaceMap() && CHECK_OPT(METHODTABLES) )
7188     {
7189         PTR_InterfaceInfo ifMap = mt->GetInterfaceMap();
7190         m_display->StartArrayWithOffset( "InterfaceMap",
7191                                          offsetof(MethodTable, m_pInterfaceMap),
7192                                          sizeof(void*),
7193                                          NULL );
7194         for( unsigned i = 0; i < mt->GetNumInterfaces(); ++i )
7195         {
7196             PTR_InterfaceInfo info = ifMap + i;
7197             DisplayStartStructure( "InterfaceInfo_t", DPtrToPreferredAddr(info),
7198                                    sizeof(*info), METHODTABLES );
7199             WriteFieldMethodTable( m_pMethodTable,
7200                                    info->GetMethodTable(),
7201                                    InterfaceInfo_t, METHODTABLES );
7202             DisplayEndStructure( METHODTABLES ); //InterfaceInfo_t
7203         }
7204         DisplayEndArray( "Total InterfaceInfos",
7205                          METHODTABLES ); //InterfaceMap
7206     }
7207
7208     //rest of the optional members
7209
7210     //GenericStatics comes after the generic dictionaries.  So if I
7211     //don't have extents, I can't print them.
7212     if( haveCompleteExtents &&
7213         mt->HasGenericsStaticsInfo() && 
7214         CHECK_OPT(METHODTABLES)
7215         )
7216     {
7217         PTR_GenericsStaticsInfo genStatics = mt->GetGenericsStaticsInfo();
7218         m_display->StartStructureWithOffset( "OptionalMember_"
7219                                                 "GenericsStaticsInfo",
7220                                              mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GenericsStaticsInfo),
7221                                              sizeof(*genStatics),
7222                                              DPtrToPreferredAddr(genStatics),
7223                                              sizeof(*genStatics) );
7224
7225         PTR_FieldDesc fieldDescs = ReadPointerMaybeNull((GenericsStaticsInfo *) genStatics, &GenericsStaticsInfo::m_pFieldDescs);
7226         if( fieldDescs == NULL )
7227         {
7228             DisplayWriteFieldPointer( m_pFieldDescs, NULL, GenericsStaticsInfo,
7229                                       ALWAYS );
7230         }
7231         else
7232         {
7233             DisplayStartArrayWithOffset( m_pFieldDescs, NULL,
7234                                          GenericsStaticsInfo, ALWAYS );
7235             _ASSERTE(clazz == GetClassFromMT(mt));
7236             for( int i = 0; i < clazz->GetNumStaticFields(); ++i )
7237             {
7238                 PTR_FieldDesc fd = fieldDescs + i;
7239                 DumpFieldDesc( fd, "FieldDesc" );
7240             }
7241             DisplayEndArray( "Total Static Fields", ALWAYS ); // m_pFieldDescs
7242         }
7243         DisplayWriteFieldUInt( m_DynamicTypeID, (DWORD)genStatics->m_DynamicTypeID,
7244                                GenericsStaticsInfo, METHODTABLES );
7245
7246         DisplayEndStructure( METHODTABLES );//OptionalMember_GenericsStaticsInfo
7247
7248     }
7249
7250 #ifdef FEATURE_COMINTEROP
7251     if (haveCompleteExtents &&
7252         mt->HasGuidInfo() &&
7253         CHECK_OPT(METHODTABLES)
7254         )
7255     {
7256         PTR_GuidInfo guidInfo(*mt->GetGuidInfoPtr());
7257
7258         if (guidInfo != NULL)
7259         {
7260             m_display->StartStructureWithOffset( "OptionalMember_GuidInfo",
7261                                                  mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_GuidInfo),
7262                                                  sizeof(void*),
7263                                                  DPtrToPreferredAddr(guidInfo),
7264                                                  sizeof(GuidInfo)
7265                                                  );
7266             TempBuffer buf;
7267             GuidToString( guidInfo->m_Guid, buf );
7268             DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
7269                                       ALWAYS );
7270             DisplayWriteFieldFlag( m_bGeneratedFromName,
7271                                    guidInfo->m_bGeneratedFromName,
7272                                    GuidInfo, ALWAYS );
7273             DisplayEndStructure( ALWAYS ); // OptionalMember_GuidInfo
7274         }
7275     }
7276
7277     if (haveCompleteExtents &&
7278         mt->HasCCWTemplate() 
7279         && CHECK_OPT(METHODTABLES)
7280         )
7281     {
7282         PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(*mt->GetCCWTemplatePtr()));
7283         m_display->WriteFieldPointer( "OptionalMember_CCWTemplate",
7284                                       mt->GetOffsetOfOptionalMember(MethodTable::OptionalMember_CCWTemplate),
7285                                       sizeof(void *),
7286                                       DPtrToPreferredAddr(ccwTemplate)
7287                                       );
7288     }
7289 #endif // FEATURE_COMINTEROP
7290
7291     DisplayEndStructure( METHODTABLES ); //MethodTable
7292 } // NativeImageDumper::DumpMethodTable
7293 #ifdef _PREFAST_
7294 #pragma warning(pop)
7295 #endif
7296
7297 void
7298 NativeImageDumper::DumpMethodTableSlotChunk( TADDR slotChunk, COUNT_T numSlots, bool isRelative )
7299 {
7300     IF_OPT( METHODTABLES )
7301     {
7302         COUNT_T slotsSize;
7303         if (isRelative)
7304         {
7305             slotsSize = numSlots * sizeof(RelativePointer<PCODE>);
7306         }
7307         else
7308         {
7309             slotsSize = numSlots * sizeof(PCODE);
7310         }
7311         DisplayStartStructure( "MethodTableSlotChunk", DataPtrToDisplay(slotChunk), slotsSize, METHODTABLES );
7312
7313         IF_OPT(VERBOSE_TYPES)
7314         {
7315             DisplayStartList( W("[%-4s]: %s (%s)"), ALWAYS );
7316             for( unsigned i = 0; i < numSlots; ++i )
7317             {
7318                 PCODE target;
7319                 if (isRelative)
7320                 {
7321                     target = RelativePointer<PCODE>::GetValueMaybeNullAtPtr(slotChunk + i * sizeof(RelativePointer<PCODE>));
7322                 }
7323                 else
7324                 {
7325                     target = dac_cast<PTR_PCODE>(slotChunk)[i];
7326                 }
7327
7328                 DumpSlot(i, target);
7329             }
7330             DisplayEndList( ALWAYS ); //Slot list
7331         }
7332         else
7333             CoverageRead( slotChunk, slotsSize );
7334         DisplayEndStructure(ALWAYS); //Slot chunk
7335     }
7336 }
7337
7338
7339 void
7340 NativeImageDumper::DumpSlot( unsigned index, PCODE tgt )
7341 {
7342     IF_OPT(VERBOSE_TYPES)
7343     {
7344         DisplayStartElement( "Slot", ALWAYS );
7345         DisplayWriteElementInt( "Index", index, ALWAYS );
7346         DisplayWriteElementPointer( "Pointer",
7347                                     DataPtrToDisplay(tgt),
7348                                     ALWAYS );
7349         if( !isInRange(TO_TADDR(tgt)) )
7350         {
7351             DisplayWriteElementString( "Type", "external",
7352                                        ALWAYS );
7353         }
7354         else if( isPrecode(TO_TADDR(tgt))
7355                            && Precode::IsValidType(PTR_Precode(TO_TADDR(tgt))->GetType()) )
7356         {
7357             PTR_Precode precode(TO_TADDR(tgt));
7358             DisplayWriteElementString( "Type", "precode",
7359                                        ALWAYS );
7360             //DumpPrecode( precode, module );
7361         }
7362         else
7363         {
7364             DisplayWriteElementString( "Type", "code pointer",
7365                                        ALWAYS );
7366         }
7367         DisplayEndElement( ALWAYS ); //Slot
7368     }
7369 }
7370
7371 NativeImageDumper::EnumMnemonics NativeImageDumper::s_SSMDExtendedFlags[] =
7372 {
7373 #define SSMD_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
7374     
7375 #define SSMD_ACCESS_ENTRY(x) NativeImageDumper::EnumMnemonics( x, mdMemberAccessMask, W(#x) )
7376     SSMD_ACCESS_ENTRY(mdPrivateScope),
7377     SSMD_ACCESS_ENTRY(mdPrivate),
7378     SSMD_ACCESS_ENTRY(mdFamANDAssem),
7379     SSMD_ACCESS_ENTRY(mdAssem),
7380     SSMD_ACCESS_ENTRY(mdFamily),
7381     SSMD_ACCESS_ENTRY(mdFamORAssem),
7382     SSMD_ACCESS_ENTRY(mdPublic),
7383 #undef SSMD_ACCESS_ENTRY
7384
7385     SSMD_ENTRY(mdStatic),
7386     SSMD_ENTRY(mdFinal),
7387     SSMD_ENTRY(mdVirtual),
7388     SSMD_ENTRY(mdHideBySig),
7389
7390     SSMD_ENTRY(mdVtableLayoutMask),
7391     SSMD_ENTRY(mdNewSlot),
7392
7393     SSMD_ENTRY(mdCheckAccessOnOverride),
7394     SSMD_ENTRY(mdAbstract),
7395     SSMD_ENTRY(mdSpecialName),
7396
7397     SSMD_ENTRY(mdPinvokeImpl),
7398     SSMD_ENTRY(mdUnmanagedExport),
7399
7400     SSMD_ENTRY(mdRTSpecialName),
7401     SSMD_ENTRY(mdHasSecurity),
7402     SSMD_ENTRY(mdRequireSecObject),
7403
7404     NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdILStub,
7405                                       W("nomdILStub") ),
7406     NativeImageDumper::EnumMnemonics( DynamicMethodDesc::nomdLCGMethod,
7407                                       W("nomdLCGMethod") ),
7408 #undef SSMD_ENTRY
7409 };
7410
7411 //maps MethodClassification to a name for a MethodDesc
7412 const char * const s_MDTypeName[] =
7413 {
7414     "MethodDesc", //mcIL
7415     "FCallMethodDesc", //mcFCall
7416     "NDirectMethodDesc", //mcNDirect
7417     "EEImplMethodDesc", //mcEEImpl - //public StoredSigMethodDesc
7418     "ArrayMethodDesc", //mcArray - //public StoredSigMethodDesc
7419     "InstantiatedMethodDesc", //mcInstantiated
7420 #if defined(FEATURE_COMINTEROP)
7421     "ComPlusCallMethodDesc", //mcComInterop
7422 #else
7423     "",
7424 #endif
7425     "DynamicMethodDesc", //mcDynamic -- //public StoredSigMethodDesc
7426 };
7427
7428 unsigned s_MDSizes[] =
7429 {
7430     sizeof(MethodDesc),                 //mcIL
7431     sizeof(FCallMethodDesc),            //mcFCall
7432     sizeof(NDirectMethodDesc),          //mcNDirect
7433     sizeof(EEImplMethodDesc),           //mcEEImpl
7434     sizeof(ArrayMethodDesc),            //mcArray
7435     sizeof(InstantiatedMethodDesc),     //mcInstantiated
7436 #if defined(FEATURE_COMINTEROP)
7437     sizeof(ComPlusCallMethodDesc),      //mcComInterop
7438 #else
7439     0,
7440 #endif
7441     sizeof(DynamicMethodDesc),          //mcDynamic
7442 };
7443
7444 static NativeImageDumper::EnumMnemonics g_NDirectFlags[] =
7445 {
7446 #define NDF_ENTRY(x) NativeImageDumper::EnumMnemonics( NDirectMethodDesc:: x, W(#x) )
7447         NDF_ENTRY(kEarlyBound),
7448         NDF_ENTRY(kHasSuppressUnmanagedCodeAccess),
7449         NDF_ENTRY(kIsMarshalingRequiredCached),
7450         NDF_ENTRY(kCachedMarshalingRequired),
7451         NDF_ENTRY(kNativeAnsi),
7452         NDF_ENTRY(kLastError),
7453         NDF_ENTRY(kNativeNoMangle),
7454         NDF_ENTRY(kVarArgs),
7455         NDF_ENTRY(kStdCall),
7456         NDF_ENTRY(kThisCall),
7457         NDF_ENTRY(kIsQCall),
7458         NDF_ENTRY(kStdCallWithRetBuf),
7459 #undef NDF_ENTRY
7460 };
7461 NativeImageDumper::EnumMnemonics NativeImageDumper::s_IMDFlags[] =
7462 {
7463 #define IMD_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, W(#x) )
7464
7465 #define IMD_KIND_ENTRY(x) NativeImageDumper::EnumMnemonics( InstantiatedMethodDesc:: x, InstantiatedMethodDesc::KindMask, W(#x) )
7466         IMD_KIND_ENTRY(GenericMethodDefinition),
7467         IMD_KIND_ENTRY(UnsharedMethodInstantiation),
7468         IMD_KIND_ENTRY(SharedMethodInstantiation),
7469         IMD_KIND_ENTRY(WrapperStubWithInstantiations),
7470 #undef IMD_KIND_ENTRY
7471
7472 #ifdef EnC_SUPPORTED
7473         // Method is a new virtual function added through EditAndContinue.
7474         IMD_ENTRY(EnCAddedMethod),
7475 #endif // EnC_SUPPORTED
7476
7477         IMD_ENTRY(Unrestored),
7478
7479 #ifdef FEATURE_COMINTEROP
7480         IMD_ENTRY(HasComPlusCallInfo),
7481 #endif // FEATURE_COMINTEROP
7482
7483 #undef IMD_ENTRY
7484 };
7485
7486 void NativeImageDumper::DumpPrecode( PTR_Precode precode, PTR_Module module )
7487 {
7488     _ASSERTE(isPrecode(PTR_TO_TADDR(precode)));
7489
7490     PrecodeType pType = precode->GetType();
7491     switch(pType)
7492     {
7493 #define DISPLAY_PRECODE(type) \
7494         IF_OPT_AND(PRECODES, METHODDESCS)   \
7495         { \
7496             PTR_ ## type p( precode->As ## type () ); \
7497             DisplayStartStructure( # type, \
7498                                    DPtrToPreferredAddr(p), \
7499                                    sizeof(*p), ALWAYS ); \
7500             WriteFieldMethodDesc( m_pMethodDesc, \
7501                                   p->m_pMethodDesc, \
7502                                   type, ALWAYS ); \
7503             TADDR target = p->GetTarget(); \
7504             DisplayWriteElementPointer("Target",\
7505                                         DataPtrToDisplay(target),\
7506                                         ALWAYS );\
7507             DisplayEndStructure( ALWAYS ); \
7508         }
7509
7510     case PRECODE_STUB:
7511         DISPLAY_PRECODE(StubPrecode); break;
7512 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7513     case PRECODE_NDIRECT_IMPORT:
7514         DISPLAY_PRECODE(NDirectImportPrecode); break;
7515 #endif
7516 #ifdef HAS_FIXUP_PRECODE
7517     case PRECODE_FIXUP:
7518 #ifdef HAS_RELATIVE_FIXUP_PRECODE
7519         _ASSERTE(!"unreachable"); break;
7520 #else // HAS_RELATIVE_FIXUP_PRECODE
7521         IF_OPT_AND(PRECODES, METHODDESCS)
7522         {
7523             PTR_FixupPrecode p( precode->AsFixupPrecode() );
7524             DisplayStartStructure( "FixupPrecode",
7525                                    DPtrToPreferredAddr(p),
7526                                    sizeof(*p),
7527                                    ALWAYS );
7528             PTR_MethodDesc precodeMD(p->GetMethodDesc());
7529 #ifdef HAS_FIXUP_PRECODE_CHUNKS
7530             {
7531                 DisplayWriteFieldInt( m_MethodDescChunkIndex,
7532                                       p->m_MethodDescChunkIndex, FixupPrecode,
7533                                       ALWAYS );
7534                 DisplayWriteFieldInt( m_PrecodeChunkIndex,
7535                                       p->m_PrecodeChunkIndex, FixupPrecode,
7536                                       ALWAYS );
7537                 if( p->m_PrecodeChunkIndex == 0 )
7538                 {
7539                     //dump the location of the Base
7540                     DisplayWriteElementAddress( "PrecodeChunkBase",
7541                                                 DataPtrToDisplay(p->GetBase()),
7542                                                 sizeof(void*), ALWAYS );
7543                 }
7544                 //Make sure I align up if there is no code slot to make
7545                 //sure that I get the padding
7546                 TADDR mdPtrStart = p->GetBase()
7547                     + (p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
7548                 TADDR mdPtrEnd = ALIGN_UP( mdPtrStart + sizeof(MethodDesc*),
7549                                            8 );
7550                 CoverageRead( mdPtrStart, (ULONG32)(mdPtrEnd - mdPtrStart) );
7551                 TADDR precodeMDSlot = p->GetBase()
7552                     + p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT;
7553                 DoWriteFieldMethodDesc( "MethodDesc",
7554                                         (DWORD)(precodeMDSlot - PTR_TO_TADDR(p)),
7555                                         sizeof(TADDR), precodeMD );
7556             }
7557 #else //HAS_FIXUP_PRECODE_CHUNKS
7558             WriteFieldMethodDesc( m_pMethodDesc,
7559                                   p->m_pMethodDesc,
7560                                   FixupPrecode, ALWAYS );
7561 #endif //HAS_FIXUP_PRECODE_CHUNKS
7562             TADDR target = p->GetTarget();
7563             DisplayWriteElementPointer("Target",
7564                                         DataPtrToDisplay(target),
7565                                         ALWAYS );
7566             /* REVISIT_TODO Thu 01/05/2006
7567              * dump slot with offset if it is here
7568              */
7569             DisplayEndStructure( ALWAYS ); //FixupPrecode
7570         }
7571         break;
7572 #endif // HAS_RELATIVE_FIXUP_PRECODE
7573 #endif // HAS_FIXUP_PRECODE
7574 #ifdef HAS_RELATIVE_FIXUP_PRECODE
7575     case PRECODE_RELATIVE_FIXUP:
7576         IF_OPT_AND(PRECODES, METHODDESCS)
7577         {
7578             PTR_RelativeFixupPrecode p( precode->AsRelativeFixupPrecode() );
7579             DisplayStartStructure( "RelativeFixupPrecode",
7580                                    DPtrToPreferredAddr(p),
7581                                    sizeof(*p),
7582                                    ALWAYS );
7583             PTR_MethodDesc precodeMD(p->GetMethodDesc());
7584             {
7585                 DisplayWriteFieldInt( m_MethodDescChunkIndex,
7586                                       p->m_MethodDescChunkIndex, RelativeFixupPrecode,
7587                                       ALWAYS );
7588                 DisplayWriteFieldInt( m_PrecodeChunkIndex,
7589                                       p->m_PrecodeChunkIndex, RelativeFixupPrecode,
7590                                       ALWAYS );
7591                 if( p->m_PrecodeChunkIndex == 0 )
7592                 {
7593                     //dump the location of the Base
7594                     DisplayWriteElementAddress( "PrecodeChunkBase",
7595                                                 DataPtrToDisplay(p->GetBase()),
7596                                                 sizeof(void*), ALWAYS );
7597                 }
7598                 //Make sure I align up if there is no code slot to make
7599                 //sure that I get the padding
7600                 TADDR mdPtrStart = p->GetBase()
7601                     + (p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT);
7602                 TADDR mdPtrEnd = ALIGN_UP( mdPtrStart + sizeof(MethodDesc*),
7603                                            8 );
7604                 CoverageRead( mdPtrStart, (ULONG32)(mdPtrEnd - mdPtrStart) );
7605                 TADDR precodeMDSlot = p->GetBase()
7606                     + p->m_MethodDescChunkIndex * MethodDesc::ALIGNMENT;
7607                 DoWriteFieldMethodDesc( "MethodDesc",
7608                                         (DWORD)(precodeMDSlot - PTR_TO_TADDR(p)),
7609                                         sizeof(TADDR), precodeMD );
7610             }
7611             TADDR target = p->GetTarget();
7612             DisplayWriteElementPointer("Target",
7613                                         DataPtrToDisplay(target),
7614                                         ALWAYS );
7615             /* REVISIT_TODO Thu 01/05/2006
7616              * dump slot with offset if it is here
7617              */
7618             DisplayEndStructure( ALWAYS ); //RelativeFixupPrecode
7619         }
7620         break;
7621 #endif // HAS_RELATIVE_FIXUP_PRECODE
7622 #ifdef HAS_THISPTR_RETBUF_PRECODE
7623     case PRECODE_THISPTR_RETBUF:
7624         DISPLAY_PRECODE(ThisPtrRetBufPrecode); break;
7625 #endif
7626     default:
7627         _ASSERTE( !"Unsupported precode type" );
7628 #undef DISPLAY_PRECODE
7629 #undef PrecodeMDWrite
7630     }
7631 }
7632
7633 #ifdef _PREFAST_
7634 #pragma warning(push)
7635 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
7636 #endif
7637 void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module )
7638 {
7639     //StoredSigMethodDesc
7640
7641     MethodClassification mc =
7642         (MethodClassification)md->GetClassification();
7643     _ASSERTE(mc >= 0 && mc < mcCount);
7644     const char * mdTypeName = s_MDTypeName[mc];
7645     unsigned mdSize = (unsigned)md->SizeOf();
7646
7647     DisplayStartStructure( mdTypeName, DPtrToPreferredAddr(md),
7648                            mdSize, METHODDESCS );
7649     IF_OPT(METHODDESCS)
7650     {
7651         TempBuffer buf;
7652         MethodDescToString( md, buf );
7653         DisplayWriteElementStringW( "Name", (const WCHAR *)buf, METHODDESCS );
7654     }
7655 #ifdef _DEBUG
7656     IF_OPT(METHODDESCS)
7657     {
7658         WriteFieldStr(m_pszDebugMethodName,
7659                       PTR_BYTE(TO_TADDR(md->m_pszDebugMethodName)),
7660                       MethodDesc, METHODDESCS);
7661         WriteFieldStr(m_pszDebugClassName,
7662                       PTR_BYTE(TO_TADDR(md->m_pszDebugClassName)),
7663                       MethodDesc, METHODDESCS);
7664         WriteFieldStr(m_pszDebugMethodSignature,
7665                       PTR_BYTE(TO_TADDR(md->m_pszDebugMethodSignature)),
7666                       MethodDesc, METHODDESCS);
7667     }
7668     else
7669     {
7670         CoverageReadString(TO_TADDR(md->m_pszDebugMethodName));
7671         CoverageReadString(TO_TADDR(md->m_pszDebugClassName));
7672         CoverageReadString(TO_TADDR(md->m_pszDebugMethodSignature));
7673     }
7674 #endif
7675
7676     DisplayWriteFieldInt( m_wFlags3AndTokenRemainder, md->m_wFlags3AndTokenRemainder,
7677                           MethodDesc, METHODDESCS );
7678
7679     DisplayWriteFieldInt( m_chunkIndex, md->m_chunkIndex,
7680                           MethodDesc, METHODDESCS );
7681
7682     /* XXX Fri 03/24/2006
7683      * This is a workaround.  The InstantiatedMethodDescs are in chunks, but there's
7684      * no obvious place to display the chunk, so display the bounds here.
7685      */
7686     if( mc == mcInstantiated && md->m_chunkIndex == 0 )
7687     {
7688         PTR_MethodDescChunk chunk( md->GetMethodDescChunk() );
7689         DisplayWriteElementAddress( "MethodDescChunk", DPtrToPreferredAddr(chunk),
7690                                     chunk->SizeOf(), METHODDESCS );
7691     }
7692
7693     DisplayWriteFieldEnumerated( m_bFlags2, md->m_bFlags2, MethodDesc,
7694                                  s_MDFlag2, W(", "), METHODDESCS );
7695
7696     DisplayWriteFieldInt( m_wSlotNumber, md->GetSlot(), MethodDesc,
7697                           METHODDESCS );
7698     DisplayWriteFieldEnumerated( m_wFlags, md->m_wFlags, MethodDesc,
7699                                  s_MDC, W(", "), METHODDESCS );
7700
7701     IF_OPT(IL)
7702     {
7703         if( md->IsIL() )
7704         {
7705             PTR_MethodDescChunk chunk(md->GetMethodDescChunk());
7706             //chunk is implicitly remapped because it's calculated from the pointer
7707             //to MD.
7708             PTR_MethodTable mt = chunk->GetMethodTable();
7709             if( !CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
7710             {
7711                 if ( md->IsTypicalMethodDefinition() )
7712                 {
7713                     DWORD dwRVA = 0;
7714                     m_import->GetMethodProps(md->GetMemberDef(), NULL, NULL, NULL, 0,
7715                         NULL, NULL, NULL, &dwRVA, NULL);
7716
7717                     if (dwRVA != 0)
7718                     {
7719                         _ASSERTE(m_ILHostCopy);
7720                         _ASSERTE(m_ILSectionStart);
7721                         _ASSERTE(dwRVA >= m_ILSectionStart);
7722                         _ASSERTE(dwRVA < (m_ILSectionStart + m_ILSectionSize));
7723                         //The RVA is from the start of the file, so convert it
7724                         //to an RVA to the start of the .text section.
7725                         TADDR pILTarget = (TADDR)m_decoder.GetRvaData(dwRVA);
7726                         COR_ILMETHOD * pILHeader = (COR_ILMETHOD*)(m_ILHostCopy + dwRVA - m_ILSectionStart);
7727
7728                         COR_ILMETHOD_DECODER decoder(pILHeader);
7729
7730                         DisplayStartStructure( "IL",
7731                                        DataPtrToDisplay(pILTarget),
7732                                        PEDecoder::ComputeILMethodSize(pILTarget),
7733                                        ALWAYS );
7734
7735                         DisplayWriteElementInt( "CodeSize", decoder.GetCodeSize(), ALWAYS );
7736
7737                         // Dump the disassembled IL code?
7738
7739                         DisplayEndStructure( ALWAYS );
7740                     }
7741                 }
7742             }
7743         }
7744     }
7745     if( md->HasPrecode() )
7746     {
7747         PTR_Precode precode( md->GetPrecode() );
7748
7749         DumpPrecode( precode, module );
7750     }
7751     if ( md->HasNonVtableSlot() )
7752     {
7753         DisplayWriteElementInt( "Slot", (DWORD)(md->GetAddrOfSlot() - PTR_TO_TADDR(md)), ALWAYS);
7754     }
7755     if (md->HasNativeCodeSlot())
7756     {
7757         DisplayWriteElementInt( "NativeCode", DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)), ALWAYS);
7758         //m_display->WriteFieldPointer( "NativeCode",
7759         //                              DWORD(md->GetAddrOfNativeCodeSlot() - PTR_TO_TADDR(md)),
7760         //                              sizeof(TADDR),
7761         //                              md->GetNativeCode() );
7762     }
7763     if (md->HasMethodImplSlot())
7764     {
7765         DisplayStartVStructure( "MethodImpl", METHODDESCS );
7766         PTR_MethodImpl impl(md->GetMethodImpl());
7767         PTR_DWORD slots = impl->GetSlots() - 1;  // GetSlots returns the address of the first real slot (past the size)
7768         unsigned numSlots = impl->GetSize();
7769         _ASSERTE(!numSlots || numSlots == slots[0]);
7770         _ASSERTE(slots == NULL || isInRange(PTR_TO_TADDR(slots)));
7771         if ((slots != NULL) && isInRange(PTR_TO_TADDR(slots)))
7772         {
7773             DisplayWriteFieldAddress(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7774                                      (numSlots + 1) * sizeof(*slots),
7775                                      MethodImpl, METHODDESCS);
7776         }
7777         else
7778         {
7779             DisplayWriteFieldPointer(pdwSlots, DataPtrToDisplay(dac_cast<TADDR>(slots)),
7780                                      MethodImpl, METHODDESCS);
7781
7782         }
7783         _ASSERTE(impl->pImplementedMD.IsNull()
7784                  || isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())));
7785         if (!impl->pImplementedMD.IsNull() &&
7786             isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull())))
7787         {
7788             DisplayWriteFieldAddress( pImplementedMD,
7789                                       DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDsNonNull())),
7790                                       numSlots * sizeof(RelativePointer <MethodDesc*>),
7791                                       MethodImpl, METHODDESCS );
7792         }
7793         else
7794         {
7795             DisplayWriteFieldPointer( pImplementedMD,
7796                                       DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDs())),
7797                                       MethodImpl, METHODDESCS );
7798         }
7799         DisplayEndVStructure( METHODDESCS );
7800     }
7801     if (md->HasStoredSig())
7802     {
7803         DisplayStartVStructure( "StoredSigMethodDesc", METHODDESCS );
7804         PTR_StoredSigMethodDesc ssmd(md); 
7805         //display signature information.
7806         if( isInRange(ssmd->GetSigRVA()) )
7807         {
7808             DisplayWriteFieldAddress(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7809                                      ssmd->m_cSig, StoredSigMethodDesc,
7810                                      METHODDESCS);
7811         }
7812         else
7813         {
7814             DisplayWriteFieldPointer(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()),
7815                                      StoredSigMethodDesc, METHODDESCS);
7816
7817         }
7818         CoverageRead(TO_TADDR(ssmd->GetSigRVA()), ssmd->m_cSig);
7819         DisplayWriteFieldInt( m_cSig, ssmd->m_cSig,
7820                               StoredSigMethodDesc, METHODDESCS );
7821 #ifdef _WIN64
7822         DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7823                                      ssmd->m_dwExtendedFlags,
7824                                      StoredSigMethodDesc,
7825                                      s_SSMDExtendedFlags, W(", "),
7826                                      METHODDESCS );
7827 #endif
7828         DisplayEndVStructure( METHODDESCS ); //StoredSigMethodDesc
7829     }
7830     if( mc == mcDynamic )
7831     {
7832         PTR_DynamicMethodDesc dmd(md);
7833         DisplayStartVStructure( "DynamicMethodDesc", METHODDESCS );
7834         WriteFieldStr( m_pszMethodName, PTR_BYTE(dmd->GetMethodName()),
7835                        DynamicMethodDesc, METHODDESCS );
7836         if( !CHECK_OPT(METHODDESCS) )
7837             CoverageReadString( PTR_TO_TADDR(dmd->GetMethodName()) );
7838         DisplayWriteFieldPointer( m_pResolver,
7839                                   DPtrToPreferredAddr(dmd->m_pResolver),
7840                                   DynamicMethodDesc, METHODDESCS );
7841 #ifndef _WIN64
7842         DisplayWriteFieldEnumerated( m_dwExtendedFlags,
7843                                      dmd->m_dwExtendedFlags,
7844                                      DynamicMethodDesc,
7845                                      s_SSMDExtendedFlags, W(", "),
7846                                      METHODDESCS );
7847 #endif
7848         DisplayEndVStructure( METHODDESCS );
7849     }
7850     if (mc == mcFCall )
7851     {
7852         PTR_FCallMethodDesc fcmd(md);
7853         DisplayStartVStructure( "FCallMethodDesc", METHODDESCS );
7854
7855         DisplayWriteFieldInt( m_dwECallID,
7856                               fcmd->m_dwECallID,
7857                               FCallMethodDesc,
7858                               METHODDESCS );
7859
7860         DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7861     }
7862     if( mc == mcNDirect )
7863     {
7864         PTR_NDirectMethodDesc ndmd(md);
7865         DisplayStartVStructure( "NDirectMethodDesc", METHODDESCS );
7866         DPTR(NDirectMethodDesc::temp1) nd( PTR_HOST_MEMBER_TADDR(NDirectMethodDesc, ndmd, ndirect) );
7867         DisplayStartStructureWithOffset( ndirect,
7868                                          DPtrToPreferredAddr(nd),
7869                                          sizeof(*nd), NDirectMethodDesc,
7870                                          METHODDESCS );
7871         DisplayWriteFieldPointer( m_pNativeNDirectTarget,
7872                                   DataPtrToDisplay((TADDR)nd->m_pNativeNDirectTarget),
7873                                   NDirectMethodDesc::temp1,
7874                                   METHODDESCS );
7875         DisplayWriteFieldEnumerated( m_wFlags, nd->m_wFlags,
7876                                      NDirectMethodDesc::temp1,
7877                                      g_NDirectFlags, W(", "),
7878                                      METHODDESCS );
7879
7880         WriteFieldStr( m_pszEntrypointName,
7881                        PTR_BYTE(dac_cast<TADDR>(ndmd->GetEntrypointName())),
7882                        NDirectMethodDesc::temp1, METHODDESCS );
7883         if( !CHECK_OPT(METHODDESCS) )
7884             CoverageReadString(dac_cast<TADDR>(ndmd->GetEntrypointName()));
7885         if (md->IsQCall())
7886         {
7887             DisplayWriteFieldInt( m_dwECallID,
7888                                   nd->m_dwECallID,
7889                                   NDirectMethodDesc::temp1,
7890                                   METHODDESCS );
7891         }
7892         else
7893         {
7894             WriteFieldStr( m_pszLibName,
7895                            PTR_BYTE(dac_cast<TADDR>(ndmd->GetLibNameRaw())),
7896                            NDirectMethodDesc::temp1, METHODDESCS );
7897         }
7898         if( !CHECK_OPT(METHODDESCS) )
7899             CoverageReadString( dac_cast<TADDR>(ndmd->GetLibNameRaw()) );
7900
7901         PTR_NDirectWriteableData wnd( ndmd->GetWriteableData() );
7902         DisplayStartStructureWithOffset( m_pWriteableData,
7903                                          DPtrToPreferredAddr(wnd),
7904                                          sizeof(*wnd),
7905                                          NDirectMethodDesc::temp1,
7906                                          METHODDESCS );
7907         DisplayWriteFieldPointer( m_pNDirectTarget,
7908                                   DataPtrToDisplay((TADDR)wnd->m_pNDirectTarget), NDirectWriteableData, METHODDESCS );
7909         if( !CHECK_OPT(METHODDESCS) )
7910             CoverageRead( PTR_TO_TADDR(wnd), sizeof(*wnd) );
7911         DisplayEndStructure( METHODDESCS ); //m_pWriteableData
7912
7913         PTR_NDirectImportThunkGlue glue(ndmd->GetNDirectImportThunkGlue());
7914
7915 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7916         if (glue == NULL)
7917         {
7918             // import thunk glue is not needed for P/Invoke that is not inlinable
7919             DisplayWriteFieldPointer( m_pImportThunkGlue,
7920                                       NULL,
7921                                       NDirectMethodDesc::temp1,
7922                                       METHODDESCS );
7923         }
7924         else
7925         {
7926             DisplayStartStructureWithOffset( m_pImportThunkGlue,
7927                                              DPtrToPreferredAddr(glue),
7928                                              sizeof(*glue),
7929                                              NDirectMethodDesc::temp1,
7930                                              METHODDESCS);
7931 #else
7932             DisplayStartStructureWithOffset( m_ImportThunkGlue,
7933                                              DPtrToPreferredAddr(glue),
7934                                              sizeof(*glue),
7935                                              NDirectMethodDesc::temp1,
7936                                              METHODDESCS);
7937 #endif
7938 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7939             /* REVISIT_TODO Thu 01/05/2006
7940              * Dump this properly as a precode
7941              */
7942             WriteFieldMethodDesc( m_pMethodDesc, glue->m_pMethodDesc,
7943                                   NDirectImportThunkGlue, METHODDESCS );
7944             {
7945                 PTR_Precode p(glue);
7946                 DumpPrecode( p, module );
7947             }
7948             if( !CHECK_OPT(METHODDESCS) )
7949                 CoverageRead(PTR_TO_TADDR(glue), sizeof(*glue));
7950             /* REVISIT_TODO Fri 12/16/2005
7951              * Factor out this code into some shared precode dumping code
7952              */
7953 #else //!HAS_NDIRECT_IMPORT_PRECODE
7954             /* REVISIT_TODO Fri 10/27/2006
7955              * For Whidbey AMD64 (!HAS_NDIRECT_IMPORT_PRECODE), I don't have this data structure in the output.
7956              */
7957 #endif //HAS_NDIRECT_IMPORT_PRECODE
7958
7959             DisplayEndStructure( METHODDESCS ); //m_pImportThunkGlue
7960 #ifdef HAS_NDIRECT_IMPORT_PRECODE
7961         }
7962 #endif
7963
7964 #ifdef _TARGET_X86_
7965         DisplayWriteFieldInt( m_cbStackArgumentSize,
7966                               nd->m_cbStackArgumentSize,
7967                               NDirectMethodDesc::temp1, METHODDESCS );
7968 #endif
7969
7970         WriteFieldMethodDesc( m_pStubMD,
7971                               nd->m_pStubMD.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc::temp1, nd, m_pStubMD)),
7972                               NDirectMethodDesc::temp1, METHODDESCS );
7973
7974         DisplayEndStructure( METHODDESCS ); //ndirect
7975
7976
7977         DisplayEndVStructure( METHODDESCS ); //NDirectMethodDesc
7978     }
7979     if( mc == mcEEImpl )
7980     {
7981         DisplayStartVStructure( "EEImplMethodDesc", METHODDESCS );
7982         DisplayEndVStructure( METHODDESCS );
7983     }
7984 #if defined(FEATURE_COMINTEROP)
7985     if( mc == mcComInterop )
7986     {
7987         PTR_ComPlusCallMethodDesc cpmd(md);
7988         DisplayStartVStructure( "ComPlusCallMethodDesc", METHODDESCS );
7989         PTR_ComPlusCallInfo compluscall((TADDR)cpmd->m_pComPlusCallInfo);
7990
7991         if (compluscall == NULL)
7992         {
7993             DisplayWriteFieldPointer( m_pComPlusCallInfo,
7994                                       NULL,
7995                                       ComPlusCallMethodDesc,
7996                                       METHODDESCS );
7997         }
7998         else
7999         {
8000             DumpComPlusCallInfo( compluscall, METHODDESCS );
8001         }
8002
8003         DisplayEndVStructure( METHODDESCS ); //ComPlusCallMethodDesc
8004     }
8005 #endif
8006     if( mc == mcInstantiated )
8007     {
8008         PTR_InstantiatedMethodDesc imd(md);
8009         DisplayStartVStructure( "InstantiatedMethodDesc", METHODDESCS );
8010         unsigned kind = imd->m_wFlags2
8011             & InstantiatedMethodDesc::KindMask;
8012         if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
8013         {
8014             PTR_DictionaryLayout layout(dac_cast<TADDR>(imd->GetDictLayoutRaw()));
8015             IF_OPT(METHODDESCS)
8016             {
8017                 WriteFieldDictionaryLayout( "m_pDictLayout",
8018                                             offsetof(InstantiatedMethodDesc, m_pDictLayout ),
8019                                             fieldsize(InstantiatedMethodDesc, m_pDictLayout),
8020                                             layout,
8021                                             GetDependencyFromMD(md)->pImport );
8022             }
8023             else
8024             {
8025                 while( layout != NULL )
8026                 {
8027                     CoverageRead( PTR_TO_TADDR(layout),
8028                                   sizeof(DictionaryLayout)
8029                                   + sizeof(DictionaryEntryLayout)
8030                                   * (layout->m_numSlots - 1) );
8031                     layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
8032                 }
8033             }
8034         }
8035         else if( kind ==
8036                  InstantiatedMethodDesc::WrapperStubWithInstantiations )
8037         {
8038             PTR_MethodDesc wimd(imd->IMD_GetWrappedMethodDesc());
8039             if( wimd == NULL || !DoWriteFieldAsFixup( "m_pWrappedMethodDesc",
8040                                                       offsetof(InstantiatedMethodDesc, m_pWrappedMethodDesc),
8041                                                       fieldsize(InstantiatedMethodDesc, m_pWrappedMethodDesc),
8042                                                       PTR_TO_TADDR(wimd) ) )
8043             {
8044                 WriteFieldMethodDesc( m_pWrappedMethodDesc, wimd,
8045                                       InstantiatedMethodDesc, METHODDESCS );
8046             }
8047         }
8048         else
8049         {
8050             _ASSERTE(imd->m_pDictLayout.IsNull());
8051             DisplayWriteFieldPointer( m_pDictLayout, NULL,
8052                                       InstantiatedMethodDesc,
8053                                       METHODDESCS );
8054         }
8055         //now handle the contents of the m_pMethInst/m_pPerInstInfo union.
8056         unsigned numSlots = imd->m_wNumGenericArgs;
8057         PTR_Dictionary inst(imd->IMD_GetMethodDictionary());
8058         unsigned dictSize;
8059         if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
8060         {
8061             dictSize = sizeof(TypeHandle);
8062         }
8063         else if( kind == InstantiatedMethodDesc::WrapperStubWithInstantiations )
8064         {
8065             PTR_InstantiatedMethodDesc wrapped =
8066                 PTR_InstantiatedMethodDesc(imd->IMD_GetWrappedMethodDesc());
8067             if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(wrapped)) )
8068             {
8069                 /* XXX Mon 03/27/2006
8070                  * Note that 4 is the correct answer for all IMDs at this time.
8071                  */
8072                 TempBuffer buf;
8073                 MethodDescToString( md, buf );
8074                 //m_display->ErrorPrintF( "WARNING! InstantiatedMethodDesc %S wraps a MethodDesc that is a fixup.  I cannot accurately determine the size of the associated generic dictionary.  Assuming 4.\n", (const WCHAR *)buf );
8075                 dictSize = (imd->GetNumGenericMethodArgs() + 4) * sizeof(void*);
8076             }
8077             else
8078             {
8079                 PTR_DictionaryLayout layout(wrapped->IsSharedByGenericMethodInstantiations()
8080                                             ? dac_cast<TADDR>(wrapped->GetDictLayoutRaw()) : NULL );
8081                 dictSize = DictionaryLayout::GetFirstDictionaryBucketSize(imd->GetNumGenericMethodArgs(), 
8082                                                                           layout);
8083             }
8084         }
8085         else
8086         {
8087             dictSize = sizeof(TypeHandle);
8088         }
8089         //instantiations has the number of slots of
8090         //GetNumGenericMethodArgs.
8091         if( inst == NULL )
8092         {
8093             m_display->WriteFieldPointer( "m_pPerInstInfo",
8094                                           offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8095                                           fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8096                                           NULL );
8097         }
8098         else
8099         {
8100             IF_OPT(METHODDESCS)
8101             {
8102
8103                 m_display->StartStructureWithOffset( "m_pPerInstInfo",
8104                                                      offsetof(InstantiatedMethodDesc, m_pPerInstInfo),
8105                                                      fieldsize(InstantiatedMethodDesc, m_pPerInstInfo),
8106                                                      DPtrToPreferredAddr(inst),
8107                                                      dictSize );
8108             }
8109             DisplayStartArray( "InstantiationInfo", W("[%-2s]: %s"),
8110                                METHODDESCS );
8111             /* REVISIT_TODO Thu 03/23/2006
8112              * This doesn't dump the contents of the dictionary which are
8113              * hanging around after the real slots.  Get around to doing that.
8114              */
8115             for( unsigned i = 0; i < numSlots
8116                  && CHECK_OPT(METHODDESCS); ++i )
8117             {
8118                 DisplayStartElement( "Handle", METHODDESCS );
8119                 DisplayWriteElementInt( "Index", i, METHODDESCS );
8120
8121                 TypeHandle thArg = inst->GetInstantiation()[i].GetValue();
8122                 IF_OPT(METHODDESCS)
8123                     WriteElementTypeHandle( "TypeHandle", thArg);
8124
8125                 /* XXX Fri 03/24/2006
8126                  * There is no really good home for TypeDescs, so I gotta check
8127                  * lots of places for them.
8128                  */
8129                 if( !CORCOMPILE_IS_POINTER_TAGGED(thArg.AsTAddr()) &&
8130                     thArg.IsTypeDesc() )
8131                 {
8132                     PTR_TypeDesc td(thArg.AsTypeDesc());
8133                     if( isInRange(PTR_TO_TADDR(td)) )
8134                     {
8135                         m_discoveredTypeDescs.AppendEx(td);
8136                     }
8137                 }
8138                 DisplayEndElement( METHODDESCS ); //Handle
8139             }
8140             //Instantiation Info
8141             DisplayEndArray( "Total TypeHandles", METHODDESCS );
8142
8143             DisplayEndVStructure(METHODDESCS); //m_pPerInstInfo;
8144             if( !CHECK_OPT(METHODDESCS) )
8145                 CoverageRead(PTR_TO_TADDR(inst), numSlots * sizeof(*inst));
8146         }
8147
8148         DisplayWriteFieldEnumerated( m_wFlags2, imd->m_wFlags2,
8149                                      InstantiatedMethodDesc, s_IMDFlags,
8150                                      W(", "), METHODDESCS );
8151         DisplayWriteFieldInt( m_wNumGenericArgs, imd->m_wNumGenericArgs,
8152                               InstantiatedMethodDesc, METHODDESCS );
8153
8154 #ifdef FEATURE_COMINTEROP
8155         if (imd->IMD_HasComPlusCallInfo())
8156         {
8157             PTR_ComPlusCallInfo compluscall = imd->IMD_GetComPlusCallInfo();
8158             DumpComPlusCallInfo( compluscall, METHODDESCS );
8159         }
8160 #endif // FEATURE_COMINTEROP
8161
8162         DisplayEndStructure( METHODDESCS );
8163     }
8164
8165     DisplayEndStructure( METHODDESCS ); //MethodDesc (mdTypeName)
8166     if( !CHECK_OPT(METHODDESCS) )
8167         CoverageRead( PTR_TO_TADDR(md), mdSize );
8168
8169 }
8170 #ifdef _PREFAST_
8171 #pragma warning(pop)
8172 #endif
8173
8174 NativeImageDumper::EnumMnemonics NativeImageDumper::s_EECLIFlags[] =
8175 {
8176 #define EECLI_FLAGS_ENTRY(x) NativeImageDumper::EnumMnemonics( EEClassLayoutInfo:: x, W(#x) )
8177     EECLI_FLAGS_ENTRY(e_BLITTABLE),
8178     EECLI_FLAGS_ENTRY(e_MANAGED_SEQUENTIAL),
8179     EECLI_FLAGS_ENTRY(e_ZERO_SIZED),
8180     EECLI_FLAGS_ENTRY(e_HAS_EXPLICIT_SIZE),
8181 #undef EECLI_FLAGS_ENTRY
8182 };
8183
8184
8185 #ifdef _PREFAST_
8186 #pragma warning(push)
8187 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
8188 #endif
8189 void 
8190 NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
8191 {
8192     PTR_EEClass clazz = mt->GetClass();
8193
8194     _ASSERTE(CHECK_OPT(EECLASSES));
8195     _ASSERTE(clazz != NULL);
8196     _ASSERTE(isInRange(PTR_TO_TADDR(clazz)));
8197
8198     const char * eeClassType;
8199
8200     if( clazz->HasLayout() )
8201         eeClassType = "LayoutEEClass";
8202     else if( mt->IsArray() )
8203         eeClassType = "ArrayClass";
8204     else if( clazz->IsDelegate() )
8205         eeClassType = "DelegateEEClass";
8206     else
8207         eeClassType = "EEClass";
8208
8209     DisplayStartStructure( eeClassType, DPtrToPreferredAddr(clazz), clazz->GetSize(),
8210                            EECLASSES );
8211     {
8212         TempBuffer buf;
8213         MethodTableToString( mt, buf );
8214         DisplayWriteElementStringW( "Name", (const WCHAR *)buf, EECLASSES );
8215     }
8216
8217     PTR_GuidInfo guidInfo = clazz->GetGuidInfo();
8218     if(guidInfo != NULL)
8219     {
8220         DisplayStartStructureWithOffset( m_pGuidInfo,
8221                                          DPtrToPreferredAddr(guidInfo),
8222                                          sizeof(*guidInfo), EEClass,
8223                                          EECLASSES );
8224         TempBuffer buf;
8225         GuidToString( guidInfo->m_Guid, buf );
8226         DisplayWriteFieldStringW( m_Guid, (const WCHAR *)buf, GuidInfo,
8227                                   EECLASSES );
8228         DisplayWriteFieldFlag( m_bGeneratedFromName,
8229                                guidInfo->m_bGeneratedFromName,
8230                                GuidInfo, EECLASSES );
8231         DisplayEndStructure( EECLASSES ); //guidinfo
8232     }
8233     else
8234     {
8235         /* XXX Fri 10/14/2005
8236          * if Clazz isn't an interface, m_pGuidInfo is undefined.
8237          */
8238         DisplayWriteFieldPointerAnnotated( m_pGuidInfo, PTR_TO_TADDR(guidInfo),
8239                                            W("Invalid"), EEClass, EECLASSES );
8240     }
8241
8242
8243 #ifdef _DEBUG
8244     WriteFieldStr( m_szDebugClassName,
8245                    PTR_BYTE(TO_TADDR(clazz->m_szDebugClassName)),
8246                    EEClass, EECLASSES );
8247     DisplayWriteFieldFlag( m_fDebuggingClass, clazz->m_fDebuggingClass,
8248                            EEClass, EECLASSES );
8249 #endif
8250
8251     WriteFieldMethodTable( m_pMethodTable, clazz->GetMethodTable(), EEClass,
8252                            EECLASSES );
8253
8254     WriteFieldCorElementType( m_NormType, (CorElementType)clazz->m_NormType,
8255                               EEClass, EECLASSES );
8256
8257     PTR_FieldDesc fdList = clazz->GetFieldDescList();
8258
8259     ULONG fieldCount = (ULONG)CountFields(mt);
8260     _ASSERTE((fdList == NULL) == (fieldCount == 0));
8261
8262     IF_OPT(EECLASSES)
8263     {
8264         m_display->StartStructureWithOffset( "m_pFieldDescList",
8265                                              offsetof(EEClass, m_pFieldDescList),
8266                                              fieldsize(EEClass, m_pFieldDescList),
8267                                              DPtrToPreferredAddr(fdList),
8268                                              fdList != NULL ? 
8269                                                 sizeof(*fdList) * fieldCount :
8270                                                 0 );
8271     }
8272     IF_OPT(VERBOSE_TYPES)
8273     {
8274         if( fdList != NULL )
8275         {
8276             DisplayStartArray( "FieldDescs", NULL, EECLASSES );
8277             for( SIZE_T i = 0; i < fieldCount; ++i )
8278             {
8279                 PTR_FieldDesc fd = fdList + i;
8280                 IF_OPT(EECLASSES)
8281                     DumpFieldDesc( fd, "FieldDesc" );
8282             }
8283             DisplayEndArray( "Total FieldDescs", EECLASSES ); //FieldDescs
8284         }
8285     }
8286     else if( (fdList != NULL) && CHECK_OPT(DEBUG_COVERAGE) )
8287     {
8288         for( SIZE_T i = 0; i < fieldCount; ++i )
8289         {
8290             PTR_FieldDesc fd = fdList + i;
8291 #ifdef _DEBUG
8292             if( fd != NULL && fd->m_debugName != NULL )
8293                 CoverageReadString( fd->m_debugName );
8294 #endif
8295         }
8296         CoverageRead( PTR_TO_TADDR(fdList), sizeof(*fdList) * fieldCount );
8297     }
8298
8299     DisplayEndStructure( EECLASSES ); //FieldDescList
8300
8301     DisplayWriteFieldEnumerated( m_dwAttrClass, clazz->GetAttrClass(),
8302                                  EEClass, s_CorTypeAttr, W(" "), EECLASSES );
8303     DisplayWriteFieldEnumerated( m_VMFlags, clazz->m_VMFlags, EEClass,
8304                                  s_VMFlags, W(", "), EECLASSES );
8305
8306     PTR_MethodDescChunk chunk = clazz->GetChunks();
8307
8308     DisplayStartArrayWithOffset( m_pChunks, NULL, EEClass, EECLASSES );
8309     while( chunk != NULL )
8310     {
8311         DisplayStartStructure( "MethodDescChunk",
8312                                DPtrToPreferredAddr(chunk),
8313                                chunk->SizeOf(), EECLASSES );
8314         _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(chunk->GetMethodTable())));
8315         PTR_MethodTable chunkMT = chunk->GetMethodTable();
8316         DisplayWriteFieldPointer( m_methodTable,
8317                                   DPtrToPreferredAddr(chunkMT),
8318                                   MethodDescChunk, EECLASSES );
8319         PTR_MethodDescChunk chunkNext = chunk->GetNextChunk();
8320         DisplayWriteFieldPointer( m_next,
8321                                   DPtrToPreferredAddr(chunkNext),
8322                                   MethodDescChunk, EECLASSES );
8323         DisplayWriteFieldInt( m_size, chunk->m_size, MethodDescChunk,
8324                               EECLASSES );
8325         DisplayWriteFieldInt( m_count, chunk->m_count, MethodDescChunk,
8326                               EECLASSES );
8327         DisplayWriteFieldInt( m_flagsAndTokenRange, chunk->m_flagsAndTokenRange, MethodDescChunk,
8328                               EECLASSES );
8329         /* XXX Wed 12/14/2005
8330          * Don't skip walking this array.  I need to make sure I touch the
8331          * precodes.
8332          */
8333         DisplayStartArray( "MethodDescs", NULL, METHODDESCS );
8334         PTR_MethodDesc md(chunk->GetFirstMethodDesc());
8335         while (md != NULL)
8336         {
8337             IF_OPT_OR(METHODDESCS, DEBUG_COVERAGE)
8338             {
8339                 PTR_Module module = mt->GetModule();
8340                 if(CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(module) )) 
8341                     DumpMethodDesc( md, PTR_Module((TADDR)0) );
8342                 else
8343                     DumpMethodDesc( md, module );
8344             }
8345
8346             // Check whether the next MethodDesc is within the bounds of the current chunks
8347             TADDR pNext = PTR_HOST_TO_TADDR(md) + md->SizeOf();
8348             TADDR pEnd = PTR_HOST_TO_TADDR(chunk) + chunk->SizeOf();
8349
8350             md = (pNext < pEnd) ? PTR_MethodDesc(pNext) : NULL;
8351         }
8352
8353         DisplayEndArray( "Total MethodDescs", METHODDESCS); //MethodDescs
8354
8355         chunk = chunk->GetNextChunk();
8356
8357         DisplayEndStructure( EECLASSES ); //MethodDescChunk
8358     }
8359
8360     DisplayEndArray( "Total MethodDescChunks", EECLASSES );
8361     /* REVISIT_TODO Fri 10/14/2005
8362      * Dump the class dependencies
8363      */
8364     //_ASSERTE(!clazz->m_classDependencies.TestAnyBit());
8365
8366     /* REVISIT_TODO Mon 10/24/2005
8367      * Create vstructure for union?
8368      */
8369     //decode union here
8370 #ifdef FEATURE_COMINTEROP
8371     if( clazz->IsBlittable() || clazz->HasLayout() )
8372     {
8373         DisplayWriteFieldInt(m_cbNativeSize, clazz->m_cbNativeSize, EEClass,
8374                              EECLASSES );
8375     }
8376     else if( clazz->IsInterface() )
8377     {
8378         DisplayWriteFieldPointer( m_ohDelegate,
8379                                   DataPtrToDisplay(clazz->m_ohDelegate),
8380                                   EEClass, EECLASSES );
8381     }
8382     else
8383     {
8384         static const WCHAR * ifnames[] ={W("Dual"),W("Vtable"),W("Dispatch")};
8385         m_display->WriteFieldEnumerated( "ComInterfaceType",
8386                                          offsetof(EEClass,
8387                                                   m_ComInterfaceType),
8388                                          fieldsize(EEClass,
8389                                                    m_ComInterfaceType),
8390                                          (int)clazz->m_ComInterfaceType,
8391                                          ifnames[(int)clazz->m_ComInterfaceType] );
8392     }
8393 #else
8394     DisplayWriteFieldInt( m_cbNativeSize, clazz->m_cbNativeSize,
8395                           EEClass, EECLASSES );
8396 #endif
8397
8398 #if defined(FEATURE_COMINTEROP)
8399     PTR_ComCallWrapperTemplate ccwTemplate(TO_TADDR(clazz->m_pccwTemplate));
8400     if( ccwTemplate != NULL )
8401     {
8402         DisplayWriteFieldPointer( m_pccwTemplate, NULL, EEClass,
8403                                   EECLASSES );
8404     }
8405     else
8406     {
8407         /* REVISIT_TODO Fri 10/14/2005
8408          * Dump CcwTemplate
8409          */
8410         DisplayWriteFieldPointer( m_pccwTemplate,
8411                                   DPtrToPreferredAddr(ccwTemplate), EEClass,
8412                                   EECLASSES );
8413     }
8414 #endif // defined(FEATURE_COMINTEROP)
8415
8416     //fields for classes that aren't just EEClasses.
8417     if( clazz->HasLayout() )
8418     {
8419         PTR_LayoutEEClass layoutClass(PTR_TO_TADDR(clazz));
8420         DisplayStartVStructure("LayoutEEClass", EECLASSES );
8421
8422         PTR_EEClassLayoutInfo eecli( PTR_HOST_MEMBER_TADDR( LayoutEEClass,
8423                                                             layoutClass,
8424                                                             m_LayoutInfo ) );
8425         DisplayStartStructureWithOffset( m_LayoutInfo,
8426                                          DPtrToPreferredAddr(eecli),
8427                                          sizeof(EEClassLayoutInfo),
8428                                          LayoutEEClass, EECLASSES );
8429         /* REVISIT_TODO Fri 10/14/2005
8430          * Dump EEClassLayoutInfo
8431          */
8432         DisplayWriteFieldInt( m_cbNativeSize, eecli->m_cbNativeSize,
8433                               EEClassLayoutInfo, VERBOSE_TYPES );
8434         DisplayWriteFieldInt( m_cbManagedSize, eecli->m_cbManagedSize,
8435                               EEClassLayoutInfo, VERBOSE_TYPES );
8436         DisplayWriteFieldInt( m_LargestAlignmentRequirementOfAllMembers,
8437                               eecli->m_LargestAlignmentRequirementOfAllMembers,
8438                               EEClassLayoutInfo, VERBOSE_TYPES );
8439         DisplayWriteFieldInt( m_ManagedLargestAlignmentRequirementOfAllMembers,
8440                               eecli->m_ManagedLargestAlignmentRequirementOfAllMembers,
8441                               EEClassLayoutInfo, VERBOSE_TYPES );
8442         DisplayWriteFieldEnumerated( m_bFlags, eecli->m_bFlags,
8443                                      EEClassLayoutInfo, s_EECLIFlags, W(", "),
8444                                      VERBOSE_TYPES );
8445         DisplayWriteFieldInt( m_numCTMFields, eecli->m_numCTMFields,
8446                               EEClassLayoutInfo, VERBOSE_TYPES );
8447         PTR_FieldMarshaler fmArray = eecli->GetFieldMarshalers();
8448         DisplayWriteFieldAddress( m_pFieldMarshalers,
8449                                   DPtrToPreferredAddr(fmArray),
8450                                   eecli->m_numCTMFields
8451                                   * MAXFIELDMARSHALERSIZE,
8452                                   EEClassLayoutInfo, VERBOSE_TYPES );
8453         /* REVISIT_TODO Wed 03/22/2006
8454          * Dump the various types of FieldMarshalers.
8455          */
8456 #if 0
8457         DisplayStartArrayWithOffset( m_pFieldMarshalers, NULL,
8458                                      EEClassLayoutInfo, VERBOSE_TYPES );
8459         for( unsigned i = 0; i < eecli->m_numCTMFields; ++i )
8460         {
8461             /* REVISIT_TODO Wed 03/22/2006
8462              * Try to display the type of the field marshaler in the future.
8463              */
8464             PTR_FieldMarshaler current = fmArray + i;
8465             DisplayStartStructure( "FieldMarshaler",
8466                                    DPtrToPreferredAddr(current),
8467                                    sizeof(*current), VERBOSE_TYPES );
8468             WriteFieldFieldDesc( m_pFD, PTR_FieldDesc(TO_TADDR(current->m_pFD)),
8469                                  FieldMarshaler, VERBOSE_TYPES );
8470             DisplayWriteFieldInt( m_dwExternalOffset,
8471                                   current->m_dwExternalOffset, FieldMarshaler,
8472                                   VERBOSE_TYPES );
8473             DisplayEndStructure( VERBOSE_TYPES ); //FieldMarshaler
8474         }
8475         
8476         DisplayEndArray( "Number of FieldMarshalers", VERBOSE_TYPES ); //m_pFieldMarshalers
8477 #endif
8478         
8479         DisplayEndStructure( EECLASSES ); //LayoutInfo
8480
8481         DisplayEndVStructure( EECLASSES ); //LayoutEEClass
8482     }
8483     else if( mt->IsArray() )
8484     {
8485         PTR_ArrayClass arrayClass(PTR_TO_TADDR(clazz));
8486         DisplayStartVStructure( "ArrayClass", EECLASSES);
8487         IF_OPT(EECLASSES)
8488         {
8489             m_display->WriteFieldInt( "m_rank", offsetof(ArrayClass, m_rank),
8490                                       fieldsize(ArrayClass, m_rank),
8491                                       arrayClass->GetRank() );
8492         }
8493         DoWriteFieldCorElementType( "m_ElementType",
8494                                     offsetof(ArrayClass, m_ElementType),
8495                                     fieldsize(ArrayClass, m_ElementType),
8496                                     arrayClass->GetArrayElementType() );
8497
8498         DisplayEndVStructure( EECLASSES ); //ArrayClass
8499     }
8500     else if( clazz->IsDelegate() )
8501     {
8502         PTR_DelegateEEClass delegateClass(PTR_TO_TADDR(clazz));
8503         DisplayStartVStructure( "DelegateEEClass", EECLASSES );
8504
8505         DumpFieldStub( m_pStaticCallStub, delegateClass->m_pStaticCallStub,
8506                        DelegateEEClass, EECLASSES );
8507         DumpFieldStub( m_pInstRetBuffCallStub,
8508                        delegateClass->m_pInstRetBuffCallStub,
8509                        DelegateEEClass, EECLASSES );
8510
8511         WriteFieldMethodDesc( m_pInvokeMethod,
8512                               delegateClass->GetInvokeMethod(),
8513                               DelegateEEClass, EECLASSES );
8514         DumpFieldStub( m_pMultiCastInvokeStub, 
8515                        delegateClass->m_pMultiCastInvokeStub,
8516                        DelegateEEClass, EECLASSES );
8517
8518         DPTR(UMThunkMarshInfo)
8519             umInfo(TO_TADDR(delegateClass->m_pUMThunkMarshInfo));
8520
8521         if( umInfo == NULL )
8522         {
8523             DisplayWriteFieldPointer( m_pUMThunkMarshInfo, NULL,
8524                                       DelegateEEClass, EECLASSES );
8525         }
8526         else
8527         {
8528             DisplayStartStructureWithOffset( m_pUMThunkMarshInfo,
8529                                              DPtrToPreferredAddr(umInfo),
8530                                              sizeof(*umInfo),
8531                                              DelegateEEClass, EECLASSES );
8532             /* REVISIT_TODO Fri 10/14/2005
8533              * DumpUMThunkMarshInfo
8534              */
8535             DisplayEndStructure( EECLASSES ); //UMThunkMarshInfo
8536         }
8537
8538         WriteFieldMethodDesc( m_pBeginInvokeMethod,
8539                               delegateClass->GetBeginInvokeMethod(),
8540                               DelegateEEClass, EECLASSES );
8541         WriteFieldMethodDesc( m_pEndInvokeMethod,
8542                               delegateClass->GetEndInvokeMethod(),
8543                               DelegateEEClass, EECLASSES );
8544         DisplayWriteFieldPointer( m_pMarshalStub, delegateClass->m_pMarshalStub,
8545                        DelegateEEClass, EECLASSES );
8546
8547         WriteFieldMethodDesc( m_pForwardStubMD,
8548                               PTR_MethodDesc(TO_TADDR(delegateClass->m_pForwardStubMD)),
8549                               DelegateEEClass, EECLASSES );
8550         WriteFieldMethodDesc( m_pReverseStubMD,
8551                               PTR_MethodDesc(TO_TADDR(delegateClass->m_pReverseStubMD)),
8552                               DelegateEEClass, EECLASSES );
8553
8554 #ifdef FEATURE_COMINTEROP
8555         DPTR(ComPlusCallInfo) compluscall((TADDR)delegateClass->m_pComPlusCallInfo);
8556         if (compluscall == NULL)
8557         {
8558             DisplayWriteFieldPointer( m_pComPlusCallInfo,
8559                                       NULL,
8560                                       DelegateEEClass,
8561                                       EECLASSES );
8562         }
8563         else
8564         {
8565             DumpComPlusCallInfo( compluscall, EECLASSES );
8566         }        
8567 #endif // FEATURE_COMINTEROP
8568
8569         DisplayEndVStructure( EECLASSES ); //DelegateEEClass
8570     }
8571
8572     DisplayEndStructure( EECLASSES ); //eeClassType
8573
8574     PTR_EEClassOptionalFields pClassOptional = clazz->GetOptionalFields();
8575     if (pClassOptional)
8576     {
8577         DisplayStartStructure( "EEClassOptionalFields", DPtrToPreferredAddr(pClassOptional), sizeof(EEClassOptionalFields),
8578                                EECLASSES );
8579
8580 #ifdef FEATURE_COMINTEROP
8581         PTR_SparseVTableMap sparseVTMap(TO_TADDR(pClassOptional->m_pSparseVTableMap));
8582         if( sparseVTMap == NULL )
8583         {
8584             DisplayWriteFieldPointer( m_pSparseVTableMap, NULL, EEClassOptionalFields,
8585                                       EECLASSES );
8586         }
8587         else
8588         {
8589             _ASSERTE( !"Untested code" );
8590             IF_OPT(EECLASSES)
8591             {
8592                 m_display->StartStructure( "m_SparseVTableMap",
8593                                            DPtrToPreferredAddr(sparseVTMap),
8594                                            sizeof(*sparseVTMap) );
8595             }
8596             _ASSERTE(sparseVTMap->m_MapList != NULL);
8597             PTR_SparseVTableMap_Entry mapList(TO_TADDR(sparseVTMap->m_MapList));
8598             DisplayStartArray( "m_MapList", NULL, EECLASSES );
8599             for( WORD i = 0; i < sparseVTMap->m_MapEntries; ++i )
8600             {
8601                 DisplayWriteFieldInt( m_Start, mapList[i].m_Start,
8602                                       SparseVTableMap::Entry, EECLASSES );
8603                 DisplayWriteFieldInt( m_Span, mapList[i].m_Span,
8604                                       SparseVTableMap::Entry, EECLASSES );
8605                 DisplayWriteFieldInt( m_Span, mapList[i].m_MapTo,
8606                                       SparseVTableMap::Entry, EECLASSES );
8607             }
8608
8609             DisplayEndArray( "Total Entries", EECLASSES ); //m_MapList
8610
8611             DisplayWriteFieldInt( m_MapEntries, sparseVTMap->m_MapEntries,
8612                                   SparseVTableMap, EECLASSES );
8613             DisplayWriteFieldInt( m_Allocated, sparseVTMap->m_Allocated,
8614                                   SparseVTableMap, EECLASSES );
8615             DisplayWriteFieldInt( m_LastUsed, sparseVTMap->m_LastUsed,
8616                                   SparseVTableMap, EECLASSES );
8617             DisplayWriteFieldInt( m_VTSlot, sparseVTMap->m_VTSlot,
8618                                   SparseVTableMap, EECLASSES );
8619             DisplayWriteFieldInt( m_MTSlot, sparseVTMap->m_MTSlot,
8620                                   SparseVTableMap, EECLASSES );
8621
8622             DisplayEndStructure( EECLASSES ); //SparseVTableMap
8623         }
8624
8625         WriteFieldTypeHandle( m_pCoClassForIntf, pClassOptional->m_pCoClassForIntf,
8626                               EEClassOptionalFields, EECLASSES );
8627
8628         PTR_ClassFactoryBase classFactory(TO_TADDR(pClassOptional->m_pClassFactory));
8629         if( classFactory != NULL )
8630         {
8631             DisplayWriteFieldPointer( m_pClassFactory, NULL, EEClassOptionalFields,
8632                                       EECLASSES );
8633         }
8634         else
8635         {
8636             /* REVISIT_TODO Fri 10/14/2005
8637              * Dump ComClassFactory
8638              */
8639             DisplayWriteFieldPointer( m_pClassFactory,
8640                                       DPtrToPreferredAddr(classFactory),
8641                                       EEClassOptionalFields, EECLASSES );
8642         }
8643 #endif // FEATURE_COMINTEROP
8644
8645         PTR_DictionaryLayout layout = pClassOptional->m_pDictLayout;
8646         if( layout == NULL )
8647         {
8648             DisplayWriteFieldPointer( m_pDictLayout, NULL, EEClassOptionalFields, EECLASSES );
8649         }
8650         else
8651         {
8652             IF_OPT(VERBOSE_TYPES)
8653             {
8654                 WriteFieldDictionaryLayout( "m_pDictLayout",
8655                                             offsetof(EEClassOptionalFields, m_pDictLayout),
8656                                             fieldsize(EEClassOptionalFields, m_pDictLayout),
8657                                             layout, GetDependencyFromMT(mt)->pImport );
8658             }
8659             else
8660             {
8661                 while( layout != NULL )
8662                 {
8663                     CoverageRead( PTR_TO_TADDR(layout),
8664                                   sizeof(DictionaryLayout)
8665                                   + sizeof(DictionaryEntryLayout)
8666                                   * (layout->m_numSlots - 1) );
8667                     layout = PTR_DictionaryLayout(TO_TADDR(layout->m_pNext));
8668                 }
8669             }
8670         }
8671         PTR_BYTE varianceInfo = pClassOptional->GetVarianceInfo();
8672         if( varianceInfo == NULL )
8673         {
8674             DisplayWriteFieldPointer( m_pVarianceInfo, NULL,
8675                                       EEClassOptionalFields, EECLASSES );
8676         }
8677         else
8678         {
8679             /* REVISIT_TODO Fri 10/14/2005
8680              * Dump variance info
8681              */
8682             DisplayWriteFieldPointer( m_pVarianceInfo,
8683                                       DPtrToPreferredAddr(varianceInfo), EEClassOptionalFields,
8684                                       EECLASSES );
8685         }
8686
8687         DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID,
8688                               EEClassOptionalFields, EECLASSES );
8689
8690         DisplayEndStructure( EECLASSES ); // EEClassOptionalFields
8691     }
8692 } // NativeImageDumper::DumpEEClassForMethodTable
8693 #ifdef _PREFAST_
8694 #pragma warning(pop)
8695 #endif
8696
8697 enum TypeDescType
8698 {
8699     TDT_IsTypeDesc,
8700     TDT_IsParamTypeDesc,
8701     TDT_IsArrayTypeDesc,
8702     TDT_IsTypeVarTypeDesc,
8703     TDT_IsFnPtrTypeDesc
8704 };
8705 const char * const g_typeDescTypeNames[] =
8706 {
8707     "TypeDesc",
8708     "ParamTypeDesc",
8709     "ArrayTypeDesc",
8710     "TypeVarTypeDesc",
8711     "FnPtrTypeDesc"
8712 };
8713 int g_typeDescSizes[] =
8714 {
8715     sizeof(TypeDesc),
8716     sizeof(ParamTypeDesc),
8717     sizeof(ArrayTypeDesc),
8718     sizeof(TypeVarTypeDesc),
8719     -1//sizeof(FnPtrTypeDesc) -- variable size
8720 };
8721 TypeDescType getTypeDescType( PTR_TypeDesc td )
8722 {
8723     _ASSERTE(td != NULL);
8724     if( td->IsArray() )
8725         return TDT_IsArrayTypeDesc;
8726     if( td->HasTypeParam() )
8727         return TDT_IsParamTypeDesc;
8728     if( td->IsGenericVariable() )
8729         return TDT_IsTypeVarTypeDesc;
8730     if( td->GetInternalCorElementType() == ELEMENT_TYPE_FNPTR )
8731         return TDT_IsFnPtrTypeDesc;
8732     return TDT_IsTypeDesc;
8733 }
8734 NativeImageDumper::EnumMnemonics NativeImageDumper::s_TDFlags[] =
8735 {
8736
8737 #define TDF_ENTRY(x) NativeImageDumper::EnumMnemonics(TypeDesc:: x, W(#x) )
8738         TDF_ENTRY(enum_flag_NeedsRestore),
8739         TDF_ENTRY(enum_flag_PreRestored),
8740         TDF_ENTRY(enum_flag_Unrestored),
8741         TDF_ENTRY(enum_flag_UnrestoredTypeKey),
8742         TDF_ENTRY(enum_flag_IsNotFullyLoaded),
8743         TDF_ENTRY(enum_flag_DependenciesLoaded),
8744 #undef TDF_ENTRY
8745 };
8746
8747 NativeImageDumper::EnumMnemonics s_CConv[] =
8748 {
8749 #define CC_ENTRY(x) NativeImageDumper::EnumMnemonics( x, W(#x) )
8750
8751 #define CC_CALLCONV_ENTRY(x) NativeImageDumper::EnumMnemonics( x, IMAGE_CEE_CS_CALLCONV_MASK, W(#x) )
8752     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_VARARG),
8753     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_FIELD),
8754     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG),
8755     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_PROPERTY),
8756     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_UNMGD),
8757     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERICINST),
8758     CC_CALLCONV_ENTRY(IMAGE_CEE_CS_CALLCONV_NATIVEVARARG),
8759 #undef CC_CALLCONV_ENTRY
8760
8761     CC_ENTRY(IMAGE_CEE_CS_CALLCONV_HASTHIS),
8762     CC_ENTRY(IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS),
8763     CC_ENTRY(IMAGE_CEE_CS_CALLCONV_GENERIC)
8764 };
8765
8766
8767 void NativeImageDumper::DumpTypeDesc( PTR_TypeDesc td )
8768 {
8769     _ASSERTE(CHECK_OPT(TYPEDESCS));
8770     TypeDescType tdt = getTypeDescType(td);
8771     int size = g_typeDescSizes[(int)tdt];
8772     if( size == -1 )
8773     {
8774         _ASSERTE(tdt == TDT_IsFnPtrTypeDesc);
8775         size = FnPtrTypeDesc::DacSize(PTR_TO_TADDR(td));
8776     }
8777     DisplayStartStructure( g_typeDescTypeNames[(int)tdt],
8778                            DPtrToPreferredAddr(td), size, TYPEDESCS );
8779
8780     //first handle the fields of typedesc
8781     WriteFieldCorElementType( m_typeAndFlags, td->GetInternalCorElementType(),
8782                               TypeDesc, TYPEDESCS );
8783     DisplayWriteFieldEnumerated( m_typeAndFlags, td->m_typeAndFlags, TypeDesc,
8784                                  s_TDFlags, W(", "), TYPEDESCS );
8785     if( tdt == TDT_IsParamTypeDesc || tdt == TDT_IsArrayTypeDesc )
8786     {
8787         PTR_ParamTypeDesc ptd(td);
8788         DisplayStartVStructure( "ParamTypeDesc", TYPEDESCS );
8789         WriteFieldMethodTable( m_TemplateMT, ptd->GetTemplateMethodTableInternal(),
8790                                ParamTypeDesc, TYPEDESCS );
8791         WriteFieldTypeHandle( m_Arg, ptd->m_Arg, 
8792                               ParamTypeDesc, TYPEDESCS );
8793         DisplayWriteFieldPointer( m_hExposedClassObject,
8794                                   DataPtrToDisplay(ptd->m_hExposedClassObject),
8795                                   ParamTypeDesc, TYPEDESCS );
8796
8797         DisplayEndVStructure( TYPEDESCS ); //ParamTypeDesc
8798     }
8799     else if( tdt == TDT_IsFnPtrTypeDesc )
8800     {
8801         PTR_FnPtrTypeDesc ftd(td);
8802         DisplayStartVStructure( "FnPtrTypeDesc", TYPEDESCS );
8803         DisplayWriteFieldInt( m_NumArgs, ftd->m_NumArgs, FnPtrTypeDesc,
8804                               TYPEDESCS );
8805         DisplayWriteFieldEnumerated( m_CallConv, ftd->m_CallConv, 
8806                                      FnPtrTypeDesc, s_CConv, W(", "),
8807                                      TYPEDESCS );
8808         DisplayStartArrayWithOffset( m_RetAndArgTypes, W("[%-4s]: %s"),
8809                                      FnPtrTypeDesc, TYPEDESCS );
8810         PTR_TypeHandle args( PTR_HOST_MEMBER_TADDR(FnPtrTypeDesc, ftd,
8811                                                    m_RetAndArgTypes) );
8812         for( unsigned i = 0; i < ftd->m_NumArgs; ++i )
8813         {
8814             DisplayStartElement( "Argument", TYPEDESCS );
8815             DisplayWriteElementInt( "Index", i, TYPEDESCS );
8816             IF_OPT( TYPEDESCS )
8817                 WriteElementTypeHandle( "TypeHandle", args[i] );
8818             DisplayEndElement( TYPEDESCS );
8819         }
8820         DisplayEndArray( "Total Arguments", TYPEDESCS ); 
8821         DisplayEndVStructure( TYPEDESCS );
8822     }
8823     else if( tdt == TDT_IsTypeVarTypeDesc )
8824     {
8825         PTR_TypeVarTypeDesc tvtd(td);
8826         DisplayStartVStructure( "TypeVarTypeDesc", TYPEDESCS );
8827         DisplayWriteFieldPointer( m_pModule,
8828                                   DPtrToPreferredAddr(tvtd->GetModule()),
8829                                   TypeVarTypeDesc, TYPEDESCS );
8830         DisplayWriteFieldUInt( m_typeOrMethodDef,
8831                                tvtd->m_typeOrMethodDef,
8832                                TypeVarTypeDesc, TYPEDESCS );
8833         DisplayWriteFieldInt( m_numConstraints, tvtd->m_numConstraints,
8834                               TypeVarTypeDesc, TYPEDESCS );
8835         if( tvtd->m_constraints == NULL )
8836         {
8837             DisplayWriteFieldPointer( m_constraints, NULL, TypeVarTypeDesc,
8838                                       TYPEDESCS );
8839         }
8840         else
8841         {
8842             DisplayStartStructureWithOffset( m_constraints,
8843                                              DPtrToPreferredAddr(tvtd->m_constraints),
8844                                              sizeof(*tvtd->m_constraints) * 
8845                                              tvtd->m_numConstraints,
8846                                              TypeVarTypeDesc, TYPEDESCS );
8847             DisplayStartArray( "Constraints", NULL, TYPEDESCS );
8848             for( unsigned i = 0; i < tvtd->m_numConstraints; ++i )
8849             {
8850                 WriteElementTypeHandle( "TypeHandle", tvtd->m_constraints[i] );
8851             }
8852             DisplayEndArray( "Total Constraints", TYPEDESCS ); //Constraints
8853             DisplayEndStructure( TYPEDESCS ); //m_constraints
8854         }
8855         DisplayWriteFieldPointer( m_hExposedClassObject,
8856                                   DataPtrToDisplay(tvtd->m_hExposedClassObject),
8857                                   TypeVarTypeDesc, TYPEDESCS );
8858         DisplayWriteFieldUInt( m_token, tvtd->m_token, TypeVarTypeDesc,
8859                                TYPEDESCS );
8860         DisplayWriteFieldInt( m_index, tvtd->m_index, TypeVarTypeDesc,
8861                               TYPEDESCS );
8862
8863         DisplayEndVStructure( TYPEDESCS ); //TypeVarTypeDesc
8864     }
8865     
8866
8867     DisplayEndStructure( TYPEDESCS ); // g_typeDescTypeNames
8868
8869 }
8870
8871 void NativeImageDumper::DumpDictionaryEntry( const char * elementName,
8872                                              DictionaryEntryKind kind,
8873                                              PTR_DictionaryEntry entry )
8874 {
8875     m_display->StartElement( elementName );
8876     const char * name = NULL;
8877     switch(kind)
8878     {
8879     case EmptySlot:
8880         m_display->WriteEmptyElement("EmptySlot");
8881         break;
8882     case TypeHandleSlot:
8883         {
8884             TypeHandle th = dac_cast<DPTR(FixupPointer<TypeHandle>)>(entry)->GetValue();
8885             WriteElementTypeHandle( "TypeHandle", th );
8886             /* XXX Fri 03/24/2006
8887              * There is no straightforward home for these, so make sure to
8888              * record them
8889              */
8890             if( !CORCOMPILE_IS_POINTER_TAGGED(th.AsTAddr()) && th.IsTypeDesc() )
8891             {
8892                 PTR_TypeDesc td(th.AsTypeDesc());
8893                 if( isInRange(PTR_TO_TADDR(td)) )
8894                 {
8895                     m_discoveredTypeDescs.AppendEx(td);
8896                 }
8897             }
8898         }
8899         break;
8900     case MethodDescSlot:
8901         {
8902             TempBuffer buf;
8903             PTR_MethodDesc md(TO_TADDR(*entry));
8904             WriteElementMethodDesc( "MethodDesc", md );
8905         }
8906         break;
8907     case MethodEntrySlot:
8908         name = "MethodEntry";
8909         goto StandardEntryDisplay;
8910     case ConstrainedMethodEntrySlot:
8911         name = "ConstrainedMethodEntry";
8912         goto StandardEntryDisplay;
8913     case DispatchStubAddrSlot:
8914         name = "DispatchStubAddr";
8915         goto StandardEntryDisplay;
8916         /* REVISIT_TODO Tue 10/11/2005
8917          * Print out name information here
8918          */
8919     case FieldDescSlot:
8920         name = "FieldDescSlot";
8921 StandardEntryDisplay:
8922         m_display->WriteElementPointer(name, DataPtrToDisplay((TADDR)*entry));
8923         break;
8924     default:
8925         _ASSERTE( !"unreachable" );
8926     }
8927     m_display->EndElement(); //elementName
8928 }
8929
8930 #ifdef FEATURE_READYTORUN
8931 IMAGE_DATA_DIRECTORY * NativeImageDumper::FindReadyToRunSection(DWORD type)
8932 {
8933     PTR_READYTORUN_SECTION pSections = dac_cast<PTR_READYTORUN_SECTION>(dac_cast<TADDR>(m_pReadyToRunHeader) + sizeof(READYTORUN_HEADER));
8934     for (DWORD i = 0; i < m_pReadyToRunHeader->NumberOfSections; i++)
8935     {
8936         // Verify that section types are sorted
8937         _ASSERTE(i == 0 || (pSections[i - 1].Type < pSections[i].Type));
8938
8939         READYTORUN_SECTION * pSection = pSections + i;
8940         if (pSection->Type == type)
8941             return &pSection->Section;
8942     }
8943     return NULL;
8944 }
8945
8946 //
8947 // Ready to Run specific dumping methods
8948 //
8949 void NativeImageDumper::DumpReadyToRun()
8950 {
8951     m_pReadyToRunHeader = m_decoder.GetReadyToRunHeader();
8952
8953     m_nativeReader = NativeFormat::NativeReader(dac_cast<PTR_BYTE>(m_decoder.GetBase()), m_decoder.GetVirtualSize());
8954
8955     IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindReadyToRunSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS);
8956     if (pRuntimeFunctionsDir != NULL)
8957     {
8958         m_pRuntimeFunctions = dac_cast<PTR_RUNTIME_FUNCTION>(m_decoder.GetDirectoryData(pRuntimeFunctionsDir));
8959         m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION);
8960     }
8961     else
8962     {
8963         m_nRuntimeFunctions = 0;
8964     }
8965
8966     IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindReadyToRunSection(READYTORUN_SECTION_METHODDEF_ENTRYPOINTS);
8967     if (pEntryPointsDir != NULL)
8968         m_methodDefEntryPoints = NativeFormat::NativeArray((TADDR)&m_nativeReader, pEntryPointsDir->VirtualAddress);
8969
8970     DisplayStartCategory("NativeInfo", NATIVE_INFO);
8971
8972     IF_OPT(NATIVE_INFO)
8973         DumpReadyToRunHeader();
8974
8975     DisplayEndCategory(NATIVE_INFO); //NativeInfo
8976
8977     IF_OPT_OR3(METHODS, GC_INFO, DISASSEMBLE_CODE)
8978         DumpReadyToRunMethods();
8979
8980     IF_OPT(RELOCATIONS)
8981         DumpBaseRelocs();
8982 }
8983
8984 const NativeImageDumper::EnumMnemonics s_ReadyToRunFlags[] = 
8985 {
8986 #define RTR_FLAGS(f) NativeImageDumper::EnumMnemonics(f, W(#f))
8987     RTR_FLAGS(READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE),
8988 #undef RTR_FLAGS
8989 };
8990
8991 void NativeImageDumper::DumpReadyToRunHeader()
8992 {
8993     IF_OPT(NATIVE_INFO)
8994     {
8995         m_display->StartStructure( "READYTORUN_HEADER",
8996                                    DPtrToPreferredAddr(dac_cast<PTR_READYTORUN_HEADER>(m_pReadyToRunHeader)),
8997                                    sizeof(*m_pReadyToRunHeader) );
8998
8999         DisplayWriteFieldUInt( Signature, m_pReadyToRunHeader->Signature, READYTORUN_HEADER, ALWAYS );
9000         DisplayWriteFieldUInt( MajorVersion, m_pReadyToRunHeader->MajorVersion, READYTORUN_HEADER, ALWAYS );
9001         DisplayWriteFieldUInt( MinorVersion, m_pReadyToRunHeader->MinorVersion, READYTORUN_HEADER, ALWAYS );
9002
9003         DisplayWriteFieldEnumerated( Flags, m_pReadyToRunHeader->Flags,
9004                                      READYTORUN_HEADER, s_ReadyToRunFlags, W(", "),
9005                                      NATIVE_INFO );
9006
9007         m_display->EndStructure(); //READYTORUN_HEADER
9008     }
9009 }
9010
9011 void NativeImageDumper::DumpReadyToRunMethods()
9012 {
9013     DisplayStartArray("Methods", NULL, METHODS);
9014
9015     for (uint rid = 1; rid <= m_methodDefEntryPoints.GetCount(); rid++)
9016     {
9017         uint offset;
9018         if (!m_methodDefEntryPoints.TryGetAt(rid - 1, &offset))
9019             continue;
9020
9021         uint id;
9022         offset = m_nativeReader.DecodeUnsigned(offset, &id);
9023
9024         if (id & 1)
9025         {
9026             if (id & 2)
9027             {
9028                 uint val;
9029                 m_nativeReader.DecodeUnsigned(offset, &val);
9030                 offset -= val;
9031             }
9032
9033             // TODO: Dump fixups from dac_cast<TADDR>(m_pLayout->GetBase()) + offset
9034
9035             id >>= 2;
9036         }
9037         else
9038         {
9039             id >>= 1;
9040         }
9041
9042         _ASSERTE(id < m_nRuntimeFunctions);
9043         PTR_RUNTIME_FUNCTION pRuntimeFunction = m_pRuntimeFunctions + id;
9044         PCODE pEntryPoint = dac_cast<TADDR>(m_decoder.GetBase()) + pRuntimeFunction->BeginAddress;
9045
9046         SString buf;
9047         AppendTokenName(TokenFromRid(rid, mdtMethodDef), buf, m_import);
9048
9049         DumpReadyToRunMethod(pEntryPoint, pRuntimeFunction, buf);
9050     }
9051
9052     DisplayEndArray("Total Methods", METHODS); //Methods
9053 }
9054
9055 extern PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntimeFunction, /* out */ SIZE_T * pSize);
9056
9057 void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNCTION pRuntimeFunction, SString& name)
9058 {
9059     //Read the GCInfo to get the total method size.
9060     unsigned methodSize = 0;
9061     unsigned gcInfoSize = UINT_MAX;
9062
9063     SIZE_T nUnwindDataSize;
9064     PTR_VOID pUnwindData = GetUnwindDataBlob(dac_cast<TADDR>(m_decoder.GetBase()), pRuntimeFunction, &nUnwindDataSize);
9065
9066     // GCInfo immediatelly follows unwind data
9067     PTR_CBYTE gcInfo = dac_cast<PTR_CBYTE>(pUnwindData) + nUnwindDataSize;
9068
9069     void(*stringOutFn)(const char *, ...);
9070     IF_OPT(GC_INFO)
9071     {
9072         stringOutFn = stringOut;
9073     }
9074     else
9075     {
9076         stringOutFn = nullStringOut;
9077     }
9078     if (gcInfo != NULL)
9079     {
9080         PTR_CBYTE curGCInfoPtr = gcInfo;
9081         g_holdStringOutData.Clear();
9082         GCDump gcDump(GCINFO_VERSION);
9083         gcDump.gcPrintf = stringOutFn;
9084         UINT32 r2rversion = m_pReadyToRunHeader->MajorVersion;
9085         UINT32 gcInfoVersion = GCInfoToken::ReadyToRunVersionToGcInfoVersion(r2rversion);
9086         GCInfoToken gcInfoToken = { curGCInfoPtr, gcInfoVersion };
9087
9088 #if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
9089         GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
9090         methodSize = gcInfoDecoder.GetCodeLength();
9091 #endif
9092
9093         //dump the data to a string first so we can get the gcinfo size.
9094 #ifdef _TARGET_X86_
9095         InfoHdr hdr;
9096         stringOutFn("method info Block:\n");
9097         curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0);
9098         stringOutFn("\n");
9099 #endif
9100
9101         IF_OPT(METHODS)
9102         {
9103 #ifdef _TARGET_X86_
9104             stringOutFn("PointerTable:\n");
9105             curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9106                 hdr,
9107                 methodSize, 0);
9108             gcInfoSize = curGCInfoPtr - gcInfo;
9109 #elif defined(USE_GC_INFO_DECODER)
9110             stringOutFn("PointerTable:\n");
9111             curGCInfoPtr += gcDump.DumpGCTable(curGCInfoPtr,
9112                 methodSize, 0);
9113             gcInfoSize = (unsigned)(curGCInfoPtr - gcInfo);
9114 #endif
9115         }
9116
9117         //data is output below.
9118     }
9119
9120     DisplayStartElement("Method", METHODS);
9121     DisplayWriteElementStringW("Name", (const WCHAR *)name, METHODS);
9122
9123     DisplayStartStructure("GCInfo",
9124         DPtrToPreferredAddr(gcInfo),
9125         gcInfoSize,
9126         METHODS);
9127
9128     DisplayStartTextElement("Contents", GC_INFO);
9129     DisplayWriteXmlTextBlock(("%S", (const WCHAR *)g_holdStringOutData), GC_INFO);
9130     DisplayEndTextElement(GC_INFO); //Contents
9131
9132     DisplayEndStructure(METHODS); //GCInfo
9133
9134     DisplayStartStructure("Code", DataPtrToDisplay(pEntryPoint), methodSize,
9135         METHODS);
9136
9137     IF_OPT(DISASSEMBLE_CODE)
9138     {
9139         // Disassemble hot code.  Read the code into the host process.
9140         /* REVISIT_TODO Mon 10/24/2005
9141         * Is this align up right?
9142         */
9143         BYTE * codeStartHost =
9144             reinterpret_cast<BYTE*>(PTR_READ(pEntryPoint,
9145                 (ULONG32)ALIGN_UP(methodSize,
9146                     CODE_SIZE_ALIGN)));
9147         DisassembleMethod(codeStartHost, methodSize);
9148     }
9149
9150     DisplayEndStructure(METHODS); //Code 
9151
9152     DisplayEndElement(METHODS); //Method
9153 }
9154 #endif // FEATURE_READYTORUN
9155
9156 #if 0
9157 void NativeImageDumper::RecordTypeRef( mdTypeRef token, PTR_MethodTable mt )
9158 {
9159     if( mt != NULL )
9160         m_mtToTypeRefMap.Add( mt, token );
9161 }
9162 mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt )
9163 {
9164     return m_mtToTypeRefMap.Find(mt);
9165 }
9166 #endif
9167
9168 #else //!FEATURE_PREJIT
9169 //dummy implementation for dac
9170 HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase,
9171     LPCWSTR name,
9172     IXCLRDataDisplay* display,
9173     IXCLRLibrarySupport* support,
9174     IXCLRDisassemblySupport* dis)
9175 {
9176     return E_FAIL;
9177 }
9178 #endif //FEATURE_PREJIT
9179
9180 /* REVISIT_TODO Mon 10/10/2005
9181  * Here is where it gets bad.  There is no DAC build of gcdump, so instead
9182  * build it directly into the the dac.  That's what all these ugly defines
9183  * are all about.
9184  */
9185 #ifdef __MSC_VER
9186 #pragma warning(disable:4244)   // conversion from 'unsigned int' to 'unsigned short', possible loss of data
9187 #pragma warning(disable:4189)   // local variable is initialized but not referenced
9188 #endif // __MSC_VER
9189
9190 #undef assert
9191 #define assert(a)
9192 #define NOTHROW
9193 #define GC_NOTRIGGER
9194 #include <gcdecoder.cpp>
9195 #undef NOTHROW
9196 #undef GC_NOTRIGGER
9197
9198 #if defined _DEBUG && defined _TARGET_X86_ 
9199 #ifdef _MSC_VER
9200 // disable FPO for checked build
9201 #pragma optimize("y", off)
9202 #endif // _MSC_VER
9203 #endif
9204
9205 #undef _ASSERTE
9206 #define _ASSERTE(a) do {} while (0)
9207 #ifdef _TARGET_X86_
9208 #include <gcdump.cpp>
9209 #endif
9210
9211 #undef LIMITED_METHOD_CONTRACT
9212 #undef WRAPPER_NO_CONTRACT
9213 #ifdef _TARGET_X86_
9214 #include <i386/gcdumpx86.cpp>
9215 #else // !_TARGET_X86_
9216 #undef PREGDISPLAY
9217 #include <gcdumpnonx86.cpp>
9218 #endif // !_TARGET_X86_
9219
9220 #ifdef __MSC_VER
9221 #pragma warning(default:4244)
9222 #pragma warning(default:4189)
9223 #endif // __MSC_VER