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
28class 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***********************************************************************/
45inline 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 * ------------------------------------------------------------------------- */
149struct SymVariable
150{
151private:
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
167public:
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 * ------------------------------------------------------------------------- */
293struct SymLexicalScope
294{
295private:
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?
302public:
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 * ------------------------------------------------------------------------- */
350struct SymUsingNamespace
351{
352private:
353
354 UINT32 m_ParentScope; // index of parent scope
355 UINT32 m_Name; // Index of name
356public:
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 * ------------------------------------------------------------------------- */
378struct SymConstant
379{
380private:
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
389public:
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 * ------------------------------------------------------------------------- */
463struct SymMethodInfo
464{
465private:
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
485public:
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 * ------------------------------------------------------------------------- */
597struct SymMap
598{
599 mdMethodDef m_MethodToken; // New Method token
600 UINT32 MethodEntry; // Method Entry
601};
602
603/* ------------------------------------------------------------------------- *
604 * SequencePoint struct
605 * ------------------------------------------------------------------------- */
606struct SequencePoint {
607
608private:
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
617public:
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 * ------------------------------------------------------------------------- */
681typedef struct DocumentInfo {
682
683private:
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
696public:
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
797template <class T>
798class ArrayStorage
799{
800public:
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
860private:
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
899typedef 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
912public:
913
914 MethodInfo() :
915 m_bytes( DEF_MISC_SPACE )
916 {
917 }
918} MethodInfo;
919
920/* ------------------------------------------------------------------------- *
921 * SymWriter class
922 * ------------------------------------------------------------------------- */
923
924class SymWriter : public ISymUnmanagedWriter3
925{
926public:
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
1099private:
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 //-----------------------------------------------------------
1121private:
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
1164class SymDocumentWriter : public ISymUnmanagedDocumentWriter
1165{
1166public:
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 //-----------------------------------------------------------
1212private:
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
1219struct 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_ */
1228