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_ */ |
1228 | |