JIT: Fix bug in finally cloning caused by unsound callfinally reordering
[platform/upstream/coreclr.git] / src / debug / ildbsymlib / symwrite.h
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 // File: SymWrite.h
6 //
7
8 // ===========================================================================
9
10 #ifndef SYMWRITE_H_
11 #define SYMWRITE_H_
12 #ifdef _MSC_VER
13 #pragma warning(disable:4786)
14 #endif
15
16 #include <windows.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19
20 #include "cor.h"
21 #include "umisc.h"
22 #include "stgpool.h"
23 #include "safemath.h"
24
25 #include <corsym.h>
26 #include "pdbdata.h"
27
28 class SymDocumentWriter;
29
30 #if BIGENDIAN
31 /***
32 *PUBLIC void VariantSwap
33 *Purpose:
34 *  Swap the Variant members
35 *
36 *Entry:
37 *  SrcInBigEndian = whether pvarg is in BIGENDIAN or not
38 *  pvargDest = Destination variant
39 *  pvarg = pointer to a VARIANT to swap
40 *
41 *Exit:
42 *  Filled in pvarDest
43 *
44 ***********************************************************************/
45 inline HRESULT VariantSwap(bool SrcInBigEndian, VARIANT FAR *pvargDest, VARIANT FAR* pvarg)
46 {
47     if (pvargDest == NULL || pvarg == NULL)
48         return E_INVALIDARG;
49     VARTYPE vt = VT_EMPTY;
50
51     if (SrcInBigEndian)
52     {
53         vt = V_VT(pvarg);
54     }
55     *(UINT32*)pvargDest = VAL32(*(UINT32*)pvarg);
56     if (!SrcInBigEndian)
57     {
58         vt = V_VT(pvargDest);
59     }
60
61     switch (vt)
62     {
63         case VT_EMPTY:
64         case VT_NULL:
65             // No Value to swap
66             break;
67
68             // 1 byte
69         case VT_I1:
70         case VT_UI1:
71             V_I1(pvargDest) = V_I1(pvarg);
72             break;
73
74             // 2 bytes
75         case VT_I2:
76         case VT_UI2:
77         case VT_INT:
78         case VT_UINT:
79         case VT_BOOL:
80             V_I2(pvargDest) = VAL16(V_I2(pvarg));
81             break;
82
83             // 4 bytes
84         case VT_I4:
85         case VT_UI4:
86         case VT_R4:
87             V_I4(pvargDest) = VAL32(V_I4(pvarg));
88             break;
89
90             // 8 bytes
91         case VT_I8:
92         case VT_UI8:
93         case VT_R8:
94         case VT_DATE:
95             V_I8(pvargDest) = VAL64(V_I8(pvarg));
96             break;
97
98         case VT_DECIMAL:
99             DECIMAL_HI32(V_DECIMAL(pvargDest)) = VAL32(DECIMAL_HI32(V_DECIMAL(pvarg)));
100             DECIMAL_LO32(V_DECIMAL(pvargDest)) = VAL32(DECIMAL_LO32(V_DECIMAL(pvarg)));
101             DECIMAL_MID32(V_DECIMAL(pvargDest)) = VAL32(DECIMAL_MID32(V_DECIMAL(pvarg)));
102             break;
103
104         // These aren't currently supported
105         case VT_CY:         //6
106         case VT_BSTR:       //8
107         case VT_DISPATCH:   //9
108         case VT_ERROR:      //10
109         case VT_VARIANT:    //12
110         case VT_UNKNOWN:    //13
111         case VT_VOID:       //24
112         case VT_HRESULT:    //25
113         case VT_PTR:        //26
114         case VT_SAFEARRAY:  //27
115         case VT_CARRAY:     //28
116         case VT_USERDEFINED://29
117         case VT_LPSTR:      //30
118         case VT_LPWSTR:     //31
119         case VT_FILETIME:   //64
120         case VT_BLOB:       //65
121         case VT_STREAM:     //66
122         case VT_STORAGE:    //67
123         case VT_STREAMED_OBJECT:    //68
124         case VT_STORED_OBJECT:      //69
125         case VT_BLOB_OBJECT:        //70
126         case VT_CF:                 //71
127         case VT_CLSID:              //72
128         default:
129             _ASSERTE(!"NYI");
130             break;
131     }
132     return NOERROR;
133 }
134 #endif // BIGENDIAN
135
136 // Default space sizes for the various arrays. Make it too small in a
137 // checked build so we exercise the growing code.
138 #ifdef _DEBUG
139 #define DEF_LOCAL_SPACE 2
140 #define DEF_MISC_SPACE  64
141 #else
142 #define DEF_LOCAL_SPACE 64
143 #define DEF_MISC_SPACE  1024
144 #endif
145
146 /* ------------------------------------------------------------------------- *
147  * SymVariable struct
148  * ------------------------------------------------------------------------- */
149 struct SymVariable
150 {
151 private:
152     UINT32           m_Scope;       // index of parent scope
153     UINT32           m_Name;        // index into misc byte array
154     ULONG32          m_Attributes;  // Attributes
155     UINT32           m_Signature;       // index into misc byte array
156     ULONG32          m_SignatureSize;   // Signature size
157     ULONG32          m_AddrKind;    // Address Kind
158     ULONG32          m_Addr1;       // Additional info
159     ULONG32          m_Addr2;
160     ULONG32          m_Addr3;
161     ULONG32          m_StartOffset; // StartOffset
162     ULONG32          m_EndOffset;   // EndOffset
163     ULONG32          m_Sequence;
164     BOOL             m_IsParam;     // parameter?
165     BOOL             m_IsHidden;    // Is not visible to the user
166
167 public:
168     UINT32 Scope()
169     {
170         return VAL32(m_Scope);
171     }
172     void SetScope(UINT32 Scope)
173     {
174         m_Scope = VAL32(Scope);
175     }
176
177     UINT32 Name()
178     {
179         return VAL32(m_Name);
180     }
181     void SetName(UINT32 Name)
182     {
183         m_Name = VAL32(Name);
184     }
185
186     ULONG32 Attributes()
187     {
188         return VAL32(m_Attributes);
189     }
190     void SetAttributes(ULONG32 Attributes)
191     {
192         m_Attributes = VAL32(Attributes);
193     }
194
195     UINT32 Signature()
196     {
197         return VAL32(m_Signature);
198     }
199     void SetSignature(UINT32 Signature)
200     {
201         m_Signature = VAL32(Signature);
202     }
203     ULONG32 SignatureSize()
204     {
205         return VAL32(m_SignatureSize);
206     }
207     void SetSignatureSize(ULONG32 SignatureSize)
208     {
209         m_SignatureSize = VAL32(SignatureSize);
210     }
211
212     ULONG32 AddrKind()
213     {
214         return VAL32(m_AddrKind);
215     }
216     void SetAddrKind(ULONG32 AddrKind)
217     {
218         m_AddrKind = VAL32(AddrKind);
219     }
220     ULONG32 Addr1()
221     {
222         return VAL32(m_Addr1);
223     }
224     void SetAddr1(ULONG32 Addr1)
225     {
226         m_Addr1 = VAL32(Addr1);
227     }
228
229     ULONG32 Addr2()
230     {
231         return VAL32(m_Addr2);
232     }
233     void SetAddr2(ULONG32 Addr2)
234     {
235         m_Addr2 = VAL32(Addr2);
236     }
237
238     ULONG32 Addr3()
239     {
240         return VAL32(m_Addr3);
241     }
242     void SetAddr3(ULONG32 Addr3)
243     {
244         m_Addr3 = VAL32(Addr3);
245     }
246
247     ULONG32 StartOffset()
248     {
249         return VAL32(m_StartOffset);
250     }
251     void SetStartOffset(ULONG32 StartOffset)
252     {
253         m_StartOffset = VAL32(StartOffset);
254     }
255     ULONG32 EndOffset()
256     {
257         return VAL32(m_EndOffset);
258     }
259     void SetEndOffset(ULONG EndOffset)
260     {
261         m_EndOffset = VAL32(EndOffset);
262     }
263     ULONG32 Sequence()
264     {
265         return VAL32(m_Sequence);
266     }
267     void SetSequence(ULONG32 Sequence)
268     {
269         m_Sequence = VAL32(Sequence);
270     }
271
272     BOOL    IsParam()
273     {
274         return VAL32(m_IsParam);
275     }
276     void SetIsParam(BOOL IsParam)
277     {
278         m_IsParam = IsParam;
279     }
280     BOOL    IsHidden()
281     {
282         return VAL32(m_IsHidden);
283     }
284     void SetIsHidden(BOOL IsHidden)
285     {
286         m_IsHidden = IsHidden;
287     }
288 };
289
290 /* ------------------------------------------------------------------------- *
291  * SymLexicalScope struct
292  * ------------------------------------------------------------------------- */
293 struct SymLexicalScope
294 {
295 private:
296
297     UINT32 m_ParentScope;          // parent index (-1 for no parent)
298     ULONG32 m_StartOffset;    // start offset
299     ULONG32 m_EndOffset;      // end offset
300     BOOL    m_HasChildren;    // scope has children
301     BOOL    m_HasVars;        // scope has vars?
302 public:
303     UINT32  ParentScope()
304     {
305         return VAL32(m_ParentScope);
306     }
307     void SetParentScope(UINT32 ParentScope)
308     {
309         m_ParentScope = VAL32(ParentScope);
310     }
311
312     ULONG32 StartOffset()
313     {
314         return VAL32(m_StartOffset);
315     }
316     void SetStartOffset(ULONG32 StartOffset)
317     {
318         m_StartOffset = VAL32(StartOffset);
319     }
320     ULONG32 EndOffset()
321     {
322         return VAL32(m_EndOffset);
323     }
324     void SetEndOffset(ULONG32 EndOffset)
325     {
326         m_EndOffset = VAL32(EndOffset);
327     }
328     BOOL    HasChildren()
329     {
330         return m_HasChildren;
331     }
332     void SetHasChildren(BOOL HasChildren)
333     {
334         m_HasChildren = HasChildren;
335     }
336     BOOL    HasVars()
337     {
338         return m_HasVars;
339     }
340     void SetHasVars(BOOL HasVars)
341     {
342         m_HasVars = HasVars;
343     }
344
345 };
346
347 /* ------------------------------------------------------------------------- *
348  * SymUsingNamespace struct
349  * ------------------------------------------------------------------------- */
350 struct SymUsingNamespace
351 {
352 private:
353
354     UINT32  m_ParentScope;  // index of parent scope
355     UINT32  m_Name;         // Index of name
356 public:
357     UINT32  ParentScope()
358     {
359         return VAL32(m_ParentScope);
360     }
361     void SetParentScope(UINT32 ParentScope)
362     {
363         m_ParentScope = VAL32(ParentScope);
364     }
365     UINT32  Name()
366     {
367         return VAL32(m_Name);
368     }
369     void SetName(UINT32 Name)
370     {
371         m_Name = VAL32(Name);
372     }
373 };
374
375 /* ------------------------------------------------------------------------- *
376  * SymConstant struct
377  * ------------------------------------------------------------------------- */
378 struct SymConstant
379 {
380 private:
381
382     VARIANT m_Value;   // Constant Value
383     UINT32 m_ParentScope;   // Parent scope
384     UINT32 m_Name;          // Name index
385     UINT32 m_Signature;     // Signature index
386     ULONG32 m_SignatureSize;// Signature size
387     UINT32 m_ValueBstr; // If the variant is a bstr, store the string
388
389 public:
390     UINT32  ParentScope()
391     {
392         return VAL32(m_ParentScope);
393     }
394     void SetParentScope(UINT32 ParentScope)
395     {
396         m_ParentScope = VAL32(ParentScope);
397     }
398     UINT32  Name()
399     {
400         return VAL32(m_Name);
401     }
402     void SetName(UINT32 Name)
403     {
404         m_Name = VAL32(Name);
405     }
406     UINT32 Signature()
407     {
408         return VAL32(m_Signature);
409     }
410     void SetSignature(UINT32 Signature)
411     {
412         m_Signature = VAL32(Signature);
413     }
414     ULONG32 SignatureSize()
415     {
416         return VAL32(m_SignatureSize);
417     }
418     void SetSignatureSize(ULONG32 SignatureSize)
419     {
420         m_SignatureSize = VAL32(SignatureSize);
421     }
422     VARIANT Value(UINT32 *pValueBstr)
423     {   
424         *pValueBstr = VAL32(m_ValueBstr);
425 #if BIGENDIAN
426         VARIANT VariantValue;
427         VariantInit(&VariantValue);
428         // VT_BSTR's are dealt with ValueBStr
429         if (m_ValueBstr)
430         {
431             V_VT(&VariantValue) = VT_BSTR;
432         }
433         else
434         {
435             VariantSwap(false, &VariantValue, &m_Value);
436         }
437         return VariantValue;
438 #else   
439         return m_Value;
440 #endif
441     }
442     void SetValue(VARIANT VariantValue, UINT32 ValueBstr)
443     {
444         m_Value = VariantValue;
445         m_ValueBstr = VAL32(ValueBstr);
446 #if BIGENDIAN
447         // VT_BSTR's are dealt with ValueBStr
448         if (m_ValueBstr)
449         {
450             V_VT(&m_Value) = VAL16(VT_BSTR);
451         }
452         else
453         {
454             VariantSwap(true, &m_Value, &VariantValue);
455         }
456 #endif
457     }
458 };
459
460 /* ------------------------------------------------------------------------- *
461  * SymMethodInfo struct
462  * ------------------------------------------------------------------------- */
463 struct SymMethodInfo
464 {
465 private:
466
467     mdMethodDef     m_MethodToken;    // Method token
468
469     // Start/End Entries into the respective tables
470     // End values are extents - one past the last index (and so may actually be an index off
471     // the end of the array).  Start may equal end if the method has none of the item.
472     UINT32          m_StartScopes;
473     UINT32          m_EndScopes;
474     UINT32          m_StartVars;      
475     UINT32          m_EndVars;
476     UINT32          m_StartUsing;
477     UINT32          m_EndUsing;
478     UINT32          m_StartConstant;
479     UINT32          m_EndConstant;
480     UINT32          m_StartDocuments;
481     UINT32          m_EndDocuments;
482     UINT32          m_StartSequencePoints;
483     UINT32          m_EndSequencePoints;
484
485 public:
486     static int __cdecl compareMethods(const void *elem1, const void *elem2 );
487
488     mdMethodDef     MethodToken()
489     {
490         return VAL32(m_MethodToken);
491     }
492     void SetMethodToken(mdMethodDef MethodToken)
493     {
494         m_MethodToken = VAL32(MethodToken);
495     }
496     UINT32  StartScopes() 
497     { 
498         return VAL32(m_StartScopes);
499     }
500     void SetStartScopes(UINT32 StartScopes)
501     {
502         m_StartScopes = VAL32(StartScopes);
503     }
504     UINT32  EndScopes()
505     {
506         return VAL32(m_EndScopes);
507     }
508     void SetEndScopes(UINT32 EndScopes)
509     {
510         m_EndScopes = VAL32(EndScopes);
511     }
512     UINT32 StartVars()
513     {
514         return VAL32(m_StartVars);
515     }
516     void SetStartVars(UINT32 StartVars)
517     {
518         m_StartVars = VAL32(StartVars);
519     }
520     UINT32 EndVars()
521     {
522         return VAL32(m_EndVars);
523     }
524     void SetEndVars(UINT32 EndVars)
525     {
526         m_EndVars = VAL32(EndVars);
527     }
528     UINT32 StartUsing()
529     {
530         return VAL32(m_StartUsing);
531     }
532     void SetStartUsing(UINT32 StartUsing)
533     {
534         m_StartUsing = VAL32(StartUsing);
535     }
536     UINT32 EndUsing()
537     {
538         return VAL32(m_EndUsing);
539     }
540     void SetEndUsing(UINT32 EndUsing)
541     {
542         m_EndUsing = VAL32(EndUsing);
543     }
544     UINT32 StartConstant()
545     {
546         return VAL32(m_StartConstant);
547     }
548     void SetStartConstant(UINT32 StartConstant)
549     {
550         m_StartConstant = VAL32(StartConstant);
551     }
552     UINT32 EndConstant()
553     {
554         return VAL32(m_EndConstant);
555     }
556     void SetEndConstant(UINT32 EndConstant)
557     {
558         m_EndConstant = VAL32(EndConstant);
559     }
560     UINT32 StartDocuments()
561     {
562         return VAL32(m_StartDocuments);
563     }
564     void SetStartDocuments(UINT32 StartDocuments)
565     {
566         m_StartDocuments = VAL32(StartDocuments);
567     }
568     UINT32 EndDocuments()
569     {
570         return VAL32(m_EndDocuments);
571     }
572     void SetEndDocuments(UINT32 EndDocuments)
573     {
574         m_EndDocuments = VAL32(EndDocuments);
575     }
576     UINT32 StartSequencePoints()
577     {
578         return VAL32(m_StartSequencePoints);
579     }
580     void SetStartSequencePoints(UINT32 StartSequencePoints)
581     {
582         m_StartSequencePoints = VAL32(StartSequencePoints);
583     }
584     UINT32 EndSequencePoints()
585     {
586         return VAL32(m_EndSequencePoints);
587     }
588     void SetEndSequencePoints(UINT32 EndSequencePoints)
589     {
590         m_EndSequencePoints = VAL32(EndSequencePoints);
591     }
592 };
593
594 /* ------------------------------------------------------------------------- *
595  * SymMap struct
596  * ------------------------------------------------------------------------- */
597 struct SymMap
598 {
599     mdMethodDef     m_MethodToken;    // New Method token
600     UINT32          MethodEntry;      // Method Entry
601 };
602
603 /* ------------------------------------------------------------------------- *
604  * SequencePoint struct
605  * ------------------------------------------------------------------------- */
606 struct SequencePoint {
607
608 private:
609
610     DWORD   m_Offset;
611     DWORD   m_StartLine;
612     DWORD   m_StartColumn;
613     DWORD   m_EndLine;
614     DWORD   m_EndColumn;
615     DWORD   m_Document;
616
617 public:
618     bool IsWithin(ULONG32 line, ULONG32 column);
619     bool IsWithinLineOnly(ULONG32 line);
620     bool IsGreaterThan(ULONG32 line, ULONG32 column);
621     bool IsLessThan(ULONG32 line, ULONG32 column);
622     bool IsUserLine();
623     static int __cdecl compareAuxLines(const void *elem1, const void *elem2 );
624
625     DWORD Offset()
626     {
627         return VAL32(m_Offset);
628     }
629     void SetOffset(DWORD Offset)
630     {
631         m_Offset = VAL32(Offset);
632     }
633     DWORD StartLine()
634     {
635         return VAL32(m_StartLine);
636     }
637     void SetStartLine(DWORD StartLine)
638     {
639         m_StartLine = VAL32(StartLine);
640     }
641
642     DWORD StartColumn()
643     {
644         return VAL32(m_StartColumn);
645     }
646     void SetStartColumn(DWORD StartColumn)
647     {
648         m_StartColumn = VAL32(StartColumn);
649     }
650
651     DWORD EndLine()
652     {
653         return VAL32(m_EndLine);
654     }
655     void SetEndLine(DWORD EndLine)
656     {
657         m_EndLine = VAL32(EndLine);
658     }
659     DWORD EndColumn()
660     {
661         return VAL32(m_EndColumn);
662     }
663     void SetEndColumn(DWORD EndColumn)
664     {
665         m_EndColumn = VAL32(EndColumn);
666     }
667     DWORD Document()
668     {
669         return VAL32(m_Document);
670     }
671     void SetDocument(DWORD Document)
672     {
673         m_Document = VAL32(Document);
674     }
675 };
676
677
678 /* ------------------------------------------------------------------------- *
679  * DocumentInfo struct
680  * ------------------------------------------------------------------------- */
681 typedef struct DocumentInfo {
682
683 private:
684
685     GUID                m_Language;
686     GUID                m_LanguageVendor;
687     GUID                m_DocumentType;
688     GUID                m_AlgorithmId;
689     DWORD               m_CheckSumSize;
690     UINT32              m_CheckSumEntry;
691     UINT32              m_SourceSize;
692     UINT32              m_SourceEntry;
693     UINT32              m_UrlEntry;
694     SymDocumentWriter * m_pDocumentWriter;
695
696 public:
697
698     GUID Language()
699     {
700         GUID TmpGuid = m_Language;
701         SwapGuid(&TmpGuid);
702         return TmpGuid;
703     }
704     void SetLanguage(GUID Language)
705     {
706         SwapGuid(&Language);
707         m_Language = Language;
708     }
709     GUID LanguageVendor()
710     {
711         GUID TmpGuid = m_LanguageVendor;
712         SwapGuid(&TmpGuid);
713         return TmpGuid;
714     }
715     void SetLanguageVendor(GUID LanguageVendor)
716     {
717         SwapGuid(&LanguageVendor);
718         m_LanguageVendor = LanguageVendor;
719     }
720     GUID DocumentType()
721     {
722         GUID TmpGuid = m_DocumentType;
723         SwapGuid(&TmpGuid);
724         return TmpGuid;
725     }
726     void SetDocumentType(GUID DocumentType)
727     {
728         SwapGuid(&DocumentType);
729         m_DocumentType = DocumentType;
730     }
731
732     // Set the pointer to the SymDocumentWriter instance corresponding to this instance of DocumentInfo
733     // An argument of NULL will call Release
734     void SetDocumentWriter(SymDocumentWriter * pDoc);
735
736     // get the associated SymDocumentWriter
737     SymDocumentWriter * DocumentWriter()
738     {
739         return m_pDocumentWriter;
740     }
741
742     GUID AlgorithmId()
743     {
744         GUID TmpGuid = m_AlgorithmId;
745         SwapGuid(&TmpGuid);
746         return TmpGuid;
747     }
748     void SetAlgorithmId(GUID AlgorithmId)
749     {
750         SwapGuid(&AlgorithmId);
751         m_AlgorithmId = AlgorithmId;
752     }
753
754     DWORD CheckSumSize()
755     {
756         return VAL32(m_CheckSumSize);
757     }
758     void SetCheckSymSize(DWORD CheckSumSize)
759     {
760         m_CheckSumSize = VAL32(CheckSumSize);
761     }
762     UINT32 CheckSumEntry()
763     {
764         return VAL32(m_CheckSumEntry);
765     }
766     void SetCheckSumEntry(UINT32 CheckSumEntry)
767     {
768         m_CheckSumEntry = VAL32(CheckSumEntry);
769     }
770     UINT32 SourceSize()
771     {
772         return VAL32(m_SourceSize);
773     }
774     void SetSourceSize(UINT32 SourceSize)
775     {
776         m_SourceSize = VAL32(SourceSize);
777     }
778     UINT32 SourceEntry()
779     {
780         return VAL32(m_SourceEntry);
781     }
782     void SetSourceEntry(UINT32 SourceEntry)
783     {
784         m_SourceEntry = VAL32(SourceEntry);
785     }
786     UINT32 UrlEntry()
787     {
788         return VAL32(m_UrlEntry);
789     }
790     void SetUrlEntry(UINT32 UrlEntry)
791     {
792         m_UrlEntry = VAL32(UrlEntry);
793     }
794
795 } DocumentInfo; 
796
797 template <class T>
798 class ArrayStorage
799 {
800 public:
801
802     ArrayStorage( int initialSize = 0 )
803         : m_spaceSize(0),  m_instanceCount( 0 ), m_array( NULL )
804     {
805         grow( initialSize );
806     }
807     ~ArrayStorage()
808     {
809         
810         if ( m_array )
811             DELETEARRAY(m_array);
812         m_array = NULL;
813         m_spaceSize = 0;
814         m_instanceCount = 0;
815     }
816     T* next() 
817     {
818         if( !grow ( m_instanceCount ) ) 
819             return NULL;
820         _ASSERTE( m_instanceCount < m_spaceSize );
821         return &m_array[ m_instanceCount++ ];
822     }
823     bool grab(UINT32 n, UINT32 * pIndex) 
824     {
825         S_UINT32 newSize = S_UINT32(m_instanceCount) + S_UINT32(n);
826         if (newSize.IsOverflow())
827             return false;
828         if (!grow(newSize.Value())) 
829             return false;
830         _ASSERTE( m_instanceCount < m_spaceSize );
831         *pIndex = m_instanceCount;
832         m_instanceCount += n;
833         return true;
834     }
835
836     T& operator[]( UINT32 i ) {
837         _ASSERTE( i < m_instanceCount );
838         if (i >= m_instanceCount)
839         {
840             // Help mitigate the impact of buffer overflow
841             // Fail fast with a null-reference AV
842             volatile char* nullPointer = nullptr;
843             *nullPointer;
844         }
845         return m_array[ i ];
846     }
847     void reset() {
848         m_instanceCount = 0;
849     }
850     UINT32 size() {
851         return m_spaceSize;
852     }
853     UINT32 count() {
854         return m_instanceCount;
855     }
856
857     UINT32      m_spaceSize;     // Total size of array in elements
858     UINT32      m_instanceCount;   // total T's in the file
859     T          *m_array;         // array of T's
860 private:
861     bool grow( UINT32 n )
862     {
863         if (n >= m_spaceSize)
864         {
865             // Make a new, bigger array.
866             UINT32 newSpaceSize;
867
868             if (n == 0)
869                 newSpaceSize = DEF_LOCAL_SPACE;
870             else
871                 newSpaceSize = max( m_spaceSize * 2, n);
872
873             // Make sure we're not asking for more than 4GB of bytes to ensure no integer-overflow attacks are possible
874             S_UINT32 newBytes = S_UINT32(newSpaceSize) * S_UINT32(sizeof(T));
875             if (newBytes.IsOverflow())
876                 return false;
877
878             T *newTs;
879             newTs = NEW(T[newSpaceSize]);
880             if ( newTs == NULL )
881                 return false;
882
883             // Copy over the old Ts.
884             memcpy(newTs, m_array,
885                    sizeof(T) * m_spaceSize);
886
887             // Delete the old Ts.
888             DELETEARRAY(m_array);
889
890             // Hang onto the new array.
891             m_array = newTs;
892             m_spaceSize = newSpaceSize;
893         }
894         return true;
895     }
896
897 };
898
899 typedef struct MethodInfo {
900
901     ArrayStorage<SymMethodInfo> m_methods;    // Methods information
902     ArrayStorage<SymLexicalScope> m_scopes;   // Scope information for the method
903     ArrayStorage<SymVariable> m_vars;         // Variables
904     ArrayStorage<SymUsingNamespace> m_usings; // using/imports
905     ArrayStorage<SymConstant> m_constants;    // Constants
906     ArrayStorage<DocumentInfo> m_documents;   // Document Source Format
907     ArrayStorage<SequencePoint>  m_auxSequencePoints;  // Sequence Points
908     // Array of various bytes (variable signature, etc)
909     ArrayStorage<BYTE>  m_bytes;
910
911
912 public:
913
914   MethodInfo() :
915       m_bytes( DEF_MISC_SPACE )
916   {
917   }
918 } MethodInfo;
919
920 /* ------------------------------------------------------------------------- *
921  * SymWriter class
922  * ------------------------------------------------------------------------- */
923
924 class SymWriter : public ISymUnmanagedWriter3
925 {
926 public:
927     SymWriter();
928     virtual ~SymWriter();
929
930     //-----------------------------------------------------------
931     // IUnknown support
932     //-----------------------------------------------------------
933     ULONG STDMETHODCALLTYPE AddRef()
934     {
935         return (InterlockedIncrement((LONG *) &m_refCount));
936     }
937
938     ULONG STDMETHODCALLTYPE Release()
939     {
940         // Note that this must be thread-safe - it may be invoked on the finalizer thread
941         LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
942         if (refCount == 0)
943             DELETE(this);
944
945         return (refCount);
946     }
947     COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
948
949     //-----------------------------------------------------------
950     // ISymUnmanagedWriter
951     //-----------------------------------------------------------
952     COM_METHOD DefineDocument(const WCHAR *url,
953                               const GUID *language,
954                               const GUID *languageVendor,
955                               const GUID *documentType,
956                               ISymUnmanagedDocumentWriter **pRetVal);
957     COM_METHOD SetUserEntryPoint(mdMethodDef entryMethod);
958     COM_METHOD OpenMethod(mdMethodDef method);
959     COM_METHOD CloseMethod();
960     COM_METHOD DefineSequencePoints(ISymUnmanagedDocumentWriter *document,
961                                     ULONG32 spCount,
962                                     ULONG32 offsets[],
963                                     ULONG32 lines[],
964                                     ULONG32 columns[],
965                                     ULONG32 endLines[],
966                                     ULONG32 encColumns[]);
967     COM_METHOD OpenScope(ULONG32 startOffset, ULONG32 *scopeID);
968     COM_METHOD CloseScope(ULONG32 endOffset);
969     COM_METHOD SetScopeRange(ULONG32 scopeID, ULONG32 startOffset, ULONG32 endOffset);
970     COM_METHOD DefineLocalVariable(const WCHAR *name,
971                                    ULONG32 attributes,
972                                    ULONG32 cSig,
973                                    BYTE signature[],
974                                    ULONG32 addrKind,
975                                    ULONG32 addr1, ULONG32 addr2, ULONG32 addr3,
976                                    ULONG32 startOffset, ULONG32 endOffset);
977     COM_METHOD DefineParameter(const WCHAR *name,
978                                ULONG32 attributes,
979                                ULONG32 sequence,
980                                ULONG32 addrKind,
981                                ULONG32 addr1, ULONG32 addr2, ULONG32 addr3);
982     COM_METHOD DefineField(mdTypeDef parent,
983                            const WCHAR *name,
984                            ULONG32 attributes,
985                            ULONG32 cSig,
986                            BYTE signature[],
987                            ULONG32 addrKind,
988                            ULONG32 addr1, ULONG32 addr2, ULONG32 addr3);
989     COM_METHOD DefineGlobalVariable(const WCHAR *name,
990                                     ULONG32 attributes,
991                                     ULONG32 cSig,
992                                     BYTE signature[],
993                                     ULONG32 addrKind,
994                                     ULONG32 addr1, ULONG32 addr2, ULONG32 addr3);
995     COM_METHOD Close();
996     COM_METHOD SetSymAttribute(mdToken parent,
997                                const WCHAR *name,
998                                ULONG32 cData,
999                                BYTE data[]);
1000     COM_METHOD OpenNamespace(const WCHAR *name);
1001     COM_METHOD CloseNamespace();
1002     COM_METHOD UsingNamespace(const WCHAR *fullName);
1003     COM_METHOD SetMethodSourceRange(ISymUnmanagedDocumentWriter *startDoc,
1004                                     ULONG32 startLine,
1005                                     ULONG32 startColumn,
1006                                     ISymUnmanagedDocumentWriter *endDoc,
1007                                     ULONG32 endLine,
1008                                     ULONG32 endColumn);
1009     COM_METHOD GetDebugCVInfo(DWORD cData,
1010                            DWORD *pcData,
1011                            BYTE data[]);
1012
1013     COM_METHOD Initialize(IUnknown *emitter,
1014                         const WCHAR *filename,
1015                         IStream *pIStream,
1016                         BOOL fFullBuild);
1017
1018     COM_METHOD Initialize2(IUnknown *emitter,
1019                         const WCHAR *pdbTempPath,   // location to write pdb file
1020                         IStream *pIStream,
1021                         BOOL fFullBuild,
1022                         const WCHAR *pdbFinalPath); // location exe should contain for pdb file
1023                         
1024     COM_METHOD GetDebugInfo(IMAGE_DEBUG_DIRECTORY *pIDD,
1025                          DWORD cData,
1026                          DWORD *pcData,
1027                          BYTE data[]);
1028
1029     COM_METHOD RemapToken(mdToken oldToken,
1030                           mdToken newToken);
1031
1032     COM_METHOD DefineConstant(const WCHAR __RPC_FAR *name,
1033                         VARIANT value,
1034                         ULONG32 cSig,
1035                         unsigned char __RPC_FAR signature[  ]);
1036     
1037     COM_METHOD Abort(void);
1038
1039     //-----------------------------------------------------------
1040     // ISymUnmanagedWriter2
1041     //-----------------------------------------------------------
1042     COM_METHOD DefineLocalVariable2(const WCHAR *name,
1043                         ULONG32 attributes,
1044                         mdSignature sigToken,
1045                         ULONG32 addrKind,
1046                         ULONG32 addr1,
1047                         ULONG32 addr2,
1048                         ULONG32 addr3,
1049                         ULONG32 startOffset,
1050                         ULONG32 endOffset);
1051
1052     COM_METHOD DefineGlobalVariable2(const WCHAR *name,
1053                         ULONG32 attributes,
1054                         mdSignature sigToken,
1055                         ULONG32 addrKind,
1056                         ULONG32 addr1,
1057                         ULONG32 addr2,
1058                         ULONG32 addr3);
1059
1060     COM_METHOD DefineConstant2(const WCHAR *name,
1061                         VARIANT value,
1062                         mdSignature sigToken);
1063
1064     //-----------------------------------------------------------
1065     // ISymUnmanagedWriter3
1066     //-----------------------------------------------------------
1067
1068     COM_METHOD OpenMethod2(mdMethodDef method,
1069                         ULONG32 isect,
1070                         ULONG32 offset);
1071
1072     COM_METHOD Commit();
1073
1074     //-----------------------------------------------------------
1075     // Methods not exposed via a COM interface.
1076     //-----------------------------------------------------------
1077
1078     static HRESULT NewSymWriter(REFIID clsid, void** ppObj);
1079     HRESULT SetDocumentCheckSum(
1080             UINT32 DocumentEntry,
1081             GUID  AlgorithmId,
1082             DWORD CheckSumSize,
1083             BYTE* pCheckSum);
1084     HRESULT SetDocumentSrc(UINT32 DocumentEntry,
1085             DWORD SourceSize,
1086             BYTE* pSource);
1087
1088     COM_METHOD Write(void *pData, DWORD SizeOfData);
1089     COM_METHOD WriteStringPool();
1090     COM_METHOD WritePDB();
1091
1092     COM_METHOD Initialize(const WCHAR *szFilename, IStream *pIStream);
1093
1094     void SetFullPathName(const WCHAR *szFullPathName)
1095     {
1096         
1097     }
1098
1099 private:
1100     // Helper API for CloserScope
1101     COM_METHOD CloseScopeInternal(ULONG32 endOffset);
1102     HRESULT GetOrCreateDocument(
1103         const WCHAR *wcsUrl,          // Document name
1104         const GUID *pLanguage,        // What Language we're compiling
1105         const GUID *pLanguageVendor,  // What vendor
1106         const GUID *pDocumentType,    // Type
1107         ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
1108     );
1109     HRESULT CreateDocument(
1110         const WCHAR *wcsUrl,          // Document name
1111         const GUID *pLanguage,        // What Language we're compiling
1112         const GUID *pLanguageVendor,  // What vendor
1113         const GUID *pDocumentType,    // Type
1114         ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
1115     );
1116
1117
1118     //-----------------------------------------------------------
1119     // Data members
1120     //-----------------------------------------------------------
1121 private:
1122     UINT32      m_refCount; // AddRef/Release
1123
1124     mdMethodDef         m_openMethodToken;
1125     mdMethodDef         m_LargestMethodToken;
1126     SymMethodInfo     * m_pmethod;
1127
1128     // index of currently open scope
1129     UINT32 m_currentScope;
1130
1131     // special scope "index" meaning there is no such scope
1132     static const UINT32 k_noScope = (UINT32)-1;
1133
1134     // maximum scope end offset seen so far in this method
1135     ULONG32 m_maxScopeEnd;
1136
1137     MethodInfo m_MethodInfo;
1138     ArrayStorage<SymMap> m_MethodMap;    // Methods information
1139
1140     // Symbol File Name
1141     WCHAR m_szPath[ _MAX_PATH ];
1142     // File Handle
1143     HANDLE m_hFile;
1144     // Stream we're storing into if asked to.
1145     IStream* m_pIStream;
1146
1147     // StringPool we use to store the string into
1148     StgStringPool *m_pStringPool;
1149
1150     // Project level symbol information
1151     PDBInfo ModuleLevelInfo;
1152
1153     bool                m_closed;       // Have we closed the file yet?
1154     bool                m_sortLines;    // sort the line for current method
1155     bool                m_sortMethodEntries; // Sort the method entries
1156
1157
1158 };
1159
1160 /* ------------------------------------------------------------------------- *
1161  * SymDocumentWriter class
1162  * ------------------------------------------------------------------------- */
1163
1164 class SymDocumentWriter : public ISymUnmanagedDocumentWriter
1165 {
1166 public:
1167     SymDocumentWriter(UINT32 DocumentEntry,
1168                       SymWriter  *pEmitter);
1169
1170     virtual ~SymDocumentWriter();
1171
1172     //-----------------------------------------------------------
1173     // IUnknown support
1174     //-----------------------------------------------------------
1175     ULONG STDMETHODCALLTYPE AddRef()
1176     {
1177         return (InterlockedIncrement((LONG *) &m_refCount));
1178     }
1179
1180     ULONG STDMETHODCALLTYPE Release()
1181     {
1182         // Note that this must be thread-safe - it may be invoked on the finalizer thread
1183         LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
1184         if (refCount == 0)
1185             DELETE(this);
1186
1187         return (refCount);
1188     }
1189     COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
1190
1191     //-----------------------------------------------------------
1192     // ISymUnmanagedDocumentWriter
1193     //-----------------------------------------------------------
1194     COM_METHOD SetSource(ULONG32 sourceSize, BYTE source[]);
1195     COM_METHOD SetCheckSum(GUID algorithmId,
1196                            ULONG32 checkSumSize, BYTE checkSum[]);
1197
1198     //-----------------------------------------------------------
1199     // Methods not exposed via a COM interface.
1200     //-----------------------------------------------------------
1201     //
1202     // Commit the doc to the pdb
1203     //
1204     UINT32 GetDocumentEntry()
1205     {
1206         return m_DocumentEntry;
1207     }
1208
1209     //-----------------------------------------------------------
1210     // Data members
1211     //-----------------------------------------------------------
1212 private:
1213     UINT32 m_refCount; // AddRef/Release
1214     UINT32 m_DocumentEntry; // Entry into the documents array
1215     SymWriter *m_pEmitter;  // Associated SymWriter
1216 };
1217
1218 // Debug Info
1219 struct RSDSI                       // RSDS debug info
1220 {
1221     DWORD   dwSig;                 // RSDS
1222     GUID    guidSig;
1223     DWORD   age;
1224     char    szPDB[0];  // followed by a zero-terminated UTF8 file name
1225 };
1226
1227 #endif /* SYMWRITE_H_ */