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// Disassembler
7//
8#include "ildasmpch.h"
9
10#include "debugmacros.h"
11#include "corpriv.h"
12#include "dasmenum.hpp"
13#include "formattype.h"
14#include "dis.h"
15#include "resource.h"
16#include "ilformatter.h"
17#include "outstring.h"
18
19#include "ceeload.h"
20#include "dynamicarray.h"
21extern PELoader * g_pPELoader;
22#include <corsym.h>
23
24extern ISymUnmanagedReader* g_pSymReader;
25extern BOOL g_fDumpAsmCode;
26extern char g_szAsmCodeIndent[];
27extern BOOL g_fShowBytes;
28extern BOOL g_fShowSource;
29extern BOOL g_fInsertSourceLines;
30extern BOOL g_fTryInCode;
31extern BOOL g_fQuoteAllNames;
32extern BOOL g_fDumpTokens;
33extern DynamicArray<__int32> *g_pPtrTags; //to keep track of all "ldptr"
34extern DynamicArray<DWORD> *g_pPtrSize; //to keep track of all "ldptr"
35extern int g_iPtrCount;
36static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbStr);
37extern DWORD g_Mode;
38extern unsigned g_uConsoleCP;
39
40#define PADDING 28
41
42extern BOOL g_fThisIsInstanceMethod;
43extern unsigned g_uCodePage;
44extern HANDLE hConsoleOut;
45extern HANDLE hConsoleErr;
46// globals for source file info
47ULONG_PTR ulWasFileToken = 0xFFFFFFFF;
48GUID guidWasLang={0}, guidWasLangVendor={0},guidWasDoc={0};
49WCHAR wzWasFileName[2048];
50ULONG ulWasLine = 0;
51FILE* pFile=NULL;
52BOOL bIsNewFile = TRUE;
53WCHAR wzUniBuf[UNIBUF_SIZE];
54char szString[SZSTRING_SIZE];
55//-----------------------------------
56struct LexScope
57{
58 DWORD dwStart;
59 DWORD dwEnd;
60 ISymUnmanagedScope* pISymScope;
61 DWORD dwZOrder;
62 inline bool IsOpen() { return (dwZOrder != 0); };
63 inline bool Covers(DWORD dwOffset) { return ((dwStart <= dwOffset) && (dwOffset < dwEnd)); };
64};
65//-----------------------------------
66
67OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen)
68{
69 OPCODE opcode;
70
71 *pdwLen = 1;
72 opcode = OPCODE(pCode[0]);
73 switch(opcode) {
74 case CEE_PREFIX1:
75 opcode = OPCODE(pCode[1] + 256);
76 if (opcode < 0 || opcode >= CEE_COUNT)
77 opcode = CEE_COUNT;
78 *pdwLen = 2;
79 break;
80 case CEE_PREFIXREF:
81 case CEE_PREFIX2:
82 case CEE_PREFIX3:
83 case CEE_PREFIX4:
84 case CEE_PREFIX5:
85 case CEE_PREFIX6:
86 case CEE_PREFIX7:
87 *pdwLen = 3;
88 return CEE_COUNT;
89 default:
90 break;
91 }
92 return opcode;
93}
94//------------------------------------------------------------------
95WCHAR* UtfToUnicode(__in __nullterminated const char* sz)
96{
97 WCHAR* wz = wzUniBuf;
98 if (WszMultiByteToWideChar(CP_UTF8,0,sz,-1,wz,UNIBUF_SIZE/2) == 0)
99 {
100 wz[UNIBUF_SIZE/2 - 1] = 0;
101 }
102 return wz;
103}
104char* UnicodeToAnsi(__in __nullterminated const WCHAR* wz)
105{
106 char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
107 if (WszWideCharToMultiByte(g_uConsoleCP,0,wz,-1,sz,UNIBUF_SIZE,NULL,NULL) == 0)
108 {
109 sz[UNIBUF_SIZE - 1] = 0;
110 }
111 return sz;
112}
113WCHAR* AnsiToUnicode(__in __nullterminated const char* sz)
114{
115 WCHAR* wz = wzUniBuf;
116 if (WszMultiByteToWideChar(g_uConsoleCP,0,sz,-1,wz,UNIBUF_SIZE/2) == 0)
117 {
118 wz[UNIBUF_SIZE/2 - 1] = 0;
119 }
120 return wz;
121}
122char* UnicodeToUtf(__in __nullterminated const WCHAR* wz)
123{
124 char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
125 if (WszWideCharToMultiByte(CP_UTF8,0,wz,-1,sz,UNIBUF_SIZE,NULL,NULL) == 0)
126 {
127 sz[UNIBUF_SIZE - 1] = 0;
128 }
129 return sz;
130}
131char* AnsiToUtf(__in __nullterminated const char* sz) { return UnicodeToUtf(AnsiToUnicode(sz));}
132
133static void UnicodeToConsoleOrMsgBox(__in __nullterminated const WCHAR* wz)
134{
135 {
136 //DWORD dw;
137 //char* sz = UnicodeToAnsi(wz);
138 //WriteFile(hConsoleOut,(CONST VOID *)sz, (ULONG32)strlen(sz),&dw,NULL);
139 //WriteFile(hConsoleOut,(CONST VOID *)"\r\n", 2,&dw,NULL);
140 printf("%s\n",UnicodeToAnsi(wz));
141 }
142}
143static void UnicodeToFile(__in __nullterminated const WCHAR* wz, FILE* pF)
144{
145 unsigned endofline = 0x000A000D;
146 int L;
147 if((L=(int)wcslen(wz))) fwrite(wz,L*sizeof(WCHAR),1,pF);
148 fwrite(&endofline,4,1,pF);
149}
150static void ToGUIOrFile(__in __nullterminated const char* sz, void* GUICookie)
151{
152 {
153 if(g_fDumpRTF) fprintf((FILE*)GUICookie,"%s\\line\n",sz);
154 else fprintf((FILE*)GUICookie,"%s\n",sz);
155 }
156}
157//------------------------------------------------------------------
158void printError(void* GUICookie, __in __nullterminated const char* string)
159{
160 {
161 //DWORD dw;
162 const char* sz = ERRORMSG(string);
163 if(GUICookie) printLine(GUICookie, sz);
164 //sz = UnicodeToAnsi(UtfToUnicode(string));
165 //WriteFile(hConsoleErr,(CONST VOID *)sz, (ULONG32)strlen(sz),&dw,NULL);
166 //WriteFile(hConsoleErr,(CONST VOID *)"\r\n", 2,&dw,NULL);
167 fprintf(stderr,"%s\n",UnicodeToAnsi(UtfToUnicode(string)));
168 }
169}
170void printLine(void* GUICookie, __in __nullterminated const char* string)
171{
172 const char* sz = string;
173
174 if (GUICookie == NULL)
175 {
176 UnicodeToConsoleOrMsgBox(UtfToUnicode(string));
177 return;
178 }
179
180
181 if(g_uCodePage != CP_UTF8)
182 {
183 WCHAR* wz = UtfToUnicode(string);
184 if(g_uCodePage != 0xFFFFFFFF)
185 {
186 sz = UnicodeToAnsi(wz);
187 }
188 else if(GUICookie)
189 {
190 UnicodeToFile(wz,(FILE*)GUICookie);
191 return;
192 }
193 else sz = (char*)wz;
194 }
195 ToGUIOrFile(sz,GUICookie);
196}
197
198void printLineW(void* GUICookie, __in __nullterminated const WCHAR* string)
199{
200 const char* sz = (const char*)string;
201
202 if (GUICookie == NULL)
203 {
204 UnicodeToConsoleOrMsgBox(string);
205 return;
206 }
207 if(g_uCodePage == 0xFFFFFFFF)
208 {
209 UnicodeToFile(string,(FILE*)GUICookie);
210 return;
211 }
212 else if(g_uCodePage == CP_UTF8)
213 sz = UnicodeToUtf(string);
214 else if(g_uCodePage == g_uConsoleCP)
215 sz = UnicodeToAnsi(string);
216
217 ToGUIOrFile(sz,GUICookie);
218}
219
220char * DumpQString(void* GUICookie,
221 __in __nullterminated const char* szToDump,
222 __in __nullterminated const char* szPrefix,
223 unsigned uMaxLen)
224{
225 unsigned Lwt = (unsigned)strlen(szString);
226 char* szptr = &szString[Lwt];
227 const char* p = szToDump;
228 unsigned L = (unsigned)strlen(szToDump);
229 unsigned l,i;
230 unsigned tally=0;
231 *szptr++ = '"';
232
233 do
234 {
235 l = L;
236 if(l > uMaxLen+2) // +2 - to account for leading/trailing doublequotes in szToDump
237 {
238 l = uMaxLen;
239 while((p[l-1] == '\\')&& l) l--;
240 if(l == 0) l = (uMaxLen+1) & 0xFFFFFFFE;
241 }
242 if(tally)
243 {
244 printLine(GUICookie,szString);
245 szptr = szString;
246 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s+ \"",szPrefix);
247 }
248 else uMaxLen = uMaxLen - (ULONG32)strlen(szPrefix) + Lwt;
249 tally++;
250 for(i=0; i < l; i++, szptr++, p++)
251 {
252 switch(*p)
253 {
254 case '\n': *szptr++ = '\\'; *szptr = 'n'; break;
255 case '\r': *szptr++ = '\\'; *szptr = 'r'; break;
256 case '\t': *szptr++ = '\\'; *szptr = 't'; break;
257 case '\b': *szptr++ = '\\'; *szptr = 'b'; break;
258 case '\f': *szptr++ = '\\'; *szptr = 'f'; break;
259 case '\v': *szptr++ = '\\'; *szptr = 'v'; break;
260 case '\a': *szptr++ = '\\'; *szptr = 'a'; break;
261 case '\?': *szptr++ = '\\'; *szptr = '?'; break;
262 case '\\': *szptr++ = '\\'; *szptr = '\\'; break;
263 case '"': *szptr++ = '\\'; *szptr = '"'; break;
264 case '{': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),SCOPE()); szptr--; break;
265 case '}': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),UNSCOPE()); szptr--; break;
266 case '<': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),LTN()); szptr--; break;
267 case '>': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),GTN()); szptr--; break;
268 default: *szptr = *p; break;
269 }
270 }
271 *szptr++ = '"';
272 *szptr = 0;
273 L -= l;
274 } while(L);
275 return szptr;
276}
277struct DasmExceptionInfoClause : COR_ILMETHOD_SECT_EH_CLAUSE_FAT {
278public:
279 bool ClauseIsFat;
280};
281DasmExceptionInfoClause* g_ehInfo = NULL;
282ULONG g_ehCount = 0;
283/********************************************************************************/
284/* used by qsort to sort the g_ehInfo table */
285static int __cdecl ehInfoCmp(const void *op1, const void *op2)
286{
287 DasmExceptionInfoClause* p1 = (DasmExceptionInfoClause*)op1;
288 DasmExceptionInfoClause* p2 = (DasmExceptionInfoClause*)op2;
289 int d;
290 d = p1->GetTryOffset() - p2->GetTryOffset(); if(d) return d;
291 d = p1->GetTryLength() - p2->GetTryLength(); if(d) return d;
292 d = p1->GetHandlerOffset() - p2->GetHandlerOffset(); if(d) return d;
293 d = p1->GetHandlerLength() - p2->GetHandlerLength(); if(d) return d;
294 return 0;
295}
296
297BOOL enumEHInfo(const COR_ILMETHOD_SECT_EH* eh, IMDInternalImport *pImport, DWORD dwCodeSize)
298{
299 COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
300 const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
301 BOOL fTryInCode = FALSE;
302 if(g_ehInfo) VDELETE(g_ehInfo);
303 g_ehCount = 0;
304 if(eh && (g_ehCount = eh->EHCount()))
305 {
306 g_ehInfo = new DasmExceptionInfoClause[g_ehCount];
307 _ASSERTE(g_ehInfo != NULL);
308 unsigned i;
309 for (i = 0; i < g_ehCount; i++)
310 {
311 ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)eh->EHClause(i, &ehBuff);
312 memcpy(&g_ehInfo[i],ehInfo,sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
313 g_ehInfo[i].ClauseIsFat = eh->IsFat();
314 //_ASSERTE((ehInfo->GetFlags() & SEH_NEW_PUT_MASK) == 0); // we are using 0x80000000 and 0x40000000
315 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)ehInfo->GetFlags() & ~SEH_NEW_PUT_MASK));
316 }
317 // check if all boundaries are within method code:
318 fTryInCode = g_fTryInCode;
319 for(i=0; i < g_ehCount; i++)
320 {
321 if( (g_ehInfo[i].GetTryOffset() >= dwCodeSize) ||
322 (g_ehInfo[i].GetTryOffset() + g_ehInfo[i].GetTryLength() >= dwCodeSize)||
323 (g_ehInfo[i].GetHandlerOffset() >= dwCodeSize) ||
324 (g_ehInfo[i].GetHandlerOffset() + g_ehInfo[i].GetHandlerLength() > dwCodeSize))
325 {
326 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | ERR_OUT_OF_CODE));
327 fTryInCode = FALSE; // if out of code, don't expand
328 }
329 }
330
331 if(fTryInCode)
332 {
333 DWORD dwWasTryOffset=0xFFFFFFFF, dwWasTryLength=0xFFFFFFFF, dwLastOffset=0xFFFFFFFF;
334 unsigned iNewTryBlock=0;
335 qsort(g_ehInfo, g_ehCount, sizeof(DasmExceptionInfoClause), ehInfoCmp);
336 for(i=0; i < g_ehCount; i++)
337 {
338 if((g_ehInfo[i].GetTryOffset() != dwWasTryOffset)||(g_ehInfo[i].GetTryLength() != dwWasTryLength))
339 {
340 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
341 dwLastOffset = g_ehInfo[i].GetTryOffset() + g_ehInfo[i].GetTryLength();
342 dwWasTryOffset = g_ehInfo[i].GetTryOffset();
343 dwWasTryLength = g_ehInfo[i].GetTryLength();
344 iNewTryBlock = i;
345 }
346
347 // determine offset of the block that lexically follows the try block (filter or handler)
348 DWORD dwFilterOrHandlerOffset;
349 if (g_ehInfo[i].GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER)
350 {
351 dwFilterOrHandlerOffset = g_ehInfo[i].GetFilterOffset();
352 }
353 else
354 dwFilterOrHandlerOffset = g_ehInfo[i].GetHandlerOffset();
355
356 if (dwFilterOrHandlerOffset == dwLastOffset)
357 {
358 if((i == iNewTryBlock)||((int)g_ehInfo[iNewTryBlock].GetFlags() & PUT_INTO_CODE))
359 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | PUT_INTO_CODE)); // insert catch/filter/finally in source
360 else
361 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert catch/filter/finally in source
362
363 dwLastOffset = (g_ehInfo[i].GetHandlerOffset() + g_ehInfo[i].GetHandlerLength());
364 }
365 else
366 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
367 }
368 }
369 else
370 {
371 for(i=0; i < g_ehCount; i++)
372 {
373 g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
374 }
375 }
376 }
377 return fTryInCode;
378}
379
380// This dumps the hex bytes for the given EHINFO clause
381void DumpHexEHInfo(DasmExceptionInfoClause *ehInfo, void *GUICookie)
382{
383 char *szptr = &szString[0];
384 _ASSERTE(g_fShowBytes);
385 COR_ILMETHOD_SECT_EH_CLAUSE_SMALL eh; // Temporary holder if we should dump the small version
386 BYTE *pb;
387 size_t sizeToDump; // Size of the hex data we're dumping
388
389 szptr = &szString[0];
390 szptr += sprintf_s(szptr, SZSTRING_SIZE,"%s// HEX:", g_szAsmCodeIndent);
391 ehInfo->SetFlags((CorExceptionFlag)((int)ehInfo->GetFlags() & ~SEH_NEW_PUT_MASK));
392
393 if (ehInfo->ClauseIsFat)
394 {
395 // Easy, though probably less common case
396 pb = (BYTE *)ehInfo;
397 sizeToDump = sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT);
398 } else
399 {
400 // Dev11 #2227 - we should dump small clauses as such in the hex dump
401 // Recreate the small EH clause, here, if it came is as a small clause
402 eh.SetFlags(ehInfo->GetFlags());
403 eh.TryOffset = ehInfo->TryOffset;
404 eh.TryLength = ehInfo->TryLength;
405 eh.HandlerOffset = ehInfo->HandlerOffset;
406 eh.HandlerLength = ehInfo->HandlerLength;
407
408 // A couple of sanity checks to make sure things the hex bites recreated are alright
409 _ASSERTE(sizeof(eh.FilterOffset) == sizeof(eh.ClassToken));
410 _ASSERTE(offsetof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL, FilterOffset) == offsetof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL, ClassToken));
411 eh.FilterOffset = ehInfo->FilterOffset;
412
413 pb = (BYTE *)&eh;
414 sizeToDump = sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL);
415 }
416 // Now dump the bytes out
417 for (size_t i = 0; i < sizeToDump; i++)
418 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), " %2.2X", *pb++);
419 printLine(GUICookie, COMMENT(szString));
420 // ehInfo->SetFlags((CorExceptionFlag)((dwFlags & ~SEH_NEW_PUT_MASK) | PUT_INTO_CODE));
421}
422
423void dumpOneEHInfo(DasmExceptionInfoClause* ehInfo, IMDInternalImport *pImport, void *GUICookie)
424{
425 //char szString[4096];
426 char* szptr = &szString[0];
427 if(!ehInfo) return;
428 DWORD dwFlags = ehInfo->GetFlags();
429 if(dwFlags & PUT_INTO_CODE)
430 return; // by the time dumpEHInfo is called, this ehInfo is done
431 if(dwFlags & NEW_TRY_BLOCK)
432 {
433 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s IL_%04x ",g_szAsmCodeIndent,KEYWORD(".try"),ehInfo->GetTryOffset());
434 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s IL_%04x ",KEYWORD("to"),ehInfo->GetTryOffset()+ehInfo->GetTryLength());
435 }
436 else
437 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",g_szAsmCodeIndent);
438
439 if (dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER)
440 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s IL_%04x ",KEYWORD("filter"),ehInfo->GetFilterOffset());
441 else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FAULT)
442 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("fault "));
443 else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FINALLY || IsNilToken(ehInfo->GetClassToken()))
444 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("finally "));
445 else
446 {
447 CQuickBytes out;
448 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s %s ",KEYWORD("catch"),PrettyPrintClass(&out, ehInfo->GetClassToken(), pImport));
449 REGISTER_REF(g_tkRefUser,ehInfo->GetClassToken());
450 }
451 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s IL_%04x",KEYWORD("handler"),ehInfo->GetHandlerOffset());
452 if(ehInfo->GetHandlerLength() != (DWORD) -1)
453 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " %s IL_%04x",KEYWORD("to"),ehInfo->GetHandlerOffset()+ehInfo->GetHandlerLength());
454
455 printLine(GUICookie, szString);
456
457 if(g_fShowBytes)
458 DumpHexEHInfo(ehInfo, GUICookie);
459 /*
460 if(ehInfo->GetFlags() & ERR_OUT_OF_CODE)
461 {
462 _snprintf_s(szString, _countof(szString), _TRUNCATE, "%s// WARNING: Boundary outside the method code",g_szAsmCodeIndent);
463 printLine(GUICookie,szString);
464 }
465 */
466}
467void dumpEHInfo(IMDInternalImport *pImport, void *GUICookie)
468{
469 //char szString[4096];
470
471 if(! g_ehCount) return;
472 sprintf_s(szString, SZSTRING_SIZE, "%s// Exception count %d", g_szAsmCodeIndent, g_ehCount);
473 //sprintf_s(szString, SZSTRING_SIZE, "%s// %d irregular exception clauses", g_szAsmCodeIndent, g_ehCount);
474 printLine(GUICookie, COMMENT(szString));
475
476 for (unsigned i = 0; i < g_ehCount; i++)
477 {
478 DasmExceptionInfoClause* ehInfo = &g_ehInfo[i];
479 dumpOneEHInfo(ehInfo,pImport,GUICookie);
480 }
481}
482
483static int __cdecl cmpLineCode(const void *p1, const void *p2)
484{ int ret = (((LineCodeDescr*)p1)->PC - ((LineCodeDescr*)p2)->PC);
485 if(ret==0)
486 {
487 ret= (((LineCodeDescr*)p1)->Line - ((LineCodeDescr*)p2)->Line);
488 if(ret==0) ret= (((LineCodeDescr*)p1)->Column - ((LineCodeDescr*)p2)->Column);
489 }
490 return ret;
491}
492
493static int __cdecl cmpLexScope(const void *p1, const void *p2)
494{
495 LexScope* pls1 = (LexScope*)p1;
496 LexScope* pls2 = (LexScope*)p2;
497 int d;
498 if((d = pls1->dwStart - pls2->dwStart)) return d;
499 return (pls2->dwEnd - pls1->dwEnd);
500}
501
502char* DumpDataPtr(__inout __nullterminated char* buffer, DWORD ptr, DWORD size)
503{
504 // check if ptr really points to some data in one of sections
505 IMAGE_SECTION_HEADER *pSecHdr = NULL;
506 DWORD i;
507 DWORD dwNumberOfSections;
508 if(g_pPELoader->IsPE32())
509 {
510 pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
511 dwNumberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
512 }
513 else
514 {
515 pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
516 dwNumberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
517 }
518
519 for (i=0; i < dwNumberOfSections; i++,pSecHdr++)
520 {
521 if((ptr >= VAL32(pSecHdr->VirtualAddress))&&
522 (ptr < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
523 {
524 if(ptr+size > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)) i = dwNumberOfSections;
525 break;
526 }
527 }
528 if(i < dwNumberOfSections)
529 { // yes, the pointer points to real data
530 int j;
531 for(j=0; (j < g_iPtrCount)&&((*g_pPtrTags)[j] != (__int32)ptr); j++);
532 if(j == g_iPtrCount)
533 {
534 if (g_pPtrSize == NULL)
535 {
536 g_pPtrSize = new DynamicArray<DWORD>;
537 }
538 if (g_pPtrTags == NULL)
539 {
540 g_pPtrTags = new DynamicArray<__int32>;
541 }
542
543 (*g_pPtrSize)[g_iPtrCount] = size;
544 (*g_pPtrTags)[g_iPtrCount++] = ptr;
545 }
546 else if((*g_pPtrSize)[j] < size) (*g_pPtrSize)[j] = size;
547 const char* szTls = "D_";
548 if(strcmp((const char*)(pSecHdr->Name),".tls") == 0) szTls = "T_";
549 else if(strcmp((const char*)(pSecHdr->Name),".text") == 0) szTls = "I_";
550 buffer+=sprintf_s(buffer,SZSTRING_REMAINING_SIZE(buffer), "%s%8.8X",szTls,ptr);
551 } //else print as hex
552 else
553 {
554 buffer+=sprintf_s(buffer,SZSTRING_REMAINING_SIZE(buffer),ERRORMSG("0x%8.8X /* WARNING: rogue pointer! (size 0x%8.8X) */"),ptr,size);
555 }
556 return buffer;
557}
558
559void DumpLocals(IMDInternalImport *pImport,COR_ILMETHOD_DECODER *pMethod, __in __nullterminated char* szVarPrefix, void* GUICookie)
560{
561 if (pMethod->GetLocalVarSigTok())
562 {
563 DWORD cbSigLen;
564 PCCOR_SIGNATURE pComSig;
565 CQuickBytes qbMemberSig;
566 size_t dwL;
567
568
569 if (FAILED(pImport->GetSigFromToken(pMethod->GetLocalVarSigTok(), &cbSigLen, &pComSig)))
570 {
571 printLine(GUICookie, "Invalid record");
572 return;
573 }
574
575 _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
576
577 appendStr(&qbMemberSig, g_szAsmCodeIndent);
578 appendStr(&qbMemberSig, KEYWORD(".locals "));
579 if(g_fDumpTokens)
580 {
581 char sz[32];
582 sprintf_s(sz,32,"/*%08X*/ ",pMethod->GetLocalVarSigTok());
583 appendStr(&qbMemberSig,COMMENT(sz));
584 }
585 if(pMethod->GetFlags() & CorILMethod_InitLocals) appendStr(&qbMemberSig, KEYWORD("init "));
586 dwL = qbMemberSig.Size();
587
588 char* pszTailSig = (char *) PrettyPrintSig(pComSig, cbSigLen, 0, &qbMemberSig, pImport,szVarPrefix);
589 if(strlen(pszTailSig) < dwL+3) return;
590
591 {
592 ULONG32 i,j,k,indent = (ULONG32)strlen(g_szAsmCodeIndent)+9; // indent+.locals (
593 char chAfterComma;
594 char *pComma = pszTailSig, *pch;
595 while((pComma = strchr(pComma,',')))
596 {
597 for(pch = pszTailSig, i=0, j=0, k=0; pch < pComma; pch++)
598 {
599 if(*pch == '\'') j=1-j;
600 else if(j==0)
601 {
602 if(*pch == '[') i++;
603 else if(*pch == ']') i--;
604 else if(strncmp(pch,LTN(),strlen(LTN()))==0) k++;
605 else if(strncmp(pch,GTN(),strlen(GTN()))==0) k--;
606 }
607 }
608 pComma++;
609 if((i==0)&&(k==0)&&(j==0)) // no brackets or all opened/closed
610 {
611 chAfterComma = *pComma;
612 *pComma = 0;
613 printLine(GUICookie,pszTailSig);
614 *pComma = chAfterComma;
615 for(i=0; i<indent; i++) pszTailSig[i] = ' ';
616 strcpy_s(&pszTailSig[indent],strlen(pComma)+1,pComma);
617 pComma = pszTailSig;
618 }
619 }
620 }
621 printLine(GUICookie, pszTailSig);
622 }
623}
624void LoadScope(ISymUnmanagedScope *pIScope,
625 DynamicArray<LexScope> *pdaScope,
626 ULONG *pulScopes)
627{
628 ULONG32 ulVars;
629 ULONG32 ulStart;
630 ULONG32 ulEnd;
631 ISymUnmanagedScope** ppChildScope = new ISymUnmanagedScope*[4096];
632 ULONG32 ulChildren;
633 unsigned i;
634
635 if(SUCCEEDED(pIScope->GetLocalCount(&ulVars)) && ulVars)
636 {
637 if(SUCCEEDED(pIScope->GetStartOffset(&ulStart)) &&
638 SUCCEEDED(pIScope->GetEndOffset(&ulEnd)))
639 {
640 (*pdaScope)[*pulScopes].dwStart = ulStart;
641 (*pdaScope)[*pulScopes].dwEnd = ulEnd;
642 (*pdaScope)[*pulScopes].dwZOrder = 0;
643 (*pdaScope)[*pulScopes].pISymScope = pIScope;
644 pIScope->AddRef();
645 (*pulScopes)++;
646 }
647 }
648 if(SUCCEEDED(pIScope->GetChildren(4096,&ulChildren,ppChildScope)))
649 {
650 for(i = 0; i < ulChildren; i++)
651 {
652 if(ppChildScope[i]) {
653 LoadScope(ppChildScope[i],pdaScope,pulScopes);
654 ppChildScope[i]->Release();
655 }
656 }
657 }
658 VDELETE(ppChildScope);
659
660}
661//#define SHOW_LEXICAL_SCOPES
662void OpenScope(ISymUnmanagedScope *pIScope,
663 __inout_ecount(ulLocals) ParamDescriptor *pLV,
664 ULONG ulLocals)
665{
666 ULONG32 dummy;
667 ULONG32 ulVars;
668 ULONG32 ulSlot;
669 ISymUnmanagedVariable** pVars = NULL;
670
671 if(FAILED(pIScope->GetLocalCount(&ulVars))) return;
672
673 ULONG32 ulNameLen;
674#ifdef SHOW_LEXICAL_SCOPES
675 for(unsigned jj = 0; jj < ulLocals; jj++) pLV[jj].attr = 0xFFFFFFFF;
676#endif
677 if(ulVars)
678 {
679 pVars = new ISymUnmanagedVariable*[ulVars+4];
680 memset(pVars,0,sizeof(PVOID)*(ulVars+4));
681
682 if(SUCCEEDED(pIScope->GetLocals(ulVars+4,&dummy,pVars)))
683 {
684 WCHAR* wzName = wzUniBuf;
685 char* szName = NULL;
686 for(ULONG ilv = 0; ilv < ulVars; ilv++)
687 {
688 if(pVars[ilv])
689 {
690 // get the local var slot number and make sure that it's in bounds:
691 if(SUCCEEDED(pVars[ilv]->GetAddressField1(&ulSlot)) && ulSlot < ulLocals)
692 {
693 if(SUCCEEDED(pVars[ilv]->GetName(UNIBUF_SIZE/2,&ulNameLen,wzName)))
694 {
695 szName = UnicodeToUtf(wzName);
696#ifndef SHOW_LEXICAL_SCOPES
697 for(ULONG32 j=0; j<ulLocals; j++)
698 {
699 if(j == ulSlot) continue;
700 if((pLV[ulSlot].name!=NULL)&&(!strcmp(szName,pLV[j].name)))
701 {
702 sprintf_s(szName,UNIBUF_SIZE/2,"V_%d",ulSlot);
703 break;
704 }
705 }
706#endif
707 if (!*szName)
708 sprintf_s(szName,UNIBUF_SIZE/2,"V_%d",ulSlot);
709 ulNameLen = (ULONG32) strlen(szName);
710 if((pLV[ulSlot].name==NULL)||(ulNameLen > (ULONG32)strlen(pLV[ulSlot].name)))
711 {
712 VDELETE(pLV[ulSlot].name);
713 pLV[ulSlot].name = new char[ulNameLen+1];
714 }
715 if(pLV[ulSlot].name != NULL)
716 strcpy_s(pLV[ulSlot].name,ulNameLen+1,szName);
717 }
718 pLV[ulSlot].attr = ulSlot;
719 }
720 pVars[ilv]->Release();
721 }
722 }
723 }
724 VDELETE(pVars);
725 }
726}
727
728char* DumpUnicodeString(void* GUICookie,
729 __inout __nullterminated char* szString,
730 __in_ecount(cbString) WCHAR* pszString,
731 ULONG cbString,
732 bool SwapString )
733{
734 unsigned i,L;
735 char* szStr=NULL, *szRet = NULL;
736#if defined(ALIGN_ACCESS) || BIGENDIAN
737 WCHAR* pszStringCopy = NULL;
738 // Make a copy if the string is unaligned or we have to modify it
739 if (cbString > 0)
740 {
741#if !BIGENDIAN
742 if((size_t)pszString & (sizeof(WCHAR)-1))
743#endif
744 {
745 L = (cbString+1)*sizeof(WCHAR);
746 pszStringCopy = new WCHAR[cbString+1];
747 memcpy(pszStringCopy, pszString, L);
748 pszString=pszStringCopy;
749 }
750 }
751#endif
752
753#if BIGENDIAN
754 if (SwapString)
755 SwapStringLength(pszString, cbString);
756#endif
757
758 // first, check for embedded zeros:
759 for(i=0; i < cbString; i++)
760 {
761 if(pszString[i] == 0) goto DumpAsByteArray;
762 }
763 szStr = new char[cbString*3 + 5];
764 memset(szStr,0,cbString*3 + 5);
765
766 WszWideCharToMultiByte(CP_UTF8,0,pszString,cbString,&szStr[0],cbString*3,NULL,NULL);
767 L = (unsigned)strlen(szStr);
768
769 szStr[L] = 0;
770 for(i=0; i < L; i++)
771 {
772 if((!isprint(((BYTE)(szStr[i]))))&&(szStr[i]!='\t')&&(szStr[i]!='\n')&&(szStr[i]!='\r')) break;
773 }
774
775 if(i == L)
776 {
777 szRet = DumpQString(GUICookie,szStr,g_szAsmCodeIndent, 50);
778 }
779 else
780 {
781DumpAsByteArray:
782 strcat_s(szString,SZSTRING_SIZE,KEYWORD("bytearray"));
783 strcat_s(szString,SZSTRING_SIZE," (");
784
785#if BIGENDIAN
786 SwapStringLength(pszString, cbString);
787#endif
788 DumpByteArray(szString,(BYTE*)pszString,cbString*sizeof(WCHAR),GUICookie);
789 szRet = &szString[strlen(szString)];
790 }
791 if(szStr) VDELETE(szStr);
792#if defined(ALIGN_ACCESS) || BIGENDIAN
793 if(pszStringCopy) VDELETE(pszStringCopy);
794#endif
795 return szRet;
796}
797
798// helper to avoid mixing of SEH and stack objects with destructors
799BOOL SourceLinesHelper(void *GUICookie, LineCodeDescr* pLCD, __out_ecount(nSize) WCHAR* pFileName, UINT nSize)
800{
801 _ASSERTE(nSize > 0);
802 memset(pFileName, 0, nSize * sizeof(WCHAR));
803
804 if(pLCD->FileToken == 0)
805 {
806 return FALSE;
807 }
808
809 struct Param
810 {
811 void *GUICookie;
812 LineCodeDescr* pLCD;
813 WCHAR* pFileName;
814 UINT nSize;
815 BOOL fRet;
816 } param;
817 param.GUICookie = GUICookie;
818 param.pLCD = pLCD;
819 param.pFileName = pFileName;
820 param.nSize = nSize;
821 param.fRet = FALSE;
822
823 PAL_TRY(Param *, pParam, &param) {
824 GUID guidLang={0},guidLangVendor={0},guidDoc={0};
825 WCHAR wzLang[64],wzVendor[64],wzDoc[64];
826 ULONG32 k;
827 if(pParam->pLCD->FileToken != ulWasFileToken)
828 {
829 ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetLanguage(&guidLang);
830 ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetLanguageVendor(&guidLangVendor);
831 ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetDocumentType(&guidDoc);
832 if(memcmp(&guidLang,&guidWasLang,sizeof(GUID))
833 ||memcmp(&guidLangVendor,&guidWasLangVendor,sizeof(GUID))
834 ||memcmp(&guidDoc,&guidWasDoc,sizeof(GUID)))
835 {
836 GuidToLPWSTR(guidLang,wzLang,64);
837 GuidToLPWSTR(guidLangVendor,wzVendor,64);
838 GuidToLPWSTR(guidDoc,wzDoc,64);
839 sprintf_s(szString,SZSTRING_SIZE,"%s%s '%ls', '%ls', '%ls'", g_szAsmCodeIndent,KEYWORD(".language"),
840 wzLang,wzVendor,wzDoc);
841 printLine(pParam->GUICookie,szString);
842 memcpy(&guidWasLang,&guidLang,sizeof(GUID));
843 memcpy(&guidWasLangVendor,&guidLangVendor,sizeof(GUID));
844 memcpy(&guidWasDoc,&guidDoc,sizeof(GUID));
845 }
846
847 /*
848 BOOL fHasEmbeddedSource=FALSE;
849 ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->HasEmbeddedSource(&fHasEmbeddedSource);
850 _snprintf_s(szString, _countof(szString), _TRUNCATE, "%s// PDB has %sembedded source",g_szAsmCodeIndent,
851 fHasEmbeddedSource ? "" : "no ");
852 printLine(pParam->GUICookie,szString);
853 */
854 }
855 ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetURL(pParam->nSize,&k,pParam->pFileName);
856 ulWasFileToken = pParam->pLCD->FileToken;
857 pParam->fRet = TRUE;
858 } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
859 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ERRORREOPENINGFILE),pLCD->FileToken);
860 printError(GUICookie, szString);
861 }
862 PAL_ENDTRY
863
864 return param.fRet;
865}
866
867#ifdef _PREFAST_
868#pragma warning(push)
869#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
870#endif
871BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs)
872{
873 DWORD PC;
874 BOOL fNeedNewLine = FALSE;
875 //char szString[4096];
876 char* szptr;
877 BYTE* pCode = NULL;
878 BOOL fTryInCode;
879
880 COR_ILMETHOD_DECODER method((COR_ILMETHOD*) ILHeader);
881
882 pCode = const_cast<BYTE*>(method.Code);
883
884 sprintf_s(szString,SZSTRING_SIZE, RstrUTF(IDS_E_CODESIZE),g_szAsmCodeIndent, method.GetCodeSize(), method.GetCodeSize());
885 printLine(GUICookie, szString);
886
887 if(method.GetCodeSize() == 0) return TRUE;
888
889 sprintf_s(szString,SZSTRING_SIZE, "%s%s %d",g_szAsmCodeIndent, KEYWORD(".maxstack"),method.GetMaxStack());
890 printLine(GUICookie, szString);
891
892 //------------ Source lines display ---------------------------------
893 ULONG32 ulLines =0;
894 LineCodeDescr* LineCode = NULL;
895 BOOL fShowSource = FALSE;
896 BOOL fInsertSourceLines = FALSE;
897 LineCodeDescr* pLCD = NULL;
898 ParamDescriptor* pszLVname = NULL;
899 ULONG ulVars=0;
900 char szVarPrefix[MAX_PREFIX_SIZE];
901 // scope handling:
902 DynamicArray<LexScope> daScope;
903 ULONG ulScopes=0;
904 DWORD dwScopeZOrder = 0;
905 ISymUnmanagedScope* pRootScope = NULL;
906 ISymUnmanagedMethod* pSymMethod = NULL;
907 char szFileName[2048];
908 ISymUnmanagedDocument* pMethodDoc[2] = {NULL,NULL};
909 ULONG32 ulMethodLine[2];
910 ULONG32 ulMethodCol[2];
911 BOOL fHasRangeInfo = FALSE;
912
913 strcpy_s(szVarPrefix,MAX_PREFIX_SIZE,"V0");
914 if(g_pSymReader)
915 {
916 g_pSymReader->GetMethod(FuncToken,&pSymMethod);
917 if(g_fShowSource || g_fInsertSourceLines)
918 {
919 if(pSymMethod)
920 {
921 unsigned ulActualLines=0; // VS compilers produce "Hidden" line numbers, don't count them
922 if(FAILED(pSymMethod->GetSourceStartEnd(pMethodDoc,ulMethodLine,ulMethodCol,&fHasRangeInfo)))
923 {
924 fHasRangeInfo = FALSE;
925 }
926 pSymMethod->GetSequencePointCount(&ulLines);
927 if (ulLines != 0)
928 {
929 LineCode = new LineCodeDescr[ulLines+2];
930 memset(LineCode, 0, sizeof(LineCodeDescr) * (ulLines + 2));
931 }
932 if(ulLines != 0 && LineCode != NULL)
933 {
934 pLCD = &LineCode[0];
935 if(fHasRangeInfo)
936 {
937 //printLine(GUICookie,"// Has source range info");
938 pLCD->Line = ulMethodLine[0];
939 pLCD->Column = ulMethodCol[0];
940 pLCD->PC = 0;
941 pLCD->FileToken = (ULONG_PTR)pMethodDoc[0];
942 ulActualLines++;
943 pLCD++;
944 }
945 if(ulLines)
946 {
947 ULONG32 *offsets=new ULONG32[ulLines], *lines=new ULONG32[ulLines], *columns=new ULONG32[ulLines];
948 ULONG32 *endlines=new ULONG32[ulLines], *endcolumns=new ULONG32[ulLines];
949 ISymUnmanagedDocument** docs = (ISymUnmanagedDocument**)(new PVOID[ulLines]);
950 ULONG32 actualCount;
951 pSymMethod->GetSequencePoints(ulLines,&actualCount, offsets,docs,lines,columns, endlines, endcolumns);
952 for(ULONG i = 0; i < ulLines; i++)
953 {
954 pLCD->Line = lines[i];
955 pLCD->Column = columns[i];
956 pLCD->LineEnd = endlines[i];
957 pLCD->ColumnEnd = endcolumns[i];
958 pLCD->PC = offsets[i];
959 pLCD->FileToken = (ULONG_PTR)docs[i];
960 ulActualLines++;
961 pLCD++;
962 }
963 VDELETE(offsets);
964 VDELETE(lines);
965 VDELETE(columns);
966 VDELETE(endlines);
967 VDELETE(endcolumns);
968 VDELETE(docs);
969 } // end if(ulLines)
970 if(fHasRangeInfo)
971 {
972 pLCD->Line = ulMethodLine[1];
973 pLCD->Column = ulMethodCol[1];
974 pLCD->PC = method.GetCodeSize();
975 pLCD->FileToken = (ULONG_PTR)pMethodDoc[1];
976 ulActualLines++;
977 pLCD++;
978 }
979
980 ulLines = ulActualLines;
981 qsort(LineCode,ulLines,sizeof(LineCodeDescr),cmpLineCode);
982 fShowSource = g_fShowSource;
983 fInsertSourceLines = g_fInsertSourceLines;
984 pLCD = &LineCode[0];
985 } // end if(LineCode)
986 } //end if (pSymMethod)
987 }//end if(g_fShowSource)
988 if (method.GetLocalVarSigTok())
989 {
990 // first, get the real number of local vars from signature
991 DWORD cbSigLen;
992 PCCOR_SIGNATURE pComSig;
993 mdSignature mdLocalVarSigTok = method.GetLocalVarSigTok();
994 if ((TypeFromToken(mdLocalVarSigTok) != mdtSignature) ||
995 (!pImport->IsValidToken(mdLocalVarSigTok)) || (RidFromToken(mdLocalVarSigTok) == 0))
996 {
997 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_BOGUSLVSIG),mdLocalVarSigTok);
998 printError(GUICookie,szString);
999 return FALSE;
1000 }
1001 if (FAILED(pImport->GetSigFromToken(mdLocalVarSigTok, &cbSigLen, &pComSig)))
1002 {
1003 sprintf_s(szString, SZSTRING_SIZE, RstrUTF(IDS_E_INVALIDRECORD), mdLocalVarSigTok);
1004 printError(GUICookie, szString);
1005 return FALSE;
1006 }
1007 _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
1008 pComSig++;
1009
1010 ULONG ulVarsInSig = CorSigUncompressData(pComSig);
1011 if(pSymMethod) pSymMethod->GetRootScope(&pRootScope);
1012 else pRootScope = NULL;
1013
1014 if(pRootScope)
1015 {
1016 ulVars = ulVarsInSig;
1017 }
1018 else ulVars = 0;
1019 if(ulVars)
1020 {
1021 ULONG ilvs;
1022 pszLVname = new ParamDescriptor[ulVars];
1023 memset(pszLVname,0,ulVars*sizeof(ParamDescriptor));
1024 for(ilvs = 0; ilvs < ulVars; ilvs++)
1025 {
1026 pszLVname[ilvs].name = new char[16];
1027 sprintf_s(pszLVname[ilvs].name,16,"V_%d",ilvs);
1028 pszLVname[ilvs].attr = ilvs;
1029 }
1030 LoadScope(pRootScope,&daScope,&ulScopes);
1031 qsort(&daScope[0],ulScopes,sizeof(LexScope),cmpLexScope);
1032 OpenScope(pRootScope,pszLVname,ulVars);
1033 sprintf_s(szVarPrefix,MAX_PREFIX_SIZE,"@%Id0",(size_t)pszLVname);
1034
1035#ifndef SHOW_LEXICAL_SCOPES
1036 for(unsigned jjj = 0; jjj < ulScopes; jjj++)
1037 {
1038 OpenScope(daScope[jjj].pISymScope,pszLVname,ulVars);
1039 daScope[jjj].pISymScope->Release();
1040 }
1041 ulScopes = 0;
1042#endif
1043 } //end if(ulLVScount)
1044 if(pRootScope) pRootScope->Release();
1045 } //end if (method.LocalVarSigTok)
1046 } //end if(g_pDebugImport)
1047 //-------------------------------------------------------------------
1048 g_tkRefUser = FuncToken;
1049 DumpLocals(pImport,&method, szVarPrefix, GUICookie);
1050 g_tkRefUser = 0;
1051
1052#if defined(_DEBUG)
1053 const BYTE* curFormat = pCode;
1054 #pragma warning(disable : 4640)
1055 static ILFormatter ilFormatter;
1056 static OutString formatOut;
1057 static OutString line;
1058 #pragma warning(default : 4640)
1059
1060 if (g_fPrettyPrint) {
1061 extern IMetaDataImport2* g_pPubImport;
1062 ilFormatter.init(g_pPubImport, method.Code, &method.Code[method.CodeSize], method.MaxStack, method.EH);
1063 }
1064#endif
1065
1066 PC = 0;
1067 fTryInCode = enumEHInfo(method.EH, pImport, method.GetCodeSize());
1068 DasmExceptionInfoClause* ehInfoToPutNext = NULL;
1069
1070 while (PC < method.GetCodeSize())
1071 {
1072 DWORD Len;
1073 DWORD i,ii;
1074 OPCODE instr;
1075 char sz[1024];
1076
1077 instr = DecodeOpcode(&pCode[PC], &Len);
1078 if (instr == CEE_COUNT)
1079 {
1080 sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_INSTRDECOD), pCode[PC],PC,PC);
1081 printError(GUICookie, szString);
1082 /*
1083 while (PC < method.CodeSize)
1084 {
1085 printf("%02x\n", pCode[PC]);
1086 PC++;
1087 }
1088 */
1089 return FALSE;
1090 }
1091
1092 if (fNeedNewLine)
1093 {
1094 fNeedNewLine = FALSE;
1095 printLine(GUICookie,"");
1096 }
1097
1098 if(fShowSource || fInsertSourceLines)
1099 {
1100 while(PC == pLCD->PC)
1101 {
1102 bIsNewFile = FALSE;
1103 if((pLCD->FileToken != ulWasFileToken) || (pLCD->Line < ulWasLine))
1104 {
1105 WCHAR wzFileName[2048];
1106 SourceLinesHelper(GUICookie, pLCD, wzFileName, 2048);
1107 bIsNewFile = (wcscmp(wzFileName,wzWasFileName)!=0);
1108 if(bIsNewFile||(pLCD->Line < ulWasLine))
1109 {
1110 wcscpy_s(wzWasFileName,2048,wzFileName);
1111 memset(szFileName,0,2048);
1112 WszWideCharToMultiByte(CP_UTF8,0,wzFileName,-1,szFileName,2048,NULL,NULL);
1113 if(fShowSource)
1114 {
1115 if(pFile) fclose(pFile);
1116 pFile = NULL;
1117 if(fopen_s(&pFile,szFileName,"rt") != 0)
1118 {
1119 char* pch = strrchr(szFileName,'\\');
1120 if(pch == NULL) pch = strrchr(szFileName,':');
1121 pFile = NULL;
1122 if(pch) fopen_s(&pFile,pch+1,"rt");
1123 }
1124 if(bIsNewFile)
1125 {
1126 sprintf_s(szString,SZSTRING_SIZE,"// Source File '%s' %s",szFileName,(pFile ? "" : "not found"));
1127 printLine(GUICookie, COMMENT(szString));
1128 }
1129 ulWasLine = 0;
1130 }
1131 }
1132 }
1133 if(fInsertSourceLines)
1134 {
1135 if(bIsNewFile)
1136 {
1137 const char* pszFN = ProperName(szFileName);
1138 sprintf_s(szString,SZSTRING_SIZE,(*pszFN == '\'' ? "%s%s %d,%d : %d,%d %s"
1139 : "%s%s %d,%d : %d,%d '%s'"),
1140 g_szAsmCodeIndent,KEYWORD(".line"),pLCD->Line,pLCD->LineEnd,
1141 pLCD->Column,pLCD->ColumnEnd,pszFN);
1142 }
1143 else
1144 sprintf_s(szString,SZSTRING_SIZE,"%s%s %d,%d : %d,%d ''",g_szAsmCodeIndent,KEYWORD(".line"),
1145 pLCD->Line,pLCD->LineEnd,pLCD->Column,pLCD->ColumnEnd);
1146
1147 printLine(GUICookie,szString);
1148 }
1149
1150 ULONG k= pLCD->Line;
1151 if(pFile)
1152 {
1153 for(k = ulWasLine; k < pLCD->Line; k++)
1154 {
1155 if(NULL==fgets(sz,1024,pFile)) { k--; break;}
1156 if((ulWasLine != 0)||(k == (pLCD->Line-1)))
1157 {
1158 while((sz[strlen(sz)-1]=='\n') || (sz[strlen(sz)-1]=='\r')) sz[strlen(sz)-1]=0;
1159 sprintf_s(szString,SZSTRING_SIZE,"//%6.6d: %s",k+1,sz);
1160 printLine(GUICookie, COMMENT(szString));
1161 }
1162 }
1163 ulWasLine = k;
1164 }
1165 if(pLCD < &LineCode[ulLines-1]) pLCD++;
1166 else { fShowSource = FALSE; break; }
1167 }
1168 }
1169 if(fTryInCode)
1170 {
1171 g_tkRefUser = FuncToken;
1172 // dumpOneEHInfo(ehInfoToPutNext,pImport,GUICookie); //doesn't do anything if ehInfoToPutNext == NULL
1173 g_tkRefUser = 0;
1174 ehInfoToPutNext = NULL;
1175
1176 for(ii = g_ehCount; ii > 0; ii--)
1177 {
1178 i = g_ehCount - ii;
1179 DWORD theEnd = g_ehInfo[i].GetHandlerOffset()+g_ehInfo[i].GetHandlerLength();
1180 if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
1181 {
1182 if(PC == theEnd)
1183 {
1184 // reduce indent, close }
1185 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1186 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end handler"));
1187 printLine(GUICookie,szString);
1188 if(g_fShowBytes)
1189 DumpHexEHInfo(&g_ehInfo[i], GUICookie);
1190 g_ehInfo[i].SetTryOffset(0xFF000000);
1191 g_ehInfo[i].SetHandlerOffset(0xFF000000);
1192 }
1193 }
1194 else
1195 {
1196 DWORD theTryEnd = g_ehInfo[i].GetTryOffset()+g_ehInfo[i].GetTryLength();
1197 if(theTryEnd > theEnd) theEnd = theTryEnd; // try block after the handler
1198 if(PC == theEnd) // If we've already found the first, don't skip to the next one
1199 ehInfoToPutNext = &g_ehInfo[i];
1200 }
1201 }
1202
1203 for(i = 0; i < g_ehCount; i++)
1204 {
1205 if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
1206 {
1207 if(g_ehInfo[i].GetFlags() & NEW_TRY_BLOCK)
1208 {
1209 if(PC == g_ehInfo[i].GetTryOffset()+g_ehInfo[i].GetTryLength())
1210 {
1211 // reduce indent, close }
1212 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1213 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end .try"));
1214 printLine(GUICookie,szString);
1215 }
1216 if(PC == g_ehInfo[i].GetTryOffset())
1217 {
1218 // Put try, {, increase indent
1219 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,KEYWORD(".try"));
1220 printLine(GUICookie,szString);
1221 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
1222 printLine(GUICookie,szString);
1223 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
1224 }
1225 }
1226
1227 DWORD dwFlags = g_ehInfo[i].GetFlags();
1228
1229 if ((dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER) && PC == g_ehInfo[i].GetFilterOffset())
1230 {
1231 // Dump filter clause, {, increase indent
1232 sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent, KEYWORD("filter"));
1233 printLine(GUICookie,szString);
1234 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
1235 printLine(GUICookie,szString);
1236 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
1237 }
1238
1239 if(PC == g_ehInfo[i].GetHandlerOffset())
1240 {
1241 if (dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER)
1242 {
1243 // reduce indent, close } (of the filter block)
1244 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1245 sprintf_s(szString,SZSTRING_SIZE, "%s%s %s", g_szAsmCodeIndent, UNSCOPE(), COMMENT("// end filter"));
1246
1247 // Dump handler clause, {, increase indent
1248 printLine(GUICookie,szString);
1249 sprintf_s(szString,SZSTRING_SIZE, "%s%s %s", g_szAsmCodeIndent, SCOPE(), COMMENT("// handler"));
1250 printLine(GUICookie,szString);
1251 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
1252 }
1253 else
1254 {
1255 // Dump catch or finally clause, {, increase indent
1256 if (dwFlags & COR_ILEXCEPTION_CLAUSE_FAULT)
1257 sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent, KEYWORD("fault"));
1258 else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FINALLY || IsNilToken(g_ehInfo[i].GetClassToken()))
1259 sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent,KEYWORD("finally"));
1260 else
1261 {
1262 CQuickBytes out;
1263 sprintf_s(szString,SZSTRING_SIZE, "%s%s %s ",g_szAsmCodeIndent,KEYWORD("catch"),
1264 PrettyPrintClass(&out, g_ehInfo[i].GetClassToken(), pImport));
1265 REGISTER_REF(FuncToken,g_ehInfo[i].GetClassToken());
1266 }
1267 printLine(GUICookie,szString);
1268 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
1269 printLine(GUICookie,szString);
1270 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
1271 }
1272 }
1273 } // end if(g_ehInfo[i].Flags & PUT_INTO_CODE)
1274 } // end for(i<g_ehCount)
1275 } // end if(fTryInCode)
1276 //----------------- lexical scope handling -----------------------------
1277 if(ulScopes) // non-zero only if local var info present
1278 {
1279 for(i=0; i < ulScopes; i++)
1280 {
1281 if(daScope[i].pISymScope != pRootScope)
1282 {
1283 if(daScope[i].IsOpen())
1284 {
1285 if(!daScope[i].Covers(PC))
1286 {
1287 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1288 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
1289 printLine(GUICookie,szString);
1290 daScope[i].dwZOrder = 0;
1291 dwScopeZOrder--;
1292 if(PC > daScope[i].dwEnd)
1293 {
1294 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope end (0x%8.8X) is not opcode-aligned"),
1295 g_szAsmCodeIndent,daScope[i].dwEnd);
1296 printLine(GUICookie,szString);
1297 }
1298 } // end if(!daScope[i].Covers(PC))
1299 }
1300 else // i.e., if scope is not open
1301 {
1302 if(daScope[i].Covers(PC))
1303 {
1304 if(g_fShowBytes)
1305 sprintf_s(szString,SZSTRING_SIZE,"%s%s // 0x%8.8X - 0x%8.8X",g_szAsmCodeIndent,SCOPE(),
1306 daScope[i].dwStart,daScope[i].dwEnd);
1307 else
1308 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
1309 printLine(GUICookie,szString);
1310 strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
1311 OpenScope(daScope[i].pISymScope,pszLVname,ulVars);
1312 DumpLocals(pImport,&method, szVarPrefix, GUICookie);
1313 dwScopeZOrder++;
1314 daScope[i].dwZOrder = dwScopeZOrder;
1315 if(PC > daScope[i].dwStart)
1316 {
1317 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope start (0x%8.8X) is not opcode-aligned"),
1318 g_szAsmCodeIndent,daScope[i].dwStart);
1319 printLine(GUICookie,szString);
1320 }
1321 } // end if(daScope[i].Covers(PC))
1322 } // end if(daScope[i].IsOpen()) -- else
1323 } // end if(daScope[i].pISymScope != pRootScope)
1324 } // end for(i=0; i < ulScopes; i++)
1325 } // end if(ulScopes)
1326
1327#if defined(_DEBUG)
1328 if (g_fPrettyPrint && &pCode[PC] >= curFormat) {
1329 formatOut.clear();
1330 curFormat = ilFormatter.formatStatement(curFormat, &formatOut);
1331 char* ptr = const_cast<char*>(formatOut.val());
1332 do {
1333 char* newLine = strchr(ptr, '\n');
1334 if (newLine)
1335 *newLine++ = 0;
1336 line.clear();
1337 line << COMMENT((char*)0)<<"// **** " << ptr<<COMMENT((char*)-1);
1338 printLine(GUICookie, const_cast<char*>(line.val()));
1339 ptr = newLine;
1340 } while (ptr != 0 && *ptr != 0);
1341 }
1342#endif
1343
1344 szptr = &szString[0];
1345 szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%sIL_%04x: ",g_szAsmCodeIndent, PC);
1346 if(g_fShowBytes)
1347 {
1348 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s/* ",COMMENT((char*)0));
1349 for(i=0; i<Len; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X",pCode[PC+i]);
1350 for(; i<2; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," "); // 2 is max.opcode length
1351 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," | ");
1352 }
1353
1354 PC += Len;
1355 Len = 0;
1356
1357 const char *pszInstrName = KEYWORD(OpcodeInfo[instr].pszName);
1358
1359 switch (OpcodeInfo[instr].Type)
1360 {
1361 DWORD tk;
1362 DWORD tkType;
1363 default:
1364 {
1365 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),RstrUTF(IDS_E_INSTRTYPE),
1366 OpcodeInfo[instr].Type,instr);
1367 printLine(GUICookie, szString);
1368 return FALSE;
1369 }
1370
1371#define PadTheString { if(Len < 16) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-*s", (16-Len), ""); \
1372 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," */%s ",COMMENT((char*)-1)); }
1373
1374 case InlineNone:
1375 {
1376 if(g_fShowBytes)
1377 PadTheString;
1378
1379 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), pszInstrName);
1380
1381 switch (instr)
1382 {
1383 case CEE_RET:
1384 case CEE_THROW:
1385 fNeedNewLine = TRUE;
1386 break;
1387 default:
1388 break;
1389 }
1390
1391 break;
1392 }
1393
1394 case ShortInlineI:
1395 case ShortInlineVar:
1396 {
1397 unsigned char ch= pCode[PC];
1398 short sh = OpcodeInfo[instr].Type==ShortInlineVar ? ch : (ch > 127 ? -(256-ch) : ch);
1399 if(g_fShowBytes)
1400 {
1401 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X ", ch);
1402 Len += 3;
1403 PadTheString;
1404 }
1405 switch(instr)
1406 {
1407 case CEE_LDARG_S:
1408 case CEE_LDARGA_S:
1409 case CEE_STARG_S:
1410 if(g_fThisIsInstanceMethod &&(ch==0))
1411 { // instance methods have arg0="this", do not label it!
1412 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, ch);
1413 }
1414 else
1415 {
1416 if(pszArgname)
1417 {
1418 unsigned char ch1 = g_fThisIsInstanceMethod ? ch-1 : ch;
1419 if(ch1 < ulArgs)
1420 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-10s %s",pszInstrName,
1421 ProperLocalName(pszArgname[ch1].name));
1422 else
1423 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_ARGINDEX)),pszInstrName, ch,ulArgs);
1424 }
1425 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s A_%d",pszInstrName, ch);
1426 }
1427 break;
1428
1429 case CEE_LDLOC_S:
1430 case CEE_LDLOCA_S:
1431 case CEE_STLOC_S:
1432 if(pszLVname)
1433 {
1434 if(ch < ulVars) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName,
1435 ProperLocalName(pszLVname[ch].name));
1436 else
1437 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_LVINDEX)),pszInstrName, ch, ulVars);
1438 }
1439 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s V_%d",pszInstrName, ch);
1440 break;
1441
1442 default:
1443 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName,sh);
1444 }
1445
1446 PC++;
1447 break;
1448 }
1449
1450 case InlineVar:
1451 {
1452 if(g_fShowBytes)
1453 {
1454 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X ", pCode[PC], pCode[PC+1]);
1455 Len += 5;
1456 PadTheString;
1457 }
1458
1459 USHORT v = pCode[PC] + (pCode[PC+1] << 8);
1460 long l = OpcodeInfo[instr].Type==InlineVar ? v : (v > 0x7FFF ? -(0x10000 - v) : v);
1461
1462 switch(instr)
1463 {
1464 case CEE_LDARGA:
1465 case CEE_LDARG:
1466 case CEE_STARG:
1467 if(g_fThisIsInstanceMethod &&(v==0))
1468 { // instance methods have arg0="this", do not label it!
1469 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, v);
1470 }
1471 else
1472 {
1473 if(pszArgname)
1474 {
1475 USHORT v1 = g_fThisIsInstanceMethod ? v-1 : v;
1476 if(v1 < ulArgs)
1477 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-10s %s",pszInstrName,
1478 ProperLocalName(pszArgname[v1].name));
1479 else
1480 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_ARGINDEX)),pszInstrName, v,ulArgs);
1481 }
1482 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s A_%d",pszInstrName, v);
1483 }
1484 break;
1485
1486 case CEE_LDLOCA:
1487 case CEE_LDLOC:
1488 case CEE_STLOC:
1489 if(pszLVname)
1490 {
1491 if(v < ulVars) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName,
1492 ProperLocalName(pszLVname[v].name));
1493 else
1494 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_LVINDEX)),pszInstrName, v,ulVars);
1495 }
1496 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s V_%d",pszInstrName, v);
1497 break;
1498
1499 default:
1500 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, l);
1501 break;
1502 }
1503 PC += 2;
1504 break;
1505 }
1506
1507 case InlineI:
1508 case InlineRVA:
1509 {
1510 DWORD v = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
1511 if(g_fShowBytes)
1512 {
1513 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1514 Len += 9;
1515 PadTheString;
1516 }
1517 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%x", pszInstrName, v);
1518 PC += 4;
1519 break;
1520 }
1521
1522 case InlineI8:
1523 {
1524 __int64 v = (__int64) pCode[PC] +
1525 (((__int64) pCode[PC+1]) << 8) +
1526 (((__int64) pCode[PC+2]) << 16) +
1527 (((__int64) pCode[PC+3]) << 24) +
1528 (((__int64) pCode[PC+4]) << 32) +
1529 (((__int64) pCode[PC+5]) << 40) +
1530 (((__int64) pCode[PC+6]) << 48) +
1531 (((__int64) pCode[PC+7]) << 56);
1532
1533 if(g_fShowBytes)
1534 {
1535 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),
1536 "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
1537 pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
1538 pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
1539 Len += 8*2;
1540 PadTheString;
1541 }
1542
1543 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%I64x", pszInstrName, v);
1544 PC += 8;
1545 break;
1546 }
1547
1548 case ShortInlineR:
1549 {
1550 __int32 v = (__int32) pCode[PC] +
1551 (((__int32) pCode[PC+1]) << 8) +
1552 (((__int32) pCode[PC+2]) << 16) +
1553 (((__int32) pCode[PC+3]) << 24);
1554
1555 float f = (float&)v;
1556
1557 if(g_fShowBytes)
1558 {
1559 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1560 Len += 9;
1561 PadTheString;
1562 }
1563
1564 char szf[32];
1565 if(f==0.0)
1566 strcpy_s(szf,32,((v>>24)==0)? "0.0" : "-0.0");
1567 else
1568 _gcvt_s(szf,32,(double)f, 8);
1569 float fd = (float)atof(szf);
1570 // Must compare as underlying bytes, not floating point otherwise optmizier will
1571 // try to enregister and comapre 80-bit precision number with 32-bit precision number!!!!
1572 if(((__int32&)fd == v)&&!IsSpecialNumber(szf))
1573 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf);
1574 else
1575 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X)",
1576 pszInstrName, pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1577 PC += 4;
1578 break;
1579 }
1580
1581 case InlineR:
1582 {
1583 __int64 v = (__int64) pCode[PC] +
1584 (((__int64) pCode[PC+1]) << 8) +
1585 (((__int64) pCode[PC+2]) << 16) +
1586 (((__int64) pCode[PC+3]) << 24) +
1587 (((__int64) pCode[PC+4]) << 32) +
1588 (((__int64) pCode[PC+5]) << 40) +
1589 (((__int64) pCode[PC+6]) << 48) +
1590 (((__int64) pCode[PC+7]) << 56);
1591
1592 double d = (double&)v;
1593
1594 if(g_fShowBytes)
1595 {
1596 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),
1597 "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
1598 pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
1599 pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
1600 Len += 8*2;
1601 PadTheString;
1602 }
1603 char szf[32],*pch;
1604 if(d==0.0)
1605 strcpy_s(szf,32,((v>>56)==0)? "0.0" : "-0.0");
1606 else
1607 _gcvt_s(szf,32,d, 17);
1608 double df = strtod(szf, &pch); //atof(szf);
1609 // Must compare as underlying bytes, not floating point otherwise optmizier will
1610 // try to enregister and comapre 80-bit precision number with 64-bit precision number!!!!
1611 if (((__int64&)df == v)&&!IsSpecialNumber(szf))
1612 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf);
1613 else
1614 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X)",
1615 pszInstrName, pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
1616 pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
1617 PC += 8;
1618 break;
1619 }
1620
1621 case ShortInlineBrTarget:
1622 {
1623 char offset = (char) pCode[PC];
1624 long dest = (PC + 1) + (long) offset;
1625
1626 if(g_fShowBytes)
1627 {
1628 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X ", pCode[PC]);
1629 Len += 3;
1630 PadTheString;
1631 }
1632 PC++;
1633 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s IL_%04x", pszInstrName, dest);
1634
1635 fNeedNewLine = TRUE;
1636 break;
1637 }
1638
1639 case InlineBrTarget:
1640 {
1641 long offset = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
1642 long dest = (PC + 4) + (long) offset;
1643
1644 if(g_fShowBytes)
1645 {
1646 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1647 Len += 9;
1648 PadTheString;
1649 }
1650 PC += 4;
1651 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s IL_%04x", pszInstrName, dest);
1652
1653 fNeedNewLine = TRUE;
1654 break;
1655 }
1656
1657 case InlineSwitch:
1658 {
1659 DWORD cases = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
1660
1661 if(g_fShowBytes)
1662 {
1663 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1664 Len += 9;
1665 PadTheString;
1666 }
1667 if(cases) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ( ", pszInstrName);
1668 else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ( )", pszInstrName);
1669 printLine(GUICookie, szString);
1670 PC += 4;
1671 DWORD PC_nextInstr = PC + 4 * cases;
1672 for (i = 0; i < cases; i++)
1673 {
1674 long offset = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
1675 long dest = PC_nextInstr + (long) offset;
1676 szptr = &szString[0];
1677 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",g_szAsmCodeIndent); //indent+label
1678 if(g_fShowBytes)
1679 {
1680 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"/* | %2.2X%2.2X%2.2X%2.2X ", // comment
1681 pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1682 Len = 9;
1683 PadTheString;
1684 }
1685
1686 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," IL_%04x%s", dest,(i == cases-1)? ")" : ",");
1687 PC += 4;
1688 printLine(GUICookie, szString);
1689 }
1690 continue;
1691 }
1692
1693 case InlinePhi:
1694 {
1695 DWORD cases = pCode[PC];
1696 unsigned short *pus;
1697 DWORD i;
1698
1699 if(g_fShowBytes)
1700 {
1701 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", cases);
1702 Len += 2;
1703 for(i=0; i < cases*2; i++)
1704 {
1705 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", pCode[PC+1+i]);
1706 Len += 2;
1707 }
1708 PadTheString;
1709 }
1710
1711 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s", pszInstrName);
1712 for(i=0, pus=(unsigned short *)(&pCode[PC+1]); i < cases; i++,pus++)
1713 {
1714 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %d",*pus);
1715 }
1716 PC += 2 * cases + 1;
1717 break;
1718 }
1719
1720 case InlineString:
1721 case InlineField:
1722 case InlineType:
1723 case InlineTok:
1724 case InlineMethod:
1725 {
1726 tk = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
1727 tkType = TypeFromToken(tk);
1728
1729 // Backwards compatible ldstr instruction.
1730 if (instr == CEE_LDSTR && TypeFromToken(tk) != mdtString)
1731 {
1732 const WCHAR *v1 = W("");
1733
1734 if(g_fShowBytes)
1735 {
1736 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ",
1737 pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1738 Len += 9;
1739 PadTheString;
1740 }
1741
1742 if(!g_pPELoader->getVAforRVA(tk, (void**) &v1))
1743 {
1744 char szStr[256];
1745 sprintf_s(szStr,256,RstrUTF(IDS_E_SECTHEADER),tk);
1746 printLine(GUICookie,szStr);
1747 }
1748 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ", pszInstrName);
1749 ConvToLiteral(szptr, v1, 0xFFFF);
1750 PC += 4;
1751 break;
1752 }
1753
1754 if(g_fShowBytes)
1755 {
1756 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "(%2.2X)%2.2X%2.2X%2.2X ",
1757 pCode[PC+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
1758 Len += 11;
1759 PadTheString;
1760 }
1761 PC += 4;
1762
1763 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ", pszInstrName);
1764
1765 if ((tk & 0xFF000000) == 0)
1766 {
1767 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%#x ", tk);
1768 break;
1769 }
1770 if(!pImport->IsValidToken(tk))
1771 {
1772 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" [ERROR: INVALID TOKEN 0x%8.8X] "),tk);
1773 break;
1774 }
1775 if(OpcodeInfo[instr].Type== InlineTok)
1776 {
1777 switch (tkType)
1778 {
1779 default:
1780 break;
1781
1782 case mdtMethodDef:
1783 case mdtMethodSpec:
1784 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
1785 break;
1786
1787 case mdtFieldDef:
1788 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
1789 break;
1790
1791 case mdtMemberRef:
1792 {
1793 PCCOR_SIGNATURE typePtr;
1794 const char* pszMemberName;
1795 ULONG cComSig;
1796
1797 if (FAILED(pImport->GetNameAndSigOfMemberRef(
1798 tk,
1799 &typePtr,
1800 &cComSig,
1801 &pszMemberName)))
1802 {
1803 szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "ERROR ");
1804 break;
1805 }
1806 unsigned callConv = CorSigUncompressData(typePtr);
1807
1808 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
1809 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
1810 else
1811 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
1812 break;
1813 }
1814 }
1815 }
1816 PrettyPrintToken(szString, tk, pImport,GUICookie,FuncToken); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
1817 break;
1818 }
1819
1820 case InlineSig:
1821 {
1822 if(g_fShowBytes)
1823 {
1824 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ",
1825 pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
1826 // output the offset and the raw bytes
1827 Len += 9;
1828 PadTheString;
1829 }
1830
1831 // get the signature token
1832 tk = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
1833 PC += 4;
1834 tkType = TypeFromToken(tk);
1835 if (tkType == mdtSignature)
1836 {
1837 // get the signature from the token
1838 DWORD cbSigLen;
1839 PCCOR_SIGNATURE pComSig;
1840 CQuickBytes qbMemberSig;
1841 if (FAILED(pImport->GetSigFromToken(tk, &cbSigLen, &pComSig)))
1842 {
1843 sprintf_s(szString, SZSTRING_SIZE, COMMENT("// ERROR: Invalid %08X record"), tk);
1844 break;
1845 }
1846
1847 qbMemberSig.Shrink(0);
1848 const char* pszTailSig = PrettyPrintSig(pComSig, cbSigLen, "", &qbMemberSig, pImport,NULL);
1849 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, pszTailSig);
1850 if (g_fDumpTokens)
1851 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X*/"),tk);
1852 }
1853 else
1854 {
1855 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG(RstrUTF(IDS_E_BADTOKENTYPE)), pszInstrName, tk);
1856 }
1857 break;
1858 }
1859 }
1860
1861 printLine(GUICookie, szString);
1862 } // end while (PC < method.CodeSize)
1863
1864 // We've finished looping over all the instructions,
1865 // Close of anything that may still be open
1866 // First, dump any remaining EH regions
1867 if(g_ehCount)
1868 {
1869 g_tkRefUser = FuncToken;
1870 DWORD i;
1871 if(fTryInCode)
1872 {
1873 for (DWORD ii = g_ehCount; ii > 0; ii--)
1874 {
1875 i = g_ehCount - ii;
1876 DWORD theEnd = g_ehInfo[i].GetHandlerOffset()+g_ehInfo[i].GetHandlerLength();
1877 if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
1878 {
1879 if(PC == theEnd)
1880 {
1881 // reduce indent, close }
1882 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1883 sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end handler"));
1884 printLine(GUICookie,szString);
1885 if(g_fShowBytes)
1886 DumpHexEHInfo(&g_ehInfo[i], GUICookie);
1887 g_ehInfo[i].SetTryOffset(0xFF000000);
1888 g_ehInfo[i].SetHandlerOffset(0xFF000000);
1889 }
1890 }
1891 }
1892 //dumpOneEHInfo(ehInfoToPutNext,pImport,GUICookie); //doesn't do anything if ehInfoToPutNext == NULL
1893 }
1894 bool fMoreToDisplay = false;
1895 for (i = 0; i < g_ehCount && !fMoreToDisplay; i++)
1896 fMoreToDisplay = !(g_ehInfo[i].GetTryOffset() == 0xFF000000 && g_ehInfo[i].GetHandlerOffset() == 0xFF000000);
1897 if (fMoreToDisplay)
1898 {
1899 sprintf_s(szString,SZSTRING_SIZE,"%sIL_%04x: ",g_szAsmCodeIndent, method.GetCodeSize()); //add dummy label
1900 printLine(GUICookie, szString);
1901 dumpEHInfo(pImport,GUICookie);
1902 }
1903 g_tkRefUser = 0;
1904 }
1905 //----------------- lexical scope handling -----------------------------
1906 if(ulScopes) // non-zero only if local var info present
1907 {
1908 for(unsigned i=0; i < ulScopes; i++)
1909 {
1910 if(daScope[i].pISymScope != pRootScope)
1911 {
1912 if((daScope[i].dwZOrder > 0)&&(PC >= daScope[i].dwEnd))
1913 {
1914 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1915 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
1916 printLine(GUICookie,szString);
1917 daScope[i].dwZOrder = 0;
1918 dwScopeZOrder--;
1919 if(PC > daScope[i].dwEnd)
1920 {
1921 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope end (0x%8.8X) is not opcode-aligned"),
1922 g_szAsmCodeIndent,daScope[i].dwEnd);
1923 printLine(GUICookie,szString);
1924 }
1925 }
1926 }
1927 daScope[i].pISymScope->Release();
1928 }
1929 }
1930 if(dwScopeZOrder != 0)
1931 {
1932 sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: %d unclosed lexical scopes, forcing closure."),
1933 g_szAsmCodeIndent,dwScopeZOrder);
1934 printLine(GUICookie,szString);
1935 for(DWORD i=0; i < dwScopeZOrder; i++)
1936 {
1937 g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
1938 sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
1939 printLine(GUICookie,szString);
1940 }
1941 }
1942 if(pSymMethod) pSymMethod->Release();
1943 if(LineCode) VDELETE(LineCode);
1944 if(pszLVname)
1945 {
1946 for(ULONG i = 0; i < ulVars; i++) SDELETE(pszLVname[i].name);
1947 VDELETE(pszLVname);
1948 }
1949// dumpEHInfo(pImport, GUICookie);
1950
1951 return TRUE;
1952}
1953#ifdef _PREFAST_
1954#pragma warning(pop)
1955#endif
1956
1957void SplitSignatureByCommas(__inout __nullterminated char* szString,
1958 __inout __nullterminated char* pszTailSig,
1959 mdToken tk,
1960 size_t indent,
1961 void* GUICookie)
1962{
1963 char chAfterComma;
1964 char *pComma, *pch;
1965 size_t i,j,k,l;
1966 if(indent < strlen(pszTailSig))
1967 {
1968 pComma = pszTailSig+indent;
1969 while((pComma = strchr(pComma,',')) != NULL)
1970 {
1971 for(pch = pszTailSig, i=0,j=0,k=0,l=0; pch < pComma; pch++)
1972 {
1973 if(*pch == '\'') j=1-j;
1974 else if(j==0)
1975 {
1976 if(*pch == '[') i++;
1977 else if(*pch == ']') i--;
1978 else if(*pch == '(') k++;
1979 else if(*pch == ')') k--;
1980 else if(strncmp(pch,LTN(),strlen(LTN()))==0) l++;
1981 else if(strncmp(pch,GTN(),strlen(GTN()))==0) l--;
1982 }
1983 }
1984 pComma++;
1985 if((i==0)&&(j==0)&&(k<=1)&&(l==0)) // no brackets or all opened/closed
1986 {
1987 chAfterComma = *pComma;
1988 *pComma = 0;
1989 printLine(GUICookie,pszTailSig);
1990 *pComma = chAfterComma;
1991 strcpy_s(pszTailSig,strlen(g_szAsmCodeIndent)+1,g_szAsmCodeIndent);
1992 for(i=(ULONG32)strlen(g_szAsmCodeIndent); i<indent; i++) pszTailSig[i] = ' ';
1993 strcpy_s(&pszTailSig[indent],strlen(pComma)+1,pComma);
1994 pComma = pszTailSig;
1995 }
1996 }
1997 }
1998 pch = szString;
1999 pch+=sprintf_s(pch,SZSTRING_SIZE,"%s",pszTailSig);
2000 if(g_fDumpTokens)
2001 pch+=sprintf_s(pch,SZSTRING_REMAINING_SIZE(pch),COMMENT(" /* %08X */"),tk);
2002}
2003
2004//#define TOKEN_SIG
2005#ifdef TOKEN_SIG
2006struct TokenSig
2007{
2008 size_t indent;
2009 char* str;
2010 TokenSig() { indent = 0; str = NULL; };
2011 ~TokenSig() { if(str) VDELETE(str); };
2012};
2013struct TokenSigArray
2014{
2015 TokenSig* ptsArray;
2016 ULONG ulCount;
2017 mdToken tkType;
2018 TokenSigArray(mdToken tk, IMDInternalImport *pImport)
2019 {
2020 HENUMInternal hEnum;
2021 pImport->EnumAllInit(tk,&hEnum);
2022 ulCount=pImport->EnumGetCount(&hEnum)+1;
2023 pImport->EnumClose(&hEnum);
2024 ptsArray = new TokenSig[ulCount];
2025 tkType = tk;
2026 };
2027 ~TokenSigArray()
2028 {
2029 VDELETE(ptsArray);
2030 }
2031};
2032
2033TokenSigArray *TSA_TD = NULL;
2034TokenSigArray *TSA_TR = NULL;
2035TokenSigArray *TSA_TS = NULL;
2036TokenSigArray *TSA_AR = NULL;
2037TokenSigArray *TSA_MR = NULL;
2038TokenSigArray *TSA_FD = NULL;
2039TokenSigArray *TSA_MD = NULL;
2040TokenSigArray *TSA_ME = NULL;
2041TokenSigArray *TSA_MS = NULL;
2042
2043#endif
2044void TokenSigInit(IMDInternalImport *pImport)
2045{
2046#ifdef TOKEN_SIG
2047 TSA_TD = new TokenSigArray(mdtTypeDef,pImport);
2048 TSA_TR = new TokenSigArray(mdtTypeRef,pImport);
2049 TSA_TS = new TokenSigArray(mdtTypeSpec,pImport);
2050 TSA_AR = new TokenSigArray(mdtAssemblyRef,pImport);
2051 TSA_MR = new TokenSigArray(mdtModuleRef,pImport);
2052 TSA_FD = new TokenSigArray(mdtFieldDef,pImport);
2053 TSA_MD = new TokenSigArray(mdtMethodDef,pImport);
2054 TSA_ME = new TokenSigArray(mdtMemberRef,pImport);
2055 TSA_MS = new TokenSigArray(mdtMethodSpec,pImport);
2056#endif
2057}
2058void TokenSigDelete()
2059{
2060#ifdef TOKEN_SIG
2061 SDELETE(TSA_TD);
2062 SDELETE(TSA_TR);
2063 SDELETE(TSA_TS);
2064 SDELETE(TSA_AR);
2065 SDELETE(TSA_MR);
2066 SDELETE(TSA_FD);
2067 SDELETE(TSA_MD);
2068 SDELETE(TSA_ME);
2069 SDELETE(TSA_MS);
2070#endif
2071}
2072
2073// Returns S_OK as TRUE or S_FALSE as FALSE or error code
2074HRESULT
2075IsGenericInst(mdToken tk, IMDInternalImport *pImport)
2076{
2077 HRESULT hr;
2078 if (TypeFromToken(tk) == mdtTypeSpec)
2079 {
2080 if (pImport->IsValidToken(tk))
2081 {
2082 ULONG cSig;
2083 PCCOR_SIGNATURE sig;
2084 IfFailRet(pImport->GetSigFromToken(tk, &cSig, &sig));
2085
2086 PCCOR_SIGNATURE sigEnd = sig + cSig;
2087 while (sig < sigEnd)
2088 {
2089 unsigned t = (unsigned)*sig;
2090 switch (t)
2091 {
2092 case ELEMENT_TYPE_PTR:
2093 case ELEMENT_TYPE_SZARRAY:
2094 case ELEMENT_TYPE_ARRAY:
2095 case ELEMENT_TYPE_BYREF:
2096 sig++;
2097 break;
2098 default:
2099 {
2100 if (*sig == ELEMENT_TYPE_GENERICINST)
2101 {
2102 return S_OK;
2103 }
2104 else
2105 {
2106 return S_FALSE;
2107 }
2108 }
2109 }
2110 }
2111 }
2112 }
2113 return S_FALSE;
2114}
2115
2116char* PrettyPrintMemberRef(__inout __nullterminated char* szString, mdToken tk, PCCOR_SIGNATURE pInstSig, ULONG cInstSig,
2117 IMDInternalImport *pImport, void* GUICookie, size_t* pIndent,
2118 CQuickBytes *pqbMemberSig)
2119{
2120 HRESULT hr;
2121 mdTypeRef cr;
2122 const char * pszMemberName;
2123 char* curPos;
2124 char* pszTailSig;
2125 char* pszOffset;
2126 PCCOR_SIGNATURE pComSig;
2127 ULONG cComSig;
2128 size_t L, indent;
2129 mdToken tkVarOwner = g_tkVarOwner;
2130 DWORD dwAttrs=0xFFFFFFFF; // used only if Parent==MethodDef
2131 mdToken tkMethodDef = 0; // used only if Parent==MethodDef
2132
2133 L = strlen(szString);
2134
2135 if (FAILED(pImport->GetNameAndSigOfMemberRef(
2136 tk,
2137 &pComSig,
2138 &cComSig,
2139 &pszMemberName)))
2140 {
2141 pComSig = NULL;
2142 cComSig = 0;
2143 pszMemberName = "Invalid MemberRef record";
2144 }
2145 MAKE_NAME_IF_NONE(pszMemberName,tk);
2146
2147 curPos = &szString[L+1];
2148 *curPos = 0;
2149 if (FAILED(pImport->GetParentOfMemberRef(tk, &cr)))
2150 {
2151 curPos += sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid MemberRef %08X record", tk);
2152 cr = mdTypeRefNil;
2153 }
2154 if (TypeFromToken(cr) == mdtMethodDef) //get the parent's parent
2155 {
2156 if (FAILED(pImport->GetMethodDefProps(cr, &dwAttrs)))
2157 {
2158 curPos += sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid MethodDef %08X record", cr);
2159 }
2160 tkMethodDef = cr;
2161
2162 mdTypeRef cr1;
2163 if(FAILED(pImport->GetParentToken(cr,&cr1))) cr1 = mdTypeRefNil;
2164 cr = cr1;
2165 }
2166 pqbMemberSig->Shrink(0);
2167 if (RidFromToken(cr)&&(cr != 0x02000001))
2168 {
2169 const char* pszClass = PrettyPrintClass(pqbMemberSig,cr,pImport);
2170 sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::",pszClass);
2171 pqbMemberSig->Shrink(0);
2172
2173 hr = IsGenericInst(cr,pImport);
2174 if (FAILED(hr))
2175 {
2176 sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid token %08X record", cr);
2177 }
2178 if (hr == S_OK)
2179 {
2180 g_tkVarOwner = 0;
2181 }
2182 }
2183 {
2184 char* curPos1 = &curPos[strlen(curPos)];
2185 if (IsMdPrivateScope(dwAttrs))
2186 {
2187 sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tkMethodDef);
2188 }
2189 else
2190 {
2191 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
2192 }
2193 if (tkMethodDef != 0)
2194 {
2195 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tkMethodDef));
2196 }
2197 else
2198 {
2199 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),ProperName(curPos1));
2200 }
2201 }
2202
2203 appendStr(pqbMemberSig, szString);
2204 if (pInstSig != NULL)
2205 {
2206 CQuickBytes qbInstSig;
2207 qbInstSig.Shrink(0);
2208 PrettyPrintSig(pInstSig, cInstSig, curPos, &qbInstSig, pImport, NULL);
2209 strcat_s(curPos,SZSTRING_REMAINING_SIZE(curPos), (char*) qbInstSig.Ptr());
2210 }
2211 pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, curPos, pqbMemberSig, pImport,NULL,(pInstSig==NULL));
2212 pszOffset = strstr(pszTailSig,curPos);
2213 indent = pszOffset - pszTailSig + strlen(curPos) + 1;
2214 if(pIndent) *pIndent = indent;
2215 g_tkVarOwner = tkVarOwner;
2216 return pszTailSig;
2217}
2218
2219char* PrettyPrintMethodDef(__inout __nullterminated char* szString, mdToken tk, PCCOR_SIGNATURE pInstSig, ULONG cInstSig,
2220 IMDInternalImport *pImport,void* GUICookie, size_t* pIndent,
2221 CQuickBytes *pqbMemberSig)
2222{
2223 HRESULT hr;
2224 mdTypeRef cr;
2225 const char * pszMemberName;
2226 char* curPos;
2227 char* pszTailSig;
2228 char* pszOffset;
2229 DWORD dwAttrs;
2230 PCCOR_SIGNATURE pComSig;
2231 ULONG cComSig;
2232 size_t L, indent;
2233 mdToken tkVarOwner = g_tkVarOwner;
2234
2235 L = strlen(szString);
2236 if (FAILED(pImport->GetNameOfMethodDef(tk, &pszMemberName)))
2237 {
2238 pszMemberName = "Invalid MethodDef record";
2239 }
2240 MAKE_NAME_IF_NONE(pszMemberName,tk);
2241 if (FAILED(pImport->GetMethodDefProps(tk, &dwAttrs)))
2242 {
2243 sprintf_s(szString, SZSTRING_SIZE, "Invalid MethodDef %08X record", tk);
2244 return szString;
2245 }
2246
2247 if (FAILED(pImport->GetSigOfMethodDef(tk, &cComSig, &pComSig)))
2248 {
2249 cComSig = 0;
2250 pComSig = NULL;
2251 }
2252
2253 hr = pImport->GetParentToken(
2254 tk,
2255 &cr
2256 );
2257 if (FAILED(hr))
2258 {
2259 strcat_s(szString, SZSTRING_SIZE, "??");
2260 return szString;
2261 }
2262 // use the tail as a buffer
2263 curPos = &szString[L+1];
2264 *curPos=0;
2265 pqbMemberSig->Shrink(0);
2266 if(RidFromToken(cr)&&(cr != 0x02000001))
2267 {
2268 const char* pszClass = PrettyPrintClass(pqbMemberSig,cr,pImport);
2269 sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::",pszClass);
2270 pqbMemberSig->Shrink(0);
2271
2272 hr = IsGenericInst(cr,pImport);
2273 if (FAILED(hr))
2274 {
2275 sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "/*Invalid token %08X record*/", cr);
2276 }
2277 if (hr == S_OK)
2278 {
2279 g_tkVarOwner = 0;
2280 }
2281 }
2282 {
2283 char* curPos1 = &curPos[strlen(curPos)];
2284 if(IsMdPrivateScope(dwAttrs))
2285 sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tk);
2286 else
2287 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
2288 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tk));
2289 }
2290 appendStr(pqbMemberSig, szString);
2291 if (pInstSig)
2292 {
2293 CQuickBytes qbInstSig;
2294 qbInstSig.Shrink(0);
2295 pszTailSig = (char*)PrettyPrintSig(pInstSig, cInstSig, curPos, &qbInstSig, pImport, NULL);
2296 strcat_s(curPos,SZSTRING_REMAINING_SIZE(curPos), (char*) qbInstSig.Ptr());
2297 }
2298
2299 pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, curPos, pqbMemberSig, pImport, NULL, (pInstSig == NULL));
2300 pszOffset = strstr(pszTailSig,curPos);
2301 indent = pszOffset - pszTailSig + strlen(curPos) + 1;
2302 if(pIndent) *pIndent = indent;
2303 g_tkVarOwner = tkVarOwner;
2304 return pszTailSig;
2305}
2306
2307void PrettyPrintTokenWithSplit(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport, void* GUICookie)
2308{
2309 CQuickBytes qbMemberSig;
2310 char* pszTailSig = NULL;
2311 size_t L, indent;
2312
2313 L = strlen(szString);
2314
2315#ifdef TOKEN_SIG
2316 TokenSig* SigToken=NULL;
2317 switch(TypeFromToken(tk))
2318 {
2319 case mdtMethodDef: SigToken = TSA_MD->ptsArray; break;
2320 case mdtMethodSpec: SigToken = TSA_MS->ptsArray; break;
2321 case mdtMemberRef: SigToken = TSA_ME->ptsArray; break;
2322 default: return; // other token types aren't served
2323 }
2324 if(SigToken[RidFromToken(tk)].str)
2325 {
2326 qbMemberSig.Shrink(0);
2327 appendStr(&qbMemberSig, szString);
2328 appendStr(&qbMemberSig, SigToken[RidFromToken(tk)].str);
2329 pszTailSig = asString(&qbMemberSig);
2330 indent = SigToken[RidFromToken(tk)].indent + L;
2331 }
2332 else
2333#endif
2334 {
2335 switch(TypeFromToken(tk))
2336 {
2337 case mdtMethodDef:
2338 pszTailSig = PrettyPrintMethodDef(szString,tk,NULL,0,pImport,GUICookie,&indent,&qbMemberSig);
2339 break;
2340 case mdtMemberRef:
2341 pszTailSig = PrettyPrintMemberRef(szString,tk,NULL,0,pImport,GUICookie,&indent,&qbMemberSig);
2342 break;
2343 case mdtMethodSpec:
2344 {
2345 mdToken meth=0;
2346 PCCOR_SIGNATURE pSig=NULL;
2347 ULONG cSig=0;
2348 mdToken tkMVarOwner = g_tkMVarOwner;
2349 g_tkMVarOwner = 0;
2350 if (FAILED(pImport->GetMethodSpecProps(tk, &meth, &pSig, &cSig)))
2351 {
2352 return;
2353 }
2354 pszTailSig = (TypeFromToken(meth) == mdtMethodDef) ?
2355 PrettyPrintMethodDef(szString,meth,pSig,cSig,pImport,GUICookie,&indent,&qbMemberSig) :
2356 PrettyPrintMemberRef(szString,meth,pSig,cSig,pImport,GUICookie,&indent,&qbMemberSig);
2357 g_tkMVarOwner = tkMVarOwner;
2358 }
2359 break;
2360 default:
2361 return;
2362 }
2363
2364#ifdef TOKEN_SIG
2365 SigToken[RidFromToken(tk)].str = new char[strlen(pszTailSig+L)+1];
2366 if(SigToken[RidFromToken(tk)].str)
2367 {
2368 strcpy_s(SigToken[RidFromToken(tk)].str,strlen(pszTailSig+L)+1,pszTailSig+L);
2369 SigToken[RidFromToken(tk)].indent = indent - L;
2370 }
2371#endif
2372 }
2373 SplitSignatureByCommas(szString,pszTailSig,tk,indent,GUICookie);
2374}
2375
2376void PrettyPrintToken(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport,void* GUICookie, mdToken FuncToken)
2377{
2378#ifdef TOKEN_SIG
2379
2380 TokenSig* SigToken=NULL;
2381
2382#endif
2383 char *szptr = &szString[strlen(szString)];
2384 if(!pImport->IsValidToken(tk))
2385 {
2386 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG("<invalid token 0x%8.8x>"), tk);
2387 return;
2388 }
2389 mdToken tkType = TypeFromToken(tk);
2390
2391 DWORD ix;
2392 for(ix = 0; ix < g_NumTypedefs; ix++)
2393 {
2394 if((*g_typedefs)[ix].tkTypeSpec == tk) break;
2395 }
2396 if(ix < g_NumTypedefs)
2397 {
2398 REGISTER_REF(FuncToken,tk);
2399 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf));
2400 return;
2401 }
2402
2403#ifdef TOKEN_SIG
2404 switch (tkType)
2405 {
2406 case mdtTypeDef: SigToken = TSA_TD->ptsArray; break;
2407 case mdtTypeRef: SigToken = TSA_TR->ptsArray; break;
2408 case mdtTypeSpec: SigToken = TSA_TS->ptsArray; break;
2409 case mdtAssemblyRef: SigToken = TSA_AR->ptsArray; break;
2410 case mdtModuleRef: SigToken = TSA_MR->ptsArray; break;
2411 case mdtFieldDef: SigToken = TSA_FD->ptsArray; break;
2412 default: SigToken = NULL; break;
2413 }
2414
2415 if(SigToken && SigToken[RidFromToken(tk)].str)
2416 {
2417 REGISTER_REF(FuncToken,tk);
2418 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),SigToken[RidFromToken(tk)].str);
2419 return;
2420 }
2421#endif
2422 CQuickBytes out;
2423 char* pszForTokenSig = NULL;
2424
2425 switch (tkType)
2426 {
2427 default:
2428 {
2429 szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG("<unknown token type 0x%02x>"), (BYTE) (tkType >> 24));
2430 pszForTokenSig = NULL;
2431 break;
2432 }
2433
2434 case mdtTypeDef:
2435 case mdtTypeRef:
2436 case mdtTypeSpec:
2437 case mdtAssemblyRef:
2438 case mdtAssembly:
2439 case mdtModuleRef:
2440 case mdtModule:
2441 {
2442 REGISTER_REF(FuncToken,tk);
2443 strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), PrettyPrintClass(&out, tk, pImport));
2444 pszForTokenSig = szptr;
2445 break;
2446 }
2447
2448 case mdtMethodDef:
2449 case mdtMemberRef:
2450 PrettyPrintTokenWithSplit(szString,tk,pImport,GUICookie);
2451 REGISTER_REF(FuncToken,tk);
2452 break;
2453
2454 case mdtMethodSpec:
2455 {
2456 mdToken meth=0;
2457 PCCOR_SIGNATURE pSig;
2458 ULONG cSig;
2459 if (FAILED(pImport->GetMethodSpecProps(tk, &meth, &pSig, &cSig)))
2460 {
2461 meth = mdTokenNil;
2462 }
2463 //g_tkMVarOwner = 0;
2464 PrettyPrintTokenWithSplit(szString,tk,pImport,GUICookie);
2465 REGISTER_REF(FuncToken,meth);
2466 break;
2467 }
2468
2469 case mdtFieldDef:
2470 {
2471 mdTypeRef cr=0;
2472 const char * pszMemberName;
2473 CQuickBytes qbMemberSig;
2474 DWORD dwAttrs;
2475
2476 PCCOR_SIGNATURE pComSig;
2477 ULONG cComSig;
2478
2479 REGISTER_REF(FuncToken,tk);
2480 if (FAILED(pImport->GetNameOfFieldDef(tk, &pszMemberName)))
2481 {
2482 strcat_s(szString, SZSTRING_SIZE, "??");
2483 break;
2484 }
2485 MAKE_NAME_IF_NONE(pszMemberName,tk);
2486 if (FAILED(pImport->GetFieldDefProps(tk, &dwAttrs)))
2487 {
2488 sprintf_s(szString, SZSTRING_SIZE, "Invalid FieldDef %08X record", tk);
2489 break;
2490 }
2491
2492 if (FAILED(pImport->GetSigOfFieldDef(tk, &cComSig, &pComSig)) ||
2493 FAILED(pImport->GetParentToken(tk, &cr)))
2494 {
2495 sprintf_s(szString, SZSTRING_SIZE, "Invalid FieldDef %08X record", tk);
2496 break;
2497 }
2498
2499 // use the tail as a buffer
2500 char* curPos = &szString[strlen(szString)+1];
2501 *curPos = 0;
2502 if((cr != 0x02000001) && RidFromToken(cr))
2503 {
2504 const char* pszClass = PrettyPrintClass(&out, cr, pImport);
2505 REGISTER_REF(FuncToken,cr);
2506 sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::", pszClass);
2507 }
2508 char* curPos1 = &curPos[strlen(curPos)];
2509 if(IsFdPrivateScope(dwAttrs))
2510 sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tk);
2511 else
2512 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
2513 strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tk));
2514 qbMemberSig.Shrink(0);
2515 strcpy_s(curPos-1,SZSTRING_REMAINING_SIZE(curPos), PrettyPrintSig(pComSig, cComSig, curPos, &qbMemberSig, pImport,NULL));
2516 curPos1 = &curPos[strlen(curPos)];
2517 if(g_fDumpTokens)
2518 sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),COMMENT(" /* %08X */"),tk);
2519 pszForTokenSig = szptr;
2520 break;
2521 }
2522
2523 case mdtString:
2524 {
2525 const WCHAR *pszString = NULL;
2526 ULONG cbString = 0;
2527 if (pImport->IsValidToken(tk))
2528 {
2529 if (FAILED(pImport->GetUserString(tk, &cbString, NULL, &pszString)))
2530 {
2531 pszString = NULL;
2532 }
2533 }
2534 if (pszString != NULL)
2535 {
2536 DumpUnicodeString(GUICookie,szString,(WCHAR *)pszString,cbString, true);
2537 }
2538 else
2539 {
2540 sprintf_s(szString,SZSTRING_SIZE,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tk);
2541 }
2542 if (g_fDumpTokens)
2543 sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT(" /* %08X */"),tk);
2544 break;
2545 }
2546 } //end switch(TypeFromToken(tk))
2547
2548#ifdef TOKEN_SIG
2549 if(SigToken && pszForTokenSig)
2550 {
2551 unsigned N = RidFromToken(tk);
2552 SigToken[N].str = new char[strlen(pszForTokenSig)+1];
2553 if(SigToken[N].str)
2554 strcpy_s(SigToken[N].str,strlen(pszForTokenSig)+1,pszForTokenSig);
2555 }
2556#endif
2557}
2558
2559/* not const char * const because it gets sorted at runtime; arguably a bad time to sort it. */
2560static const char* keyword[] = {
2561#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) s,
2562#define OPALIAS(alias_c, s, c) s,
2563#include "opcode.def"
2564#undef OPALIAS
2565#undef OPDEF
2566#define KYWD(name, sym, val) name,
2567#include "il_kywd.h"
2568#undef KYWD
2569};
2570static bool KywdNotSorted = TRUE;
2571static const char* szAllowedSymbols = "#_@$.";
2572static char DisallowedStarting[256];
2573static char DisallowedCont[256];
2574
2575struct Indx
2576{
2577 void* table[128];
2578 Indx() { memset(table,0,sizeof(table)); };
2579 ~Indx()
2580 {
2581 for(int i = 1; i < 128; i++) delete ((Indx*)(table[i]));
2582 };
2583 void IndexString(__in __nullterminated const char* psz, __out const char** pkywd)
2584 {
2585 int i = (int) *psz;
2586 if(i == 0)
2587 table[0] = pkywd;
2588 else
2589 {
2590 _ASSERTE((i > 0)&&(i <= 127));
2591 Indx* pInd = (Indx*)(table[i]);
2592 if(pInd == NULL)
2593 {
2594 pInd = new Indx;
2595 _ASSERTE(pInd);
2596 table[i] = pInd;
2597 }
2598 pInd->IndexString(psz+1,pkywd);
2599 }
2600 }
2601 const char** FindString(__in __nullterminated const char* psz)
2602 {
2603 if(*psz == 0)
2604 return (const char**)(table[0]);
2605 if(*psz > 0)
2606 {
2607 Indx* pInd = (Indx*)(table[(unsigned char)*psz]);
2608 return (pInd == NULL) ? NULL : pInd->FindString(psz+1);
2609 }
2610 return NULL;
2611 }
2612};
2613
2614/********************************************************************************/
2615/* looks up the keyword 'name' Returns FALSE on failure */
2616bool IsNameToQuote(const char *name)
2617{
2618 BYTE* p;
2619 BOOL bStarting;
2620 static Indx* indx;
2621
2622 if (indx==NULL)
2623 indx = new Indx();
2624
2625 if((name==NULL)||(*name==0)) return TRUE;
2626
2627 if(g_fQuoteAllNames)
2628 return ((strcmp(name,COR_CTOR_METHOD_NAME)!=0) && (strcmp(name,COR_CCTOR_METHOD_NAME)!=0));
2629
2630 if(KywdNotSorted)
2631 {
2632 int j;
2633 const char** const low = keyword;
2634 const char** const high = &keyword[sizeof(keyword) / sizeof(*keyword)];
2635 const char** mid;
2636 // name must start with alpha or one of allowed chars: #_$@.
2637 memset(DisallowedStarting,1,256);
2638 for(p = (BYTE*)szAllowedSymbols; *p; DisallowedStarting[*p]=0,p++);
2639 for(j='a'; j<= 'z'; DisallowedStarting[j]=0,j++);
2640 for(j='A'; j<= 'Z'; DisallowedStarting[j]=0,j++);
2641 // name must continue with the same chars, plus digits, and ? instead of #
2642 memcpy(DisallowedCont,DisallowedStarting,256);
2643 for(j='0'; j<= '9'; DisallowedCont[j]=0,j++);
2644 DisallowedCont[(unsigned char)'#'] = 1;
2645 DisallowedCont[(unsigned char)'?'] = 0;
2646 DisallowedCont[(unsigned char)'`'] = 0;
2647 // Sort the keywords for fast lookup
2648 for(mid = low; mid < high; mid++)
2649 {
2650 indx->IndexString(*mid,mid);
2651 }
2652 KywdNotSorted = FALSE;
2653 }
2654 //first, check for forbidden characters
2655 for(p = (BYTE*)name, bStarting = TRUE; *p; p++)
2656 {
2657 if(bStarting)
2658 {
2659 if(DisallowedStarting[*p]) return TRUE;
2660 }
2661 else
2662 {
2663 if(DisallowedCont[*p]) return TRUE;
2664 }
2665 bStarting = (*p == '.');
2666 if(bStarting && (*(p+1) == '.')) return TRUE;
2667 }
2668
2669 //second, check for matching keywords (remember: .ctor and .cctor are names AND keywords)
2670 if(indx->FindString((char*)name))
2671 {
2672 return ((strcmp(name,COR_CTOR_METHOD_NAME)!=0) && (strcmp(name,COR_CCTOR_METHOD_NAME)!=0));
2673 }
2674 //third, check if the name starts or ends with dot (.ctor and .cctor are out of the way)
2675 return ((*name == '.') || (name[strlen(name)-1] == '.'));
2676}
2677
2678/* Returns true if this name requires a single quote to be properly displayed as a local */
2679bool IsLocalToQuote(const char *name)
2680{
2681 // Anything that would otherwise require a quote gets a quote
2682 if (IsNameToQuote(name))
2683 return true;
2684 // No such thing as an empty name that doesn't require quoting (handled in IsNameToQuote)
2685 _ASSERTE(*name);
2686 // return true if there's a '.' anywhere in the name, after position 1
2687 return !!strchr(name + 1, '.');
2688}
2689
2690/********************************************************************/
2691/*
2692 * This is currently unused, with all calls to it commented out. In
2693 * the event that those calls return, add this function back.
2694static char* ConvNumericEscape(char* retBuff, unsigned val) {
2695 _ASSERTE(val < 256);
2696
2697 // print as octal
2698 *retBuff++ = '\\';
2699 *retBuff++ = (val >> 6) + '0';
2700 *retBuff++ = ((val >> 3) & 7) + '0';
2701 *retBuff++ = (val & 7) + '0';
2702 return(retBuff);
2703}
2704 */
2705
2706/********************************************************************/
2707/* returns the quoted version of a string (including the quotes) */
2708
2709static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbString)
2710{
2711 BOOL ret = TRUE;
2712 char* was_retBuff = retBuff;
2713
2714 *retBuff++ = '"';
2715
2716 for(int tally=0; (tally < cbString)&&ret; tally++)
2717 {
2718 if (*str > 255)
2719 {
2720 //retBuff = ConvNumericEscape(retBuff, *str >> 8);
2721 //retBuff = ConvNumericEscape(retBuff, *str & 0xFF);
2722 ret = FALSE;
2723 }
2724 else if(!isprint(*str))
2725 {
2726 if (*str == '\n')
2727 {
2728 *retBuff++ = '\\';
2729 *retBuff++ = 'n';
2730 }
2731 else
2732 //retBuff = ConvNumericEscape(retBuff, *str);
2733 ret = FALSE;
2734 }
2735 else if (*str == '"')
2736 {
2737 *retBuff++ = '\\';
2738 *retBuff++ = '"';
2739 }
2740 else if (*str == '\\')
2741 {
2742 *retBuff++ = '\\';
2743 *retBuff++ = '\\';
2744 }
2745 else if (*str == '\t')
2746 {
2747 *retBuff++ = '\\';
2748 *retBuff++ = 't';
2749 }
2750 else
2751 *retBuff++ = (char) *str;
2752 str++;
2753 }
2754 *retBuff++ = '"';
2755 *retBuff++ = 0;
2756 if(!ret) *was_retBuff = 0;
2757 return ret;
2758}
2759
2760bool IsSpecialNumber(const char* szf)
2761{
2762 return (strchr(szf, '#') != NULL)
2763 || (strstr(szf, "nan") != NULL) || (strstr(szf, "NAN") != NULL)
2764 || (strstr(szf, "inf") != NULL) || (strstr(szf, "INF") != NULL);
2765}
2766