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 // ===========================================================================
8 // ===========================================================================
13 #define CODE_WITH_NO_SOURCE 0xfeefee
14 // -------------------------------------------------------------------------
16 // -------------------------------------------------------------------------
18 //-----------------------------------------------------------
20 // Static function used to create a new instance of SymReader
21 //-----------------------------------------------------------
23 SymReader::NewSymReader(
29 SymReader* pSymReader = NULL;
31 _ASSERTE(IsValidCLSID(clsid));
32 _ASSERTE(IsValidWritePtr(ppObj, IUnknown*));
34 if (clsid != IID_ISymUnmanagedReader)
35 return (E_UNEXPECTED);
37 IfFalseGo(ppObj, E_INVALIDARG);
40 IfNullGo( pSymReader = NEW(SymReader()));
48 RELEASE( pSymReader );
54 //-----------------------------------------------------------
56 //-----------------------------------------------------------
57 SymReader::~SymReader()
62 //-----------------------------------------------------------
64 // Release all memory and clear initialized data structures
65 // (eg. as a result of a failed Initialization attempt)
66 //-----------------------------------------------------------
67 void SymReader::Cleanup()
72 for(i = 0; i < m_pPDBInfo->m_CountOfDocuments; i++)
81 // If we loaded from stream, then free the memory we allocated
82 if (m_fInitializeFromStream)
84 DELETEARRAY(m_DataPointers.m_pBytes);
85 DELETEARRAY(m_DataPointers.m_pConstants);
86 DELETEARRAY(m_DataPointers.m_pDocuments);
87 DELETEARRAY(m_DataPointers.m_pMethods);
88 DELETEARRAY(m_DataPointers.m_pScopes);
89 DELETEARRAY(m_DataPointers.m_pSequencePoints);
90 DELETEARRAY(m_DataPointers.m_pStringsBytes);
91 DELETEARRAY(m_DataPointers.m_pUsings);
92 DELETEARRAY(m_DataPointers.m_pVars);
101 memset(&m_DataPointers, 0, sizeof(PDBDataPointers));
105 //-----------------------------------------------------------
107 //-----------------------------------------------------------
109 SymReader::QueryInterface(
116 _ASSERTE(IsValidIID(riid));
117 _ASSERTE(IsValidWritePtr(ppvObject, void*));
119 IfFalseGo(ppvObject, E_INVALIDARG);
120 if (riid == IID_ISymUnmanagedReader)
122 *ppvObject = (ISymUnmanagedReader*) this;
125 if (riid == IID_IUnknown)
127 *ppvObject = (IUnknown*)this;
145 static HRESULT ReadFromStream(IStream *pIStream, void *pv, ULONG cb)
147 HRESULT hr = NOERROR;
150 IfFailGo(pIStream->Read(pv, cb, &ulBytesRead));
151 if (ulBytesRead != cb)
152 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
158 //-----------------------------------------------------------
160 // Pass in the required information to read in the debug info
161 // If a stream is passed in, it is used, otherwise a filename
163 //-----------------------------------------------------------
164 HRESULT SymReader::Initialize(
165 IUnknown *importer, // Cash it to be consistent with CLR
166 const WCHAR* szFileName, // File name of the ildb
167 const WCHAR* szsearchPath, // Search Path
168 IStream *pIStream // IStream
171 HRESULT hr = NOERROR;
172 _ASSERTE(szFileName || pIStream);
173 IfFalseGo(szFileName || pIStream, E_INVALIDARG );
175 _ASSERTE(!m_fInitialized);
176 IfFalseGo(!m_fInitialized, E_UNEXPECTED);
178 // If it's passed in, we need to AddRef to be consistent the
179 // desktop version since ReleaseImporterFromISymUnmanagedReader (ceeload.cpp)
180 // assumes there's an addref
183 m_pImporter = importer;
184 m_pImporter->AddRef();
187 // See if we're reading from a file or stream
188 if (pIStream == NULL)
190 // We're initializing from a file
191 m_fInitializeFromStream = false;
192 IfFailGo(InitializeFromFile(szFileName, szsearchPath));
196 // We're reading in from a stream
197 m_fInitializeFromStream = true;
198 IfFailGo(InitializeFromStream(pIStream));
201 // Note that up to this point, the data we've read in has not been validated. Since we don't trust
202 // our input, it's important that we don't proceed with using this data until validation has been
204 IfFailGo(ValidateData());
208 // If we have not succeeded, then we need to clean up our data structures. This would allow a client to call
209 // Initialize again, but also ensures we can't possibly use partial or otherwise invalid (possibly
217 // Otherwise we are not properly initialized
218 m_fInitialized = true;
224 //-----------------------------------------------------------
225 // Initialize the data structures by reading from the supplied stream
226 // Note that upon completion the data has not yet been validated for safety.
227 //-----------------------------------------------------------
228 HRESULT SymReader::InitializeFromStream(
229 IStream *pIStream // IStream
236 // Reset the stream to the begining
241 // Make sure we're at the beginning of the stream
242 IfFailGo(pIStream->Seek(li, STREAM_SEEK_SET, NULL));
244 IfNullGo(pSignature = (BYTE *)_alloca(ILDB_SIGNATURE_SIZE));
245 IfFailGo(ReadFromStream(pIStream, pSignature, ILDB_SIGNATURE_SIZE));
247 // Verify that we're looking at an ILDB File
248 if (memcmp(pSignature, ILDB_SIGNATURE, ILDB_SIGNATURE_SIZE))
250 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
253 IfFailGo(ReadFromStream(pIStream, &GuidVersion, sizeof(GUID)));
255 SwapGuid(&GuidVersion);
257 if (memcmp(&GuidVersion, &ILDB_VERSION_GUID, sizeof(GUID)))
259 IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
262 IfNullGo(m_pPDBInfo = NEW(PDBInfo));
264 memset(m_pPDBInfo, 0 , sizeof(PDBInfo));
265 IfFailGo(ReadFromStream(pIStream, m_pPDBInfo, sizeof(PDBInfo)));
268 m_pPDBInfo->ConvertEndianness();
270 if (m_pPDBInfo->m_CountOfConstants)
272 IfNullGo(m_DataPointers.m_pConstants = NEW(SymConstant[m_pPDBInfo->m_CountOfConstants]));
273 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pConstants, m_pPDBInfo->m_CountOfConstants*sizeof(SymConstant)));
276 if (m_pPDBInfo->m_CountOfMethods)
278 IfNullGo(m_DataPointers.m_pMethods = NEW(SymMethodInfo[m_pPDBInfo->m_CountOfMethods]));
279 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pMethods, m_pPDBInfo->m_CountOfMethods*sizeof(SymMethodInfo)));
282 if (m_pPDBInfo->m_CountOfScopes)
284 IfNullGo(m_DataPointers.m_pScopes = NEW(SymLexicalScope[m_pPDBInfo->m_CountOfScopes]));
285 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pScopes, m_pPDBInfo->m_CountOfScopes*sizeof(SymLexicalScope)));
288 if (m_pPDBInfo->m_CountOfVars)
290 IfNullGo(m_DataPointers.m_pVars = NEW(SymVariable[m_pPDBInfo->m_CountOfVars]));
291 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pVars, m_pPDBInfo->m_CountOfVars*sizeof(SymVariable)));
294 if (m_pPDBInfo->m_CountOfUsing)
296 IfNullGo(m_DataPointers.m_pUsings = NEW(SymUsingNamespace[m_pPDBInfo->m_CountOfUsing]));
297 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pUsings, m_pPDBInfo->m_CountOfUsing*sizeof(SymUsingNamespace)));
300 if (m_pPDBInfo->m_CountOfSequencePoints)
302 IfNullGo(m_DataPointers.m_pSequencePoints = NEW(SequencePoint[m_pPDBInfo->m_CountOfSequencePoints]));
303 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pSequencePoints, m_pPDBInfo->m_CountOfSequencePoints*sizeof(SequencePoint)));
306 if (m_pPDBInfo->m_CountOfDocuments)
308 IfNullGo(m_DataPointers.m_pDocuments = NEW(DocumentInfo[m_pPDBInfo->m_CountOfDocuments]));
309 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pDocuments, m_pPDBInfo->m_CountOfDocuments*sizeof(DocumentInfo)));
312 if (m_pPDBInfo->m_CountOfBytes)
314 IfNullGo(m_DataPointers.m_pBytes = NEW(BYTE[m_pPDBInfo->m_CountOfBytes]));
315 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pBytes, m_pPDBInfo->m_CountOfBytes*sizeof(BYTE)));
319 if (m_pPDBInfo->m_CountOfStringBytes)
321 IfNullGo(m_DataPointers.m_pStringsBytes = NEW(BYTE[m_pPDBInfo->m_CountOfStringBytes]));
322 IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pStringsBytes, m_pPDBInfo->m_CountOfStringBytes));
329 //-----------------------------------------------------------
331 // Checks the contents of everything in m_DataPointers (i.e. all the structures read from the file)
332 // to make sure it is valid. Specifically, validates that all indexes are within bounds for the
334 //-----------------------------------------------------------
335 HRESULT SymReader::ValidateData()
339 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfConstants; i++)
341 SymConstant & c = m_DataPointers.m_pConstants[i];
342 IfFalseGo(c.ParentScope() < m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
343 IfFalseGo(c.Name() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
344 IfFailGo(ValidateBytes(c.Signature(), c.SignatureSize()));
347 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfMethods; i++)
349 // Note that start/end values may equal the count (i.e. point one past the end) because
350 // the end is the extent, and start can equal end to indicate no entries.
351 SymMethodInfo & m = m_DataPointers.m_pMethods[i];
352 IfFalseGo(m.StartScopes() <= m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
353 IfFalseGo(m.EndScopes() <= m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
354 IfFalseGo(m.StartScopes() <= m.EndScopes(), HrFromWin32(ERROR_BAD_FORMAT));
355 IfFalseGo(m.StartVars() <= m_pPDBInfo->m_CountOfVars, HrFromWin32(ERROR_BAD_FORMAT));
356 IfFalseGo(m.EndVars() <= m_pPDBInfo->m_CountOfVars, HrFromWin32(ERROR_BAD_FORMAT));
357 IfFalseGo(m.StartVars() <= m.EndVars(), HrFromWin32(ERROR_BAD_FORMAT));
358 IfFalseGo(m.StartUsing() <= m_pPDBInfo->m_CountOfUsing, HrFromWin32(ERROR_BAD_FORMAT));
359 IfFalseGo(m.EndUsing() <= m_pPDBInfo->m_CountOfUsing, HrFromWin32(ERROR_BAD_FORMAT));
360 IfFalseGo(m.StartUsing() <= m.EndUsing(), HrFromWin32(ERROR_BAD_FORMAT));
361 IfFalseGo(m.StartConstant() <= m_pPDBInfo->m_CountOfConstants, HrFromWin32(ERROR_BAD_FORMAT));
362 IfFalseGo(m.EndConstant() <= m_pPDBInfo->m_CountOfConstants, HrFromWin32(ERROR_BAD_FORMAT));
363 IfFalseGo(m.StartConstant() <= m.EndConstant(), HrFromWin32(ERROR_BAD_FORMAT));
364 IfFalseGo(m.StartDocuments() <= m_pPDBInfo->m_CountOfDocuments, HrFromWin32(ERROR_BAD_FORMAT));
365 IfFalseGo(m.EndDocuments() <= m_pPDBInfo->m_CountOfDocuments, HrFromWin32(ERROR_BAD_FORMAT));
366 IfFalseGo(m.StartDocuments() <= m.EndDocuments(), HrFromWin32(ERROR_BAD_FORMAT));
367 IfFalseGo(m.StartSequencePoints() <= m_pPDBInfo->m_CountOfSequencePoints, HrFromWin32(ERROR_BAD_FORMAT));
368 IfFalseGo(m.EndSequencePoints() <= m_pPDBInfo->m_CountOfSequencePoints, HrFromWin32(ERROR_BAD_FORMAT));
369 IfFalseGo(m.StartSequencePoints() <= m.EndSequencePoints(), HrFromWin32(ERROR_BAD_FORMAT));
372 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfScopes; i++)
374 SymLexicalScope & s = m_DataPointers.m_pScopes[i];
375 IfFalseGo((s.ParentScope() == (UINT32)-1) || (s.ParentScope() < m_pPDBInfo->m_CountOfScopes), HrFromWin32(ERROR_BAD_FORMAT));
378 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfVars; i++)
380 SymVariable & v = m_DataPointers.m_pVars[i];
381 IfFalseGo(v.Scope() < m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
382 IfFalseGo(v.Name() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
383 IfFailGo(ValidateBytes(v.Signature(), v.SignatureSize()));
386 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfUsing; i++)
388 SymUsingNamespace & u = m_DataPointers.m_pUsings[i];
389 IfFalseGo(u.ParentScope() < m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
390 IfFalseGo(u.Name() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
393 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfSequencePoints; i++)
395 SequencePoint & s = m_DataPointers.m_pSequencePoints[i];
396 IfFalseGo(s.Document() < m_pPDBInfo->m_CountOfDocuments, HrFromWin32(ERROR_BAD_FORMAT));
399 for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfDocuments; i++)
401 DocumentInfo & d = m_DataPointers.m_pDocuments[i];
402 IfFailGo(ValidateBytes(d.CheckSumEntry(), d.CheckSumSize()));
403 IfFailGo(ValidateBytes(d.SourceEntry(), d.SourceSize()));
404 IfFalseGo(d.UrlEntry() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
407 // Nothing to validate for the m_pBytes array - each reference must validate above that it's
408 // length doesn't exceed the array
410 // We expect all strings to be null terminated. To ensure no string operation overruns the buffer
411 // it sufficies to check that the buffer ends in a null character
412 if (m_pPDBInfo->m_CountOfStringBytes > 0)
414 IfFalseGo(m_DataPointers.m_pStringsBytes[m_pPDBInfo->m_CountOfStringBytes-1] == '\0', HrFromWin32(ERROR_BAD_FORMAT));
421 //-----------------------------------------------------------
422 // Validate a reference to the bytes array
423 //-----------------------------------------------------------
424 HRESULT SymReader::ValidateBytes(UINT32 bytesIndex, UINT32 bytesLen)
426 S_UINT32 extent = S_UINT32(bytesIndex) + S_UINT32(bytesLen);
427 if (!extent.IsOverflow() &&
428 (extent.Value() <= m_pPDBInfo->m_CountOfBytes))
433 return HrFromWin32(ERROR_BAD_FORMAT);
436 //-----------------------------------------------------------
438 // Verify that the debug info in the PE is the one we want
439 //-----------------------------------------------------------
440 HRESULT SymReader::VerifyPEDebugInfo(const WCHAR* szFileName)
443 HANDLE hFile = INVALID_HANDLE_VALUE;
444 HANDLE hMapFile = INVALID_HANDLE_VALUE;
447 IMAGE_DEBUG_DIRECTORY *pDebugDir;
450 DWORD dwUnicodeLength;
452 // We need to change the .pdb extension to .ildb
453 // compatible with VS7
454 wchar_t fullpath[_MAX_PATH];
455 wchar_t drive[_MAX_DRIVE];
456 wchar_t dir[_MAX_DIR];
457 wchar_t fname[_MAX_FNAME];
459 IMAGE_NT_HEADERS*pNT;
461 hFile = WszCreateFile(szFileName,
466 FILE_ATTRIBUTE_NORMAL,
469 if (hFile == INVALID_HANDLE_VALUE)
471 // Get the last error if we can
472 return HrFromWin32(GetLastError());
475 dwFileSize = GetFileSize(hFile, NULL);
476 if (dwFileSize < ILDB_HEADER_SIZE)
478 IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
481 hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
482 if (hMapFile == NULL)
483 IfFailGo(HrFromWin32(GetLastError()));
485 pMod = (BYTE *) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
487 IfFailGo(HrFromWin32(GetLastError()));
489 pNT = Cor_RtlImageNtHeader(pMod, dwFileSize);
491 // If there is no DebugEntry, then just error out
492 if (VAL32(pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) == 0)
493 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
495 // NOTE: This code is not secure against malformed PE files - any of the pointer additions below
496 // may be outside the range of memory mapped for the file. If we ever want to use this code
497 // on untrusted PE files, we should properly validate everything (probably by using PEDecoder).
500 offset = Cor_RtlImageRvaToOffset(pNT, VAL32(pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress), dwFileSize);
502 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
503 pDebugDir = (IMAGE_DEBUG_DIRECTORY *)(pMod + offset);
504 pDebugInfo = (RSDSI *)(pMod + VAL32(pDebugDir->PointerToRawData));
506 if (pDebugInfo->dwSig != VAL32(0x53445352)) // "SDSR"
508 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
512 // Try the returned Stored Name since it might be a fully qualified path
513 dwUtf8Length = VAL32(pDebugDir->SizeOfData) - sizeof(RSDSI);
514 dwUnicodeLength = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) pDebugInfo->szPDB, dwUtf8Length, fullpath, COUNTOF(fullpath) - 1);
516 // Make sure it's NULL terminated
517 _ASSERTE(dwUnicodeLength < COUNTOF(fullpath));
518 fullpath[dwUnicodeLength]='\0';
520 // Replace the extension with ildb
521 if (_wsplitpath_s( fullpath, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
522 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
523 if (_wmakepath_s(m_szStoredSymbolName, MAX_LONGPATH, drive, dir, fname, W("ildb") ))
524 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
526 // It looks valid, make sure to set the return code
530 UnmapViewOfFile(pMod);
531 if (hMapFile != INVALID_HANDLE_VALUE)
532 CloseHandle(hMapFile);
533 if (hFile != INVALID_HANDLE_VALUE)
539 //-----------------------------------------------------------
540 // InitializeFromFile
541 // Initialize the reader using the passed in file name
542 // Note that upon completion the data hasn't yet been validated for safety.
543 //-----------------------------------------------------------
545 SymReader::InitializeFromFile(
546 const WCHAR* szFileName,
547 const WCHAR* szsearchPath)
550 wchar_t fullpath[_MAX_PATH];
551 wchar_t drive[_MAX_DRIVE];
552 wchar_t dir[_MAX_DIR];
553 wchar_t fname[_MAX_FNAME];
554 HANDLE hFile = INVALID_HANDLE_VALUE;
555 HANDLE hMapFile = INVALID_HANDLE_VALUE;
562 _ASSERTE(szFileName);
563 IfFalseGo(szFileName, E_INVALIDARG );
565 IfFailGo(VerifyPEDebugInfo(szFileName));
566 // We need to open the exe and check to see if the DebugInfo matches
568 if (_wsplitpath_s( szFileName, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
569 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
570 if (_wmakepath_s( fullpath, _MAX_PATH, drive, dir, fname, W("ildb") ))
571 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
572 if (wcsncpy_s( m_szPath, COUNTOF(m_szPath), fullpath, _TRUNCATE) == STRUNCATE)
573 IfFailGo(HrFromWin32(ERROR_INSUFFICIENT_BUFFER));
575 hFile = WszCreateFile(m_szPath,
580 FILE_ATTRIBUTE_NORMAL,
583 if (hFile == INVALID_HANDLE_VALUE)
586 // If the stored string is empty, don't do anything
587 if (m_szStoredSymbolName[0] == '\0')
589 return HrFromWin32(GetLastError());
592 if (_wsplitpath_s( m_szStoredSymbolName, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
593 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
594 if (_wmakepath_s( fullpath, _MAX_PATH, drive, dir, fname, W("ildb") ))
595 IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
596 if (wcsncpy_s( m_szPath, COUNTOF(m_szPath), fullpath, _TRUNCATE) == STRUNCATE)
597 IfFailGo(HrFromWin32(ERROR_INSUFFICIENT_BUFFER));
599 hFile = WszCreateFile(m_szPath,
604 FILE_ATTRIBUTE_NORMAL,
607 if (hFile == INVALID_HANDLE_VALUE)
609 return HrFromWin32(GetLastError());
613 dwFileSize = GetFileSize(hFile, NULL);
614 if (dwFileSize < ILDB_HEADER_SIZE)
616 IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
619 hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
620 if (hMapFile == NULL)
621 IfFailGo(HrFromWin32(GetLastError()));
623 hMod = (HMODULE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
625 IfFailGo(HrFromWin32(GetLastError()));
627 // We've opened the file, now let's get the pertinent info
628 CurrentOffset = (BYTE *)hMod;
630 // Verify that we're looking at an ILDB File
631 if (memcmp(CurrentOffset, ILDB_SIGNATURE, ILDB_SIGNATURE_SIZE))
635 CurrentOffset += ILDB_SIGNATURE_SIZE;
637 memcpy( &VersionInfo, CurrentOffset, sizeof(GUID));
638 SwapGuid( &VersionInfo );
639 CurrentOffset += sizeof(GUID);
641 if (memcmp(&VersionInfo, &ILDB_VERSION_GUID, sizeof(GUID)))
643 IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
646 IfNullGo(m_pPDBInfo = NEW(PDBInfo));
648 memcpy(m_pPDBInfo, CurrentOffset, sizeof(PDBInfo));
651 m_pPDBInfo->ConvertEndianness();
653 // Check to make sure we have enough data to be read in.
654 dwDataSize = S_UINT32(ILDB_HEADER_SIZE);
655 dwDataSize += m_pPDBInfo->m_CountOfConstants*sizeof(SymConstant);
656 dwDataSize += m_pPDBInfo->m_CountOfMethods * sizeof(SymMethodInfo);
657 dwDataSize += m_pPDBInfo->m_CountOfScopes*sizeof(SymLexicalScope);
658 dwDataSize += m_pPDBInfo->m_CountOfVars*sizeof(SymVariable);
659 dwDataSize += m_pPDBInfo->m_CountOfUsing*sizeof(SymUsingNamespace);
660 dwDataSize += m_pPDBInfo->m_CountOfSequencePoints*sizeof(SequencePoint);
661 dwDataSize += m_pPDBInfo->m_CountOfDocuments*sizeof(DocumentInfo);
662 dwDataSize += m_pPDBInfo->m_CountOfBytes*sizeof(BYTE);
663 dwDataSize += m_pPDBInfo->m_CountOfStringBytes*sizeof(BYTE);
665 if (dwDataSize.IsOverflow() || dwDataSize.Value() > dwFileSize)
667 IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
670 CurrentOffset += sizeof(PDBInfo);
672 if (m_pPDBInfo->m_CountOfConstants)
674 m_DataPointers.m_pConstants = (SymConstant*)CurrentOffset;
675 CurrentOffset += (m_pPDBInfo->m_CountOfConstants*sizeof(SymConstant));
678 if (m_pPDBInfo->m_CountOfMethods)
680 m_DataPointers.m_pMethods = (SymMethodInfo *)CurrentOffset;
681 CurrentOffset += (m_pPDBInfo->m_CountOfMethods*sizeof(SymMethodInfo));
684 if (m_pPDBInfo->m_CountOfScopes)
686 m_DataPointers.m_pScopes = (SymLexicalScope *)CurrentOffset;
687 CurrentOffset += (m_pPDBInfo->m_CountOfScopes*sizeof(SymLexicalScope));
690 if (m_pPDBInfo->m_CountOfVars)
692 m_DataPointers.m_pVars = (SymVariable *)CurrentOffset;
693 CurrentOffset += (m_pPDBInfo->m_CountOfVars*sizeof(SymVariable));
696 if (m_pPDBInfo->m_CountOfUsing)
698 m_DataPointers.m_pUsings = (SymUsingNamespace *)CurrentOffset;
699 CurrentOffset += (m_pPDBInfo->m_CountOfUsing*sizeof(SymUsingNamespace));
702 if (m_pPDBInfo->m_CountOfSequencePoints)
704 m_DataPointers.m_pSequencePoints = (SequencePoint*)CurrentOffset;
705 CurrentOffset += (m_pPDBInfo->m_CountOfSequencePoints*sizeof(SequencePoint));
708 if (m_pPDBInfo->m_CountOfDocuments)
710 m_DataPointers.m_pDocuments = (DocumentInfo*)CurrentOffset;
711 CurrentOffset += (m_pPDBInfo->m_CountOfDocuments*sizeof(DocumentInfo));
714 if (m_pPDBInfo->m_CountOfBytes)
716 m_DataPointers.m_pBytes = (BYTE*)CurrentOffset;
717 CurrentOffset += (m_pPDBInfo->m_CountOfBytes*sizeof(BYTE));
720 if (m_pPDBInfo->m_CountOfStringBytes)
722 m_DataPointers.m_pStringsBytes = (BYTE*)CurrentOffset;
730 //-----------------------------------------------------------
732 // Get the document for the passed in information
733 //-----------------------------------------------------------
735 SymReader::GetDocument(
736 __in LPWSTR wcsUrl, // URL of the document
737 GUID language, // Language for the file
738 GUID languageVendor, // Language vendor
739 GUID documentType, // Type of document
740 ISymUnmanagedDocument **ppRetVal // [out] Document
745 SymDocument* pDoc = NULL;
746 WCHAR *wcsDocumentUrl = NULL;
747 WCHAR *wcsDocumentUrlAlloc = NULL;
749 _ASSERTE(m_fInitialized);
750 IfFalseGo(m_fInitialized, E_UNEXPECTED);
752 _ASSERTE(ppRetVal && wcsUrl);
753 IfFalseGo(ppRetVal, E_INVALIDARG);
754 IfFalseGo(wcsUrl, E_INVALIDARG);
756 // Init Out Parameter
759 for (i = 0; i < m_pPDBInfo->m_CountOfDocuments; i++)
763 // Convert the UTF8 string to Wide
764 cchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
766 (LPCSTR)&(m_DataPointers.m_pStringsBytes[m_DataPointers.m_pDocuments[i].UrlEntry()]),
770 IfNullGo( wcsDocumentUrlAlloc = NEW(WCHAR[cchName]) );
772 cchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
774 (LPCSTR)&(m_DataPointers.m_pStringsBytes[m_DataPointers.m_pDocuments[i].UrlEntry()]),
778 wcsDocumentUrl = wcsDocumentUrlAlloc;
781 if (wcscmp(wcsUrl, wcsDocumentUrl) == 0)
783 IfFailGo(GetDocument(i, &pDoc));
786 DELETEARRAY(wcsDocumentUrlAlloc);
787 wcsDocumentUrlAlloc = NULL;
792 IfFailGo( pDoc->QueryInterface( IID_ISymUnmanagedDocument,
793 (void**) ppRetVal ) );
797 DELETEARRAY(wcsDocumentUrlAlloc);
804 //-----------------------------------------------------------
806 // Get the documents for this reader
807 //-----------------------------------------------------------
809 SymReader::GetDocuments(
812 ISymUnmanagedDocument *pDocs[]
816 unsigned cDocCount = 0;
818 _ASSERTE(m_fInitialized);
819 IfFalseGo(m_fInitialized, E_UNEXPECTED);
821 _ASSERTE(pDocs || pcDocs);
822 IfFalseGo(pDocs || pcDocs, E_INVALIDARG);
824 cDocs = min(cDocs, m_pPDBInfo->m_CountOfDocuments);
826 for (cDocCount = 0; cDocCount < cDocs; cDocCount++)
831 IfFailGo(GetDocument(cDocCount, &pDoc));
832 pDocs[cDocCount] = pDoc;
837 *pcDocs = (ULONG32)m_pPDBInfo->m_CountOfDocuments;
844 for (i = 0; i < cDocCount; i++)
846 RELEASE(pDocs[cDocCount]);
852 //-----------------------------------------------------------
854 // Get the entry point for the pe
855 //-----------------------------------------------------------
857 SymReader::GetUserEntryPoint(
863 _ASSERTE(m_fInitialized);
864 IfFalseGo(m_fInitialized, E_UNEXPECTED);
867 IfFalseGo(pRetVal, E_INVALIDARG);
869 // If it wasn't set then return E_FAIL
870 if (m_pPDBInfo->m_userEntryPoint == mdTokenNil)
876 *pRetVal = m_pPDBInfo->m_userEntryPoint;
882 // Compare the method token with the SymMethodInfo Entry and return the
883 // value expected by bsearch
884 int __cdecl CompareMethodToToken(const void *pMethodToken, const void *pMethodInfoEntry)
886 mdMethodDef MethodDef = *(mdMethodDef *)pMethodToken;
887 SymMethodInfo *pMethodInfo = (SymMethodInfo *)pMethodInfoEntry;
889 return MethodDef - pMethodInfo->MethodToken();
892 //-----------------------------------------------------------
894 // Get the method for the methoddef
895 //-----------------------------------------------------------
897 SymReader::GetMethod(
898 mdMethodDef method, // MethodDef
899 ISymUnmanagedMethod **ppRetVal // [out] Method
903 UINT32 MethodEntry = 0;
904 SymMethodInfo *pMethodInfo;
905 SymMethod * pMethod = NULL;
907 _ASSERTE(m_fInitialized);
908 IfFalseGo(m_fInitialized, E_UNEXPECTED);
911 IfFalseGo(ppRetVal, E_INVALIDARG);
913 pMethodInfo = (SymMethodInfo *)bsearch(&method, m_DataPointers.m_pMethods, m_pPDBInfo->m_CountOfMethods, sizeof(SymMethodInfo), CompareMethodToToken);
914 IfFalseGo(pMethodInfo, E_FAIL); // no matching method found
917 MethodEntry = UINT32 (pMethodInfo - m_DataPointers.m_pMethods);
918 _ASSERTE(m_DataPointers.m_pMethods[MethodEntry].MethodToken() == method);
919 IfNullGo( pMethod = NEW(SymMethod(this, &m_DataPointers, MethodEntry)) );
928 //-----------------------------------------------------------
929 // GetMethodByVersion
930 //-----------------------------------------------------------
932 SymReader::GetMethodByVersion(
935 ISymUnmanagedMethod **ppRetVal
938 // Don't support multiple version of the same Method so just
940 return GetMethod(method, ppRetVal);
944 //-----------------------------------------------------------
945 // GetMethodFromDocumentPosition
946 //-----------------------------------------------------------
948 SymReader::GetMethodFromDocumentPosition(
949 ISymUnmanagedDocument *document,
952 ISymUnmanagedMethod **ppRetVal
956 UINT32 DocumentEntry;
959 SequencePoint *pSequencePointBefore;
960 SequencePoint *pSequencePointAfter;
963 _ASSERTE(m_fInitialized);
964 IfFalseGo(m_fInitialized, E_UNEXPECTED);
966 _ASSERTE(document && ppRetVal);
967 IfFalseGo(document, E_INVALIDARG);
968 IfFalseGo(ppRetVal, E_INVALIDARG);
970 DocumentEntry = ((SymDocument *)document)->GetDocumentEntry();
972 // Init out parameter
975 // Walk all Methods, check their Document and SequencePoints to see if it's in this doc
976 // and the line/column
978 // This function returns the first match if more than one methods cover the specified position.
979 for (Method = 0; Method < m_pPDBInfo->m_CountOfMethods; Method++)
981 pSequencePointBefore = NULL;
982 pSequencePointAfter = NULL;
984 // Walk the sequence points
985 for (point = m_DataPointers.m_pMethods[Method].StartSequencePoints();
986 point < m_DataPointers.m_pMethods[Method].EndSequencePoints();
989 // Check to see if this sequence point is in this doc
990 if (m_DataPointers.m_pSequencePoints[point].Document() == DocumentEntry)
992 // If the point is position is within the sequence point then
994 if (m_DataPointers.m_pSequencePoints[point].IsWithin(line, column))
996 IfFailGo(GetMethod(m_DataPointers.m_pMethods[Method].MethodToken(), ppRetVal));
1001 // If the sequence is before the point then just remember the point
1002 if (m_DataPointers.m_pSequencePoints[point].IsUserLine() &&
1003 m_DataPointers.m_pSequencePoints[point].IsLessThan(line, column))
1005 pSequencePointBefore = &m_DataPointers.m_pSequencePoints[point];
1008 // If the sequence is before the point then just remember the point
1009 if (m_DataPointers.m_pSequencePoints[point].IsUserLine() &&
1010 m_DataPointers.m_pSequencePoints[point].IsGreaterThan(line, column))
1012 pSequencePointAfter = &m_DataPointers.m_pSequencePoints[point];
1017 // If we found an exact match, we're done.
1023 // If we found sequence points within the method before and after
1024 // the line/column then we may have found the method. Record the return value, but keep looking
1025 // to see if we find an exact match. This may not actually be the right method. Iron Python, for instance,
1026 // issues a "method" containing sequence points for all the method headers in a class. Sequence points
1027 // in this "method" would then span the sequence points in the bodies of all but the last method.
1028 if (pSequencePointBefore && pSequencePointAfter)
1030 IfFailGo(GetMethod(m_DataPointers.m_pMethods[Method].MethodToken(), ppRetVal));
1034 // This function returns E_FAIL if no match is found.
1035 // Note that this is different from the behaviour of GetMethodsFromDocumentPosition() (see below).
1036 if (*ppRetVal == NULL)
1045 //---------------------------------------------------------------------------------------
1047 // Return all methods with sequence points covering the specified source location. This
1048 // is actually not as straighforward as it sounds, since we need to mimic the behaviour of
1049 // diasymreader and PDBs here. For PDBs, diasymreader actually does two passes over the
1050 // sequence points. It tries to find an exact match in the first pass, and if that fails,
1051 // it'll do a second pass looking for an approximate match. An approximate match is a sequence
1052 // point which doesn't start on the specified line but covers it. If there's an exact match,
1053 // then it ignores all the approximate matches. In both cases, diasymreader only checks the
1054 // start line number of the sequence point and it ignores the column number.
1056 // For backward compatibility, I'm leaving GetMethodFromDocumentPosition() unchanged.
1060 SymReader::GetMethodsFromDocumentPosition(
1061 ISymUnmanagedDocument *document,
1065 ULONG32* pcMethod, //[Optional]: How many method actually returned
1066 ISymUnmanagedMethod** ppRetVal
1070 UINT32 DocumentEntry;
1076 bool fExactMatch = true;
1078 ULONG32 maxPreLine = 0;
1080 _ASSERTE(m_fInitialized);
1081 IfFalseGo(m_fInitialized, E_UNEXPECTED);
1084 IfFalseGo(document, E_INVALIDARG);
1086 _ASSERTE((cMethod == 0) || (ppRetVal != NULL));
1087 IfFalseGo(cMethod == 0 || ppRetVal != NULL, E_INVALIDARG);
1089 // Initialize the out parameter if it has been provided.
1090 if (pcMethod != NULL)
1095 DocumentEntry = ((SymDocument *)document)->GetDocumentEntry();
1097 // Enumerate the sequence points in two passes.
1100 // Walk all Methods, check their Document and SequencePoints to see if it's in this doc
1101 // and the line/column
1103 for (Method = 0; Method < m_pPDBInfo->m_CountOfMethods; Method++)
1107 // Walk the sequence points
1108 for (point = m_DataPointers.m_pMethods[Method].StartSequencePoints();
1109 point < m_DataPointers.m_pMethods[Method].EndSequencePoints();
1112 // Check to see if this sequence point is in this doc
1113 if (m_DataPointers.m_pSequencePoints[point].Document() == DocumentEntry)
1115 // PDBs (more specifically the DIA APIs) only check the start line number and not the end line number when
1116 // trying to determine whether a sequence point covers the specified line number. We need to match this
1117 // behaviour here. For backward compatibility reasons, GetMethodFromDocumentPosition() is still checking
1118 // against the entire range of a sequence point, but we should revisit that in the next release.
1119 ULONG32 curLine = m_DataPointers.m_pSequencePoints[point].StartLine();
1123 if (curLine == line)
1127 else if ((maxPreLine < curLine) && (curLine < line))
1129 // This is not an exact match, but let's keep track of the sequence point closest to the specified
1130 // line. We'll use this info if we have to do a second pass.
1131 maxPreLine = curLine;
1136 // We are in the second pass, looking for approximate matches.
1137 if ((maxPreLine != 0) && (maxPreLine == curLine))
1139 // Make sure the sequence point covers the specified line.
1140 if (m_DataPointers.m_pSequencePoints[point].IsWithinLineOnly(line))
1147 // If we have found a match (whether it's exact or approximate), then save this method unless the caller is
1148 // only interested in the number of matching methods or the array provided by the caller isn't big enough.
1151 if (CurMethod < cMethod)
1153 IfFailGo(GetMethod(m_DataPointers.m_pMethods[Method].MethodToken(), &(ppRetVal[CurMethod])));
1163 // If we have already filled out the entire array provided by the caller, then we are done.
1164 if ((cMethod > 0) && (cMethod == CurMethod))
1170 // Otherwise move on to the next method.
1176 // If we haven't found an exact match, then try it again looking for a sequence point covering the specified line.
1177 if (fExactMatch && (CurMethod == 0))
1179 fExactMatch = false;
1184 // If we have found an exact match, or if we have done two passes already, then bail.
1189 // Note that unlike GetMethodFromDocumentPosition(), this function returns S_OK even if a match is not found.
1192 if (pcMethod != NULL)
1194 *pcMethod = CurMethod;
1202 //-----------------------------------------------------------
1203 // GetSymbolStoreFileName
1204 //-----------------------------------------------------------
1206 SymReader::GetSymbolStoreFileName(
1207 ULONG32 cchName, // Length of szName
1208 ULONG32 *pcchName, // [Optional]
1209 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[] // [Optional]
1212 _ASSERTE(m_fInitialized);
1213 if (!m_fInitialized)
1214 return E_UNEXPECTED;
1218 *pcchName = (ULONG32)(wcslen(m_szPath)+1);
1223 if (wcsncpy_s( szName, cchName, m_szPath, _TRUNCATE) == STRUNCATE)
1224 return HrFromWin32(ERROR_INSUFFICIENT_BUFFER);
1230 //-----------------------------------------------------------
1232 //-----------------------------------------------------------
1234 SymReader::GetMethodVersion(
1235 ISymUnmanagedMethod * pMethod,
1241 _ASSERTE(m_fInitialized);
1242 IfFalseGo(m_fInitialized, E_UNEXPECTED);
1244 _ASSERTE(pMethod && pVersion);
1245 IfFalseGo( pMethod && pVersion, E_INVALIDARG);
1246 // This symbol store only supports one version of a method
1252 //-----------------------------------------------------------
1253 // GetDocumentVersion
1254 //-----------------------------------------------------------
1256 SymReader::GetDocumentVersion(
1257 ISymUnmanagedDocument* pDoc,
1259 BOOL* pbCurrent // [Optional]
1264 _ASSERTE(m_fInitialized);
1265 IfFalseGo(m_fInitialized, E_UNEXPECTED);
1267 _ASSERTE(pVersion && pDoc);
1268 IfFalseGo(pVersion, E_INVALIDARG);
1269 IfFalseGo(pDoc, E_INVALIDARG);
1271 // This symbol store only supports one version of a document
1281 //-----------------------------------------------------------
1283 // Return the document for the given entry
1284 //-----------------------------------------------------------
1285 HRESULT SymReader::GetDocument(
1286 UINT32 DocumentEntry,
1287 SymDocument **ppDocument)
1289 HRESULT hr = NOERROR;
1291 _ASSERTE(m_fInitialized);
1292 IfFalseGo(m_fInitialized, E_UNEXPECTED);
1294 _ASSERTE(ppDocument);
1295 IfFalseGo(ppDocument, E_INVALIDARG);
1297 _ASSERTE(DocumentEntry < m_pPDBInfo->m_CountOfDocuments);
1298 IfFalseGo(DocumentEntry < m_pPDBInfo->m_CountOfDocuments, E_INVALIDARG);
1300 if (m_pDocs == NULL)
1302 IfNullGo(m_pDocs = NEW(SymDocument *[m_pPDBInfo->m_CountOfDocuments]));
1303 memset(m_pDocs, 0, m_pPDBInfo->m_CountOfDocuments * sizeof(void *));
1306 if (m_pDocs[DocumentEntry] == NULL)
1308 m_pDocs[DocumentEntry] = NEW(SymDocument(this, &m_DataPointers, m_pPDBInfo->m_CountOfMethods, DocumentEntry));
1309 IfNullGo(m_pDocs[DocumentEntry]);
1310 // AddRef the table version
1311 m_pDocs[DocumentEntry]->AddRef();
1315 //Set and AddRef the Out Parameter
1316 *ppDocument = m_pDocs[DocumentEntry];
1317 (*ppDocument)->AddRef();
1324 SymReader::UpdateSymbolStore(
1325 const WCHAR *filename,
1329 // This symbol store doesn't support updating the symbol store.
1335 SymReader::ReplaceSymbolStore(
1336 const WCHAR *filename,
1340 // This symbol store doesn't support updating the symbol store.
1345 //-----------------------------------------------------------
1347 //-----------------------------------------------------------
1349 SymReader::GetVariables(
1353 ISymUnmanagedVariable *pVars[]
1357 // This symbol reader doesn't support non-local variables.
1363 //-----------------------------------------------------------
1364 // GetGlobalVariables
1365 //-----------------------------------------------------------
1367 SymReader::GetGlobalVariables(
1370 ISymUnmanagedVariable *pVars[]
1374 // This symbol reader doesn't support non-local variables.
1380 //-----------------------------------------------------------
1382 //-----------------------------------------------------------
1384 SymReader::GetSymAttribute(
1389 __out_bcount_part_opt(cBuffer, *pcBuffer) BYTE buffer[]
1392 // This symbol store doesn't support attributes
1393 // VS may query for certain attributes, but will survive without them,
1394 // so don't ASSERT here.
1398 //-----------------------------------------------------------
1400 //-----------------------------------------------------------
1402 SymReader::GetNamespaces(
1403 ULONG32 cNameSpaces,
1404 ULONG32 *pcNameSpaces,
1405 ISymUnmanagedNamespace *namespaces[]
1408 // This symbol store doesn't support this
1413 /* ------------------------------------------------------------------------- *
1415 * ------------------------------------------------------------------------- */
1418 SymDocument::QueryInterface(
1423 if (ppInterface == NULL)
1424 return E_INVALIDARG;
1426 if (riid == IID_ISymUnmanagedDocument)
1427 *ppInterface = (ISymUnmanagedDocument*)this;
1428 else if (riid == IID_IUnknown)
1429 *ppInterface = (IUnknown*)(ISymUnmanagedDocument*)this;
1432 *ppInterface = NULL;
1433 return E_NOINTERFACE;
1441 //-----------------------------------------------------------
1443 //-----------------------------------------------------------
1445 SymDocument::GetURL(
1446 ULONG32 cchUrl, // The allocated size of the buffer
1447 ULONG32 *pcchUrl, // [optional,out] The number of characters available for return
1448 __out_ecount_part_opt(cchUrl, *pcchUrl) WCHAR szUrl[] // [optional,out] The string buffer.
1453 // Convert the UTF8 string to Wide
1454 *pcchUrl = (ULONG32) MultiByteToWideChar(CP_UTF8,
1456 (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pDocuments[m_DocumentEntry].UrlEntry()]),
1464 // Convert the UTF8 string to Wide
1465 MultiByteToWideChar(CP_UTF8,
1467 (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pDocuments[m_DocumentEntry].UrlEntry()]),
1475 //-----------------------------------------------------------
1477 //-----------------------------------------------------------
1479 SymDocument::GetDocumentType(
1483 HRESULT hr = NOERROR;
1485 IfFalseGo(pRetVal, E_INVALIDARG);
1486 *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].DocumentType();
1492 //-----------------------------------------------------------
1494 //-----------------------------------------------------------
1496 SymDocument::GetLanguage(
1500 HRESULT hr = NOERROR;
1502 IfFalseGo(pRetVal, E_INVALIDARG);
1504 *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].Language();
1510 //-----------------------------------------------------------
1511 // GetLanguageVendor
1512 //-----------------------------------------------------------
1514 SymDocument::GetLanguageVendor(
1518 HRESULT hr = NOERROR;
1520 IfFalseGo(pRetVal, E_INVALIDARG);
1521 *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].LanguageVendor();
1527 //-----------------------------------------------------------
1528 // GetCheckSumAlgorithmId
1529 //-----------------------------------------------------------
1531 SymDocument::GetCheckSumAlgorithmId(
1535 HRESULT hr = NOERROR;
1537 IfFalseGo(pRetVal, E_INVALIDARG);
1538 *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].AlgorithmId();
1544 //-----------------------------------------------------------
1546 //-----------------------------------------------------------
1548 SymDocument::GetCheckSum(
1549 ULONG32 cData, // The allocated size of the buffer.
1550 ULONG32 *pcData, // [optional] The number of bytes available for return
1551 BYTE data[]) // [optional] The buffer to receive the checksum.
1553 BYTE *pCheckSum = &m_pData->m_pBytes[m_pData->m_pDocuments[m_DocumentEntry].CheckSumEntry()];
1554 ULONG32 CheckSumSize = m_pData->m_pDocuments[m_DocumentEntry].CheckSumSize();
1557 *pcData = CheckSumSize;
1561 memcpy(data, pCheckSum, min(CheckSumSize, cData));
1566 //-----------------------------------------------------------
1568 // Search the sequence points looking a line that is closest
1569 // line following this one that is a sequence point
1570 //-----------------------------------------------------------
1572 SymDocument::FindClosestLine(
1577 HRESULT hr = NOERROR;
1580 ULONG32 closestLine = 0; // GCC can't tell this isn't used before initialization
1584 IfFalseGo(pRetVal, E_INVALIDARG);
1586 // Walk all Methods, check their Document and SequencePoints to see if it's in this doc
1587 // and the line/column
1588 for (Method = 0; Method < m_CountOfMethods; Method++)
1590 // Walk the sequence points
1591 for (point = m_pData->m_pMethods[Method].StartSequencePoints();
1592 point < m_pData->m_pMethods[Method].EndSequencePoints();
1595 SequencePoint & sp = m_pData->m_pSequencePoints[point];
1596 // Check to see if this sequence point is in this doc, and is at or
1597 // after the requested line
1598 if ((sp.Document() == m_DocumentEntry) && sp.IsUserLine())
1600 if (sp.IsWithin(line, 0) || sp.IsGreaterThan(line, 0))
1602 // This sequence point is at or after the requested line. If we haven't
1603 // already found a "closest", or this is even closer than the one we have,
1604 // then mark this as the best line so far.
1605 if (!found || m_pData->m_pSequencePoints[point].StartLine() < closestLine)
1608 closestLine = m_pData->m_pSequencePoints[point].StartLine();
1617 *pRetVal = closestLine;
1621 // Didn't find any lines at or after the one requested.
1629 //-----------------------------------------------------------
1630 // SymDocument HasEmbeddedSource
1631 //-----------------------------------------------------------
1633 SymDocument::HasEmbeddedSource(
1638 // This symbol reader doesn't support embedded source.
1644 //-----------------------------------------------------------
1645 // SymDocument GetSourceLength
1646 //-----------------------------------------------------------
1648 SymDocument::GetSourceLength(
1653 // This symbol reader doesn't support embedded source.
1659 //-----------------------------------------------------------
1660 // SymDocument GetSourceRange
1661 //-----------------------------------------------------------
1663 SymDocument::GetSourceRange(
1665 ULONG32 startColumn,
1668 ULONG32 cSourceBytes,
1669 ULONG32 *pcSourceBytes,
1674 // This symbol reader doesn't support embedded source.
1680 /* ------------------------------------------------------------------------- *
1682 * ------------------------------------------------------------------------- */
1684 SymMethod::QueryInterface(
1689 if (ppInterface == NULL)
1690 return E_INVALIDARG;
1692 if (riid == IID_ISymUnmanagedMethod)
1693 *ppInterface = (ISymUnmanagedMethod*)this;
1694 else if (riid == IID_IUnknown)
1695 *ppInterface = (IUnknown*)(ISymUnmanagedMethod*)this;
1698 *ppInterface = NULL;
1699 return E_NOINTERFACE;
1706 //-----------------------------------------------------------
1708 //-----------------------------------------------------------
1710 SymMethod::GetToken(
1711 mdMethodDef *pRetVal
1717 IfFalseGo(pRetVal, E_INVALIDARG);
1718 *pRetVal = m_pData->m_pMethods[m_MethodEntry].MethodToken();
1724 //-----------------------------------------------------------
1725 // GetSequencePointCount
1726 //-----------------------------------------------------------
1728 SymMethod::GetSequencePointCount(
1735 IfFalseGo(pRetVal, E_INVALIDARG);
1737 *pRetVal = (ULONG32)(m_pData->m_pMethods[m_MethodEntry].EndSequencePoints() -
1738 m_pData->m_pMethods[m_MethodEntry].StartSequencePoints());
1743 //-----------------------------------------------------------
1744 // GetSequencePoints
1745 //-----------------------------------------------------------
1747 SymMethod::GetSequencePoints(
1748 ULONG32 cPoints, // The size of the allocated arrays.
1749 ULONG32* pcPoints, // [optional] The number of sequence points available for return.
1750 ULONG32 offsets[], // [optional]
1751 ISymUnmanagedDocument *documents[], // [Optional]
1752 ULONG32 lines[], // [Optional]
1753 ULONG32 columns[], // [Optional]
1754 ULONG32 endLines[], // [Optional]
1755 ULONG32 endColumns[] // [Optional]
1758 HRESULT hr = NOERROR;
1762 for (i = m_pData->m_pMethods[m_MethodEntry].StartSequencePoints();
1763 (i < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints());
1766 if (Points < cPoints)
1771 IfFailGo(m_pReader->GetDocument(m_pData->m_pSequencePoints[i].Document(), &pDoc));
1772 documents[Points] = pDoc;
1777 offsets[Points] = m_pData->m_pSequencePoints[i].Offset();
1782 lines[Points] = m_pData->m_pSequencePoints[i].StartLine();
1786 columns[Points] = m_pData->m_pSequencePoints[i].StartColumn();
1790 endLines[Points] = m_pData->m_pSequencePoints[i].EndLine();
1794 endColumns[Points] = m_pData->m_pSequencePoints[i].EndColumn();
1810 for (j = 0; j < i; j++)
1812 RELEASE(documents[i]);
1819 //-----------------------------------------------------------
1821 //-----------------------------------------------------------
1823 SymMethod::GetRootScope(
1824 ISymUnmanagedScope **ppRetVal
1828 SymScope *pScope = NULL;
1830 IfFalseGo(ppRetVal, E_INVALIDARG);
1834 if (m_pData->m_pMethods[m_MethodEntry].EndScopes() - m_pData->m_pMethods[m_MethodEntry].StartScopes())
1836 IfNullGo(pScope = NEW(SymScope(this, m_pData, m_MethodEntry, m_pData->m_pMethods[m_MethodEntry].StartScopes())));
1844 //-----------------------------------------------------------
1846 // Given a position in a document, gets the offset within the
1847 // method that corresponds to the position.
1848 //-----------------------------------------------------------
1850 SymMethod::GetOffset(
1851 ISymUnmanagedDocument *document,
1858 bool fFound = false;
1860 IfFalseGo(pRetVal, E_INVALIDARG);
1863 UINT32 DocumentEntry;
1865 DocumentEntry = ((SymDocument *)document)->GetDocumentEntry();
1867 // Walk the sequence points
1868 for (point = m_pData->m_pMethods[m_MethodEntry].StartSequencePoints();
1869 point < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints();
1872 // Check to see if this sequence point is in this doc
1873 if (m_pData->m_pSequencePoints[point].Document() == DocumentEntry)
1875 // Check to see if it's within the sequence point
1876 if (m_pData->m_pSequencePoints[point].IsWithin(line, column))
1878 *pRetVal = m_pData->m_pSequencePoints[point].Offset();
1892 //-----------------------------------------------------------
1894 //-----------------------------------------------------------
1896 SymMethod::GetRanges(
1897 ISymUnmanagedDocument *pDocument, // [in] Document we're working on
1898 ULONG32 line, // [in] The document line corresponding to the ranges.
1899 ULONG32 column, // [in] Ignored
1900 ULONG32 cRanges, // [in] The size of the allocated ranges[] array.
1901 ULONG32 *pcRanges, // [out] The number of ranges available for return
1902 ULONG32 ranges[] // [out] The range array.
1905 HRESULT hr = NOERROR;
1907 UINT32 DocumentEntry;
1909 bool fFound = false;
1911 // Validate some of the parameters
1912 _ASSERTE(pDocument && (cRanges % 2) == 0);
1913 IfFalseGo(pDocument, E_INVALIDARG);
1914 IfFalseGo((cRanges % 2) == 0, E_INVALIDARG);
1916 // Init out parameter
1922 DocumentEntry = ((SymDocument *)pDocument)->GetDocumentEntry();
1924 // Walk the sequence points
1925 for (point = m_pData->m_pMethods[m_MethodEntry].StartSequencePoints();
1926 point < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints();
1929 // Check to see if this sequence point is in this doc
1930 if (m_pData->m_pSequencePoints[point].Document() == DocumentEntry)
1932 // Check to see if the line is within this sequence
1933 // Note, to be compatible with VS7, ignore the column information
1934 if (line >= m_pData->m_pSequencePoints[point].StartLine() &&
1935 line <= m_pData->m_pSequencePoints[point].EndLine())
1945 for (;point < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints(); point++)
1948 // Search through all the sequence points since line might have there
1949 // IL spread accross multiple ranges (for loops for example)
1950 if (m_pData->m_pSequencePoints[point].Document() == DocumentEntry &&
1951 line >= m_pData->m_pSequencePoints[point].StartLine() &&
1952 line <= m_pData->m_pSequencePoints[point].EndLine())
1954 if (iRange < cRanges)
1956 ranges[iRange] = m_pData->m_pSequencePoints[point].Offset();
1959 if (iRange < cRanges)
1961 if (point+1 < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints())
1963 ranges[iRange] = m_pData->m_pSequencePoints[point+1].Offset();
1967 // Then it must be till the end of the function which is the root scope's endoffset
1968 ranges[iRange] = m_pData->m_pScopes[m_pData->m_pMethods[m_MethodEntry].StartScopes()].EndOffset()+1;
1976 // If cRanges passed in, return the number
1977 // of elements actually filled in
1980 *pcRanges = min(iRange, cRanges);
1984 // Otherwise return the max number
1998 //-----------------------------------------------------------
1999 // GetScopeFromOffset
2000 //-----------------------------------------------------------
2002 SymMethod::GetScopeFromOffset(
2004 ISymUnmanagedScope **pRetVal
2008 // This symbol reader doesn't support this functionality
2014 //-----------------------------------------------------------
2016 //-----------------------------------------------------------
2018 SymMethod::GetParameters(
2021 ISymUnmanagedVariable *params[]
2025 // This symbol reader doesn't support parameter access. Parameters
2026 // can be found in the normal metadata.
2032 //-----------------------------------------------------------
2034 //-----------------------------------------------------------
2036 SymMethod::GetNamespace(
2037 ISymUnmanagedNamespace **ppRetVal
2041 // This symbol reader doesn't support namespaces
2047 //-----------------------------------------------------------
2048 // GetSourceStartEnd
2049 //-----------------------------------------------------------
2051 SymMethod::GetSourceStartEnd(
2052 ISymUnmanagedDocument *docs[2],
2059 // This symbol reader doesn't support source start/end for methods.
2065 /* ------------------------------------------------------------------------- *
2067 * ------------------------------------------------------------------------- */
2069 //-----------------------------------------------------------
2071 //-----------------------------------------------------------
2073 SymScope::QueryInterface(
2078 if (ppInterface == NULL)
2079 return E_INVALIDARG;
2081 if (riid == IID_ISymUnmanagedScope)
2082 *ppInterface = (ISymUnmanagedScope*)this;
2083 else if (riid == IID_IUnknown)
2084 *ppInterface = (IUnknown*)(ISymUnmanagedScope*)this;
2087 *ppInterface = NULL;
2088 return E_NOINTERFACE;
2095 //-----------------------------------------------------------
2097 //-----------------------------------------------------------
2099 SymScope::GetMethod(
2100 ISymUnmanagedMethod **ppRetVal
2106 IfFalseGo(ppRetVal, E_INVALIDARG);
2108 *ppRetVal = m_pSymMethod;
2109 m_pSymMethod->AddRef();
2115 //-----------------------------------------------------------
2117 //-----------------------------------------------------------
2119 SymScope::GetParent(
2120 ISymUnmanagedScope **ppRetVal
2125 IfFalseGo(ppRetVal, E_INVALIDARG);
2126 if (m_pData->m_pScopes[m_ScopeEntry].ParentScope() != (UINT32)-1)
2128 IfNullGo(*ppRetVal = static_cast<ISymUnmanagedScope *>(NEW(SymScope(m_pSymMethod, m_pData, m_MethodEntry,
2129 m_pData->m_pScopes[m_ScopeEntry].ParentScope()))));
2130 (*ppRetVal)->AddRef();
2140 //-----------------------------------------------------------
2142 //-----------------------------------------------------------
2144 SymScope::GetChildren(
2145 ULONG32 cChildren, // [optional] Number of entries in children
2146 ULONG32 *pcChildren, // [optional, out] Number of Children available for retur
2147 ISymUnmanagedScope *children[] // [optional] array to store children into
2151 ULONG32 ChildrenCount = 0;
2152 _ASSERTE(pcChildren || (children && cChildren));
2153 IfFalseGo((pcChildren || (children && cChildren)), E_INVALIDARG);
2155 if (m_pData->m_pScopes[m_ScopeEntry].HasChildren())
2158 for(ScopeEntry = m_pData->m_pMethods[m_MethodEntry].StartScopes();
2159 (ScopeEntry < m_pData->m_pMethods[m_MethodEntry].EndScopes());
2162 if (m_pData->m_pScopes[ScopeEntry].ParentScope() == m_ScopeEntry)
2164 if (children && ChildrenCount < cChildren)
2168 IfNullGo(pScope = NEW(SymScope(m_pSymMethod, m_pData, m_MethodEntry, ScopeEntry)));
2169 children[ChildrenCount] = pScope;
2179 *pcChildren = ChildrenCount;
2183 if (FAILED(hr) && ChildrenCount)
2186 for (i =0; i< ChildrenCount; i++)
2188 RELEASE(children[i]);
2194 //-----------------------------------------------------------
2196 //-----------------------------------------------------------
2198 SymScope::GetStartOffset(
2204 IfFalseGo(pRetVal, E_INVALIDARG);
2205 *pRetVal = m_pData->m_pScopes[m_ScopeEntry].StartOffset();
2210 //-----------------------------------------------------------
2212 //-----------------------------------------------------------
2214 SymScope::GetEndOffset(
2220 IfFalseGo(pRetVal, E_INVALIDARG);
2221 *pRetVal = m_pData->m_pScopes[m_ScopeEntry].EndOffset();
2226 //-----------------------------------------------------------
2228 //-----------------------------------------------------------
2230 SymScope::GetLocalCount(
2235 ULONG32 LocalCount = 0;
2237 IfFalseGo(pRetVal, E_INVALIDARG);
2239 // Init out parameter
2241 if (m_pData->m_pScopes[m_ScopeEntry].HasVars())
2244 // Walk and get the locals for this Scope
2245 for (var = m_pData->m_pMethods[m_MethodEntry].StartVars();
2246 var < m_pData->m_pMethods[m_MethodEntry].EndVars();
2249 if (m_pData->m_pVars[var].Scope() == m_ScopeEntry &&
2250 m_pData->m_pVars[var].IsParam() == false)
2257 *pRetVal = LocalCount;
2262 //-----------------------------------------------------------
2264 // Input: either pcLocals or
2265 // cLocals and pLocals
2266 //-----------------------------------------------------------
2268 SymScope::GetLocals(
2269 ULONG32 cLocals, // [optional] available entries in pLocals
2270 ULONG32 *pcLocals, // [optional, out] Number of locals returned
2271 ISymUnmanagedVariable *pLocals[] // [optional] array to store locals into
2276 ULONG32 LocalCount = 0;
2277 _ASSERTE(pcLocals || pLocals);
2278 IfFalseGo(pcLocals || pLocals, E_INVALIDARG);
2280 if (m_pData->m_pScopes[m_ScopeEntry].HasVars())
2283 // Walk and get the locals for this Scope
2284 for (var = m_pData->m_pMethods[m_MethodEntry].StartVars();
2285 var < m_pData->m_pMethods[m_MethodEntry].EndVars();
2288 if (m_pData->m_pVars[var].Scope() == m_ScopeEntry &&
2289 m_pData->m_pVars[var].IsParam() == false)
2291 if (pLocals && LocalCount < cLocals)
2294 IfNullGo( pVar = NEW(SymReaderVar(this, m_pData, var)));
2295 pLocals[LocalCount] = pVar;
2304 *pcLocals = LocalCount;
2307 if (FAILED(hr) && LocalCount != 0)
2310 for (i =0; i < LocalCount; i++)
2312 RELEASE(pLocals[i]);
2318 //-----------------------------------------------------------
2320 // Input: either pcNameSpaces or
2321 // cNameSpaces and pNameSpaces
2322 //-----------------------------------------------------------
2324 SymScope::GetNamespaces(
2325 ULONG32 cNameSpaces, // [optional] number of entries pNameSpaces
2326 ULONG32 *pcNameSpaces, // [optional, out] Maximum number of Namespace
2327 ISymUnmanagedNamespace *pNameSpaces[] // [optinal] array to store namespaces into
2330 HRESULT hr = NOERROR;
2333 unsigned NameSpaceCount = 0;
2335 _ASSERTE(pcNameSpaces || (pNameSpaces && cNameSpaces));
2336 IfFalseGo(pcNameSpaces || (pNameSpaces && cNameSpaces), E_INVALIDARG);
2338 for (NameSpace = m_pData->m_pMethods[m_MethodEntry].StartUsing();
2339 NameSpace < m_pData->m_pMethods[m_MethodEntry].EndUsing();
2342 if (m_pData->m_pUsings[NameSpace].ParentScope() == m_ScopeEntry)
2344 if (pNameSpaces && (NameSpaceCount < cNameSpaces) )
2346 IfNullGo(pNameSpaces[NameSpaceCount] = NEW(SymReaderNamespace(this, m_pData, NameSpace)));
2347 pNameSpaces[NameSpaceCount]->AddRef();
2354 *pcNameSpaces = NameSpaceCount;
2357 if (FAILED(hr) && pNameSpaces)
2359 for (i = 0; (i < cNameSpaces) && (i < NameSpaceCount); i++)
2361 RELEASE(pNameSpaces[i]);
2367 /* ------------------------------------------------------------------------- *
2368 * SymReaderVar class
2369 * ------------------------------------------------------------------------- */
2371 //-----------------------------------------------------------
2373 //-----------------------------------------------------------
2375 SymReaderVar::QueryInterface(
2380 if (ppInterface == NULL)
2381 return E_INVALIDARG;
2383 if (riid == IID_ISymUnmanagedVariable)
2384 *ppInterface = (ISymUnmanagedVariable*)this;
2385 else if (riid == IID_IUnknown)
2386 *ppInterface = (IUnknown*)(ISymUnmanagedVariable*)this;
2389 *ppInterface = NULL;
2390 return E_NOINTERFACE;
2397 //-----------------------------------------------------------
2399 //-----------------------------------------------------------
2401 SymReaderVar::GetName(
2402 ULONG32 cchName, // [optional] Length of szName buffer
2403 ULONG32 *pcchName, // [optional, out] Total size needed to return the name
2404 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[] // [optional] Buffer to store the name into.
2409 // We must have at least one combination
2410 _ASSERTE(pcchName || (szName && cchName));
2411 IfFalseGo( (pcchName || (szName && cchName)), E_INVALIDARG );
2415 // Convert the UTF8 string to Wide
2416 *pcchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
2418 (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pVars[m_VarEntry].Name()]),
2426 // Convert the UTF8 string to Wide
2427 MultiByteToWideChar(CP_UTF8,
2429 (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pVars[m_VarEntry].Name()]),
2439 //-----------------------------------------------------------
2441 //-----------------------------------------------------------
2443 SymReaderVar::GetAttributes(
2444 ULONG32 *pRetVal // [out]
2447 if (pRetVal == NULL)
2448 return E_INVALIDARG;
2450 *pRetVal = m_pData->m_pVars[m_VarEntry].Attributes();
2454 //-----------------------------------------------------------
2456 //-----------------------------------------------------------
2458 SymReaderVar::GetSignature(
2459 ULONG32 cSig, // Size of allocated buffer passed in (sig)
2460 ULONG32 *pcSig, // [optional, out] Total size needed to return the signature
2461 BYTE sig[] // [Optional] Signature
2466 _ASSERTE(pcSig || sig);
2467 IfFalseGo( pcSig || sig, E_INVALIDARG );
2470 *pcSig = m_pData->m_pVars[m_VarEntry].SignatureSize();
2474 cSig = min(m_pData->m_pVars[m_VarEntry].SignatureSize(), cSig);
2475 memcpy(sig, &m_pData->m_pBytes[m_pData->m_pVars[m_VarEntry].Signature()],cSig);
2482 //-----------------------------------------------------------
2484 //-----------------------------------------------------------
2486 SymReaderVar::GetAddressKind(
2487 ULONG32 *pRetVal // [out]
2492 IfFalseGo( pRetVal, E_INVALIDARG );
2493 *pRetVal = m_pData->m_pVars[m_VarEntry].AddrKind();
2498 //-----------------------------------------------------------
2500 //-----------------------------------------------------------
2502 SymReaderVar::GetAddressField1(
2503 ULONG32 *pRetVal // [out]
2509 IfFalseGo( pRetVal, E_INVALIDARG );
2511 *pRetVal = m_pData->m_pVars[m_VarEntry].Addr1();
2518 //-----------------------------------------------------------
2520 //-----------------------------------------------------------
2522 SymReaderVar::GetAddressField2(
2523 ULONG32 *pRetVal // [out]
2529 IfFalseGo( pRetVal, E_INVALIDARG );
2531 *pRetVal = m_pData->m_pVars[m_VarEntry].Addr2();
2538 //-----------------------------------------------------------
2540 //-----------------------------------------------------------
2542 SymReaderVar::GetAddressField3(
2543 ULONG32 *pRetVal // [out]
2549 IfFalseGo( pRetVal, E_INVALIDARG );
2551 *pRetVal = m_pData->m_pVars[m_VarEntry].Addr3();
2558 //-----------------------------------------------------------
2560 //-----------------------------------------------------------
2562 SymReaderVar::GetStartOffset(
2567 // This symbol reader doesn't support variable sub-offsets.
2572 //-----------------------------------------------------------
2574 //-----------------------------------------------------------
2576 SymReaderVar::GetEndOffset(
2581 // This symbol reader doesn't support variable sub-offsets.
2587 /* ------------------------------------------------------------------------- *
2588 * SymReaderNamespace class
2589 * ------------------------------------------------------------------------- */
2591 //-----------------------------------------------------------
2593 //-----------------------------------------------------------
2595 SymReaderNamespace::QueryInterface(
2600 if (ppInterface == NULL)
2601 return E_INVALIDARG;
2603 if (riid == IID_ISymUnmanagedNamespace)
2604 *ppInterface = (ISymUnmanagedNamespace*)this;
2605 else if (riid == IID_IUnknown)
2606 *ppInterface = (IUnknown*)(ISymUnmanagedNamespace*)this;
2609 *ppInterface = NULL;
2610 return E_NOINTERFACE;
2617 //-----------------------------------------------------------
2619 //-----------------------------------------------------------
2621 SymReaderNamespace::GetName(
2622 ULONG32 cchName, // [optional] Chars available in szName
2623 ULONG32 *pcchName, // [optional] Total size needed to return the name
2624 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[] // [optional] Location to store the name into.
2628 _ASSERTE(pcchName || (szName && cchName));
2629 IfFalseGo( (pcchName || (szName && cchName)), E_INVALIDARG );
2633 *pcchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
2635 (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pUsings[m_NamespaceEntry].Name()]),
2642 MultiByteToWideChar(CP_UTF8,
2644 (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pUsings[m_NamespaceEntry].Name()]),
2654 //-----------------------------------------------------------
2656 //-----------------------------------------------------------
2658 SymReaderNamespace::GetNamespaces(
2659 ULONG32 cNamespaces,
2660 ULONG32 *pcNamespaces,
2661 ISymUnmanagedNamespace* namespaces[]
2664 // This symbol store doesn't support namespaces.
2669 //-----------------------------------------------------------
2671 //-----------------------------------------------------------
2673 SymReaderNamespace::GetVariables(
2675 ULONG32 *pcVariables,
2676 ISymUnmanagedVariable *pVars[])
2678 // This symbol store doesn't support namespaces.
2684 /* ------------------------------------------------------------------------- *
2685 * SequencePoint struct functions
2686 * ------------------------------------------------------------------------- */
2688 //-----------------------------------------------------------
2689 // IsWithin - Is the point given within this sequence point
2690 //-----------------------------------------------------------
2691 bool SequencePoint::IsWithin(
2695 // If the sequence point starts on the same line
2696 // Check the start column (if present)
2697 if (StartLine() == line)
2699 if (0 < column && StartColumn() > column)
2705 // If the sequence point ends on the same line
2706 // Check the end column
2707 if (EndLine() == line)
2709 if (EndColumn() < column)
2715 // Make sure the line is within this sequence point
2716 if (!((StartLine() <= line) && (EndLine() >= line)))
2721 // Yep it's within this sequence point
2726 //-----------------------------------------------------------
2727 // IsWithinLineOnly - Is the given line within this sequence point
2728 //-----------------------------------------------------------
2729 bool SequencePoint::IsWithinLineOnly(
2732 return ((StartLine() <= line) && (line <= EndLine()));
2735 //-----------------------------------------------------------
2736 // IsGreaterThan - Is the sequence point greater than the position
2737 //-----------------------------------------------------------
2738 bool SequencePoint::IsGreaterThan(
2742 return (StartLine() > line) ||
2743 (StartLine() == line && StartColumn() > column);
2746 //-----------------------------------------------------------
2747 // IsLessThan - Is the sequence point less than the position
2748 //-----------------------------------------------------------
2749 bool SequencePoint::IsLessThan
2755 return (StartLine() < line) ||
2756 (StartLine() == line && StartColumn() < column);
2759 //-----------------------------------------------------------
2760 // IsUserLine - Is the sequence part of user code
2761 //-----------------------------------------------------------
2762 bool SequencePoint::IsUserLine()
2764 return StartLine() != CODE_WITH_NO_SOURCE;