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.
5 //*****************************************************************************
10 //*****************************************************************************
14 #include "metadataexports.h"
19 #include "ildbsymlib.h"
21 #include "pedecoder.h"
23 //---------------------------------------------------------------------------------------
24 // Update an existing metadata importer with a buffer
27 // pUnk - IUnknoown of importer to update.
28 // pData - local buffer containing new metadata
29 // cbData - size of buffer in bytes.
30 // dwReOpenFlags - metadata flags to pass for reopening.
33 // S_OK on success. Else failure.
36 // This will call code:MDReOpenMetaDataWithMemoryEx from the metadata engine.
37 STDAPI ReOpenMetaDataWithMemoryEx(
43 HRESULT hr = MDReOpenMetaDataWithMemoryEx(pUnk,pData, cbData, dwReOpenFlags);
47 //---------------------------------------------------------------------------------------
48 // Initialize a new CordbModule around a Module in the target.
51 // pProcess - process that this module lives in
52 // vmDomainFile - CLR cookie for module.
53 CordbModule::CordbModule(
54 CordbProcess * pProcess,
55 VMPTR_Module vmModule,
56 VMPTR_DomainFile vmDomainFile)
57 : CordbBase(pProcess, vmDomainFile.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainFile), enumCordbModule),
62 m_vmDomainFile(vmDomainFile),
65 m_isIlWinMD(Uninitialized),
66 m_fForceMetaDataSerialize(FALSE),
67 m_nativeCodeTable(101)
69 _ASSERTE(pProcess->GetProcessLock()->HasLock());
71 _ASSERTE(!vmModule.IsNull());
73 m_nLoadEventContinueCounter = 0;
75 m_classes.DebugSetRSLock(pProcess->GetProcessLock());
76 m_functions.DebugSetRSLock(pProcess->GetProcessLock());
79 // Fill out properties via DAC.
81 pProcess->GetDAC()->GetModuleData(vmModule, &modInfo); // throws
83 m_PEBuffer.Init(modInfo.pPEBaseAddress, modInfo.nPESize);
85 m_fDynamic = modInfo.fIsDynamic;
86 m_fInMemory = modInfo.fInMemory;
87 m_vmPEFile = modInfo.vmPEFile;
89 if (!vmDomainFile.IsNull())
91 DomainFileInfo dfInfo;
93 pProcess->GetDAC()->GetDomainFileData(vmDomainFile, &dfInfo); // throws
95 m_pAppDomain = pProcess->LookupOrCreateAppDomain(dfInfo.vmAppDomain);
96 m_pAssembly = m_pAppDomain->LookupOrCreateAssembly(dfInfo.vmDomainAssembly);
100 // Not yet implemented
101 m_pAppDomain = pProcess->GetSharedAppDomain();
102 m_pAssembly = m_pAppDomain->LookupOrCreateAssembly(modInfo.vmAssembly);
105 m_nativeCodeTable.DebugSetRSLock(GetProcess()->GetProcessLock());
108 // MetaData is initialized lazily (via code:CordbModule::GetMetaDataImporter).
109 // Getting the metadata may be very expensive (especially if we go through the metadata locator, which
110 // invokes back to the data-target), so don't do it until asked.
111 // m_pIMImport, m_pInternalMetaDataImport are smart pointers that already initialize to NULL.
116 //---------------------------------------------------------------------------------------
117 // Callback helper for code:CordbModule::DbgAssertModuleDeleted
120 // vmDomainFile - domain file in the enumeration
121 // pUserData - pointer to the CordbModule that we just got an exit event for.
123 void DbgAssertModuleDeletedCallback(VMPTR_DomainFile vmDomainFile, void * pUserData)
125 CordbModule * pThis = reinterpret_cast<CordbModule *>(pUserData);
126 INTERNAL_DAC_CALLBACK(pThis->GetProcess());
128 if (!pThis->m_vmDomainFile.IsNull())
130 VMPTR_DomainFile vmDomainFileDeleted = pThis->m_vmDomainFile;
132 CONSISTENCY_CHECK_MSGF((vmDomainFileDeleted != vmDomainFile),
133 ("A Module Unload event was sent for a module, but it still shows up in the enumeration.\n vmDomainFileDeleted=%p\n",
134 VmPtrToCookie(vmDomainFileDeleted)));
138 //---------------------------------------------------------------------------------------
139 // Assert that a module is no longer discoverable via enumeration.
142 // See code:IDacDbiInterface#Enumeration for rules that we're asserting.
143 // This is a debug only method. It's conceptually similar to
144 // code:CordbProcess::DbgAssertAppDomainDeleted.
146 void CordbModule::DbgAssertModuleDeleted()
148 GetProcess()->GetDAC()->EnumerateModulesInAssembly(
149 m_pAssembly->GetDomainAssemblyPtr(),
150 DbgAssertModuleDeletedCallback,
155 CordbModule::~CordbModule()
157 // We should have been explicitly neutered before our internal ref went to 0.
158 _ASSERTE(IsNeutered());
160 _ASSERTE(m_pIMImport == NULL);
163 // Neutered by CordbAppDomain
164 void CordbModule::Neuter()
166 // m_pAppDomain, m_pAssembly assigned w/o AddRef()
167 m_classes.NeuterAndClear(GetProcess()->GetProcessLock());
168 m_functions.NeuterAndClear(GetProcess()->GetProcessLock());
170 m_nativeCodeTable.NeuterAndClear(GetProcess()->GetProcessLock());
173 // This is very important because it also releases the metadata's potential file locks.
174 m_pInternalMetaDataImport.Clear();
181 // Creates an IStream based off the memory described by the TargetBuffer.
184 // pProcess - process that buffer is valid in.
185 // buffer - memory range in target
186 // ppStream - out parameter to receive the new stream. *ppStream == NULL on input.
187 // caller owns the new object and must call Release.
191 // Common errors include if memory is missing in the target.
194 // This will copy the memory over from the TargetBuffer, and then create a new IStream
197 void GetStreamFromTargetBuffer(CordbProcess * pProcess, TargetBuffer buffer, IStream ** ppStream)
205 _ASSERTE(ppStream != NULL);
206 _ASSERTE(*ppStream == NULL);
208 int cbSize = buffer.cbSize;
209 NewArrayHolder<BYTE> localBuffer(new BYTE[cbSize]);
211 pProcess->SafeReadBuffer(buffer, localBuffer);
214 hr = CInMemoryStream::CreateStreamOnMemoryCopy(localBuffer, cbSize, ppStream);
216 _ASSERTE(*ppStream != NULL);
220 // Helper API to get in-memory symbols from the target into a host stream object.
223 // ppStream - out parameter to receive the new stream. *ppStream == NULL on input.
224 // caller owns the new object and must call Release.
227 // kSymbolFormatNone if no PDB stream is present. This is a common case for
228 // file-based modules, and also for dynamic modules that just aren't tracking
229 // debug information.
230 // The format of the symbols stored into ppStream. This is common:
231 // - Ref.Emit modules if the debuggee generated debug symbols,
232 // - in-memory modules (such as Load(Byte[], Byte[])
236 IDacDbiInterface::SymbolFormat CordbModule::GetInMemorySymbolStream(IStream ** ppStream)
238 // @dbgtodo : add a PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM contract
239 // This function is mainly called internally in dbi, and also by the shim to emulate the
240 // UpdateModuleSymbols callback on attach.
248 _ASSERTE(ppStream != NULL);
249 _ASSERTE(*ppStream == NULL);
252 TargetBuffer bufferPdb;
253 IDacDbiInterface::SymbolFormat symFormat;
254 GetProcess()->GetDAC()->GetSymbolsBuffer(m_vmModule, &bufferPdb, &symFormat);
255 if (bufferPdb.IsEmpty())
257 // No in-memory PDB. Common case.
258 _ASSERTE(symFormat == IDacDbiInterface::kSymbolFormatNone);
259 return IDacDbiInterface::kSymbolFormatNone;
263 _ASSERTE(symFormat != IDacDbiInterface::kSymbolFormatNone);
264 GetStreamFromTargetBuffer(GetProcess(), bufferPdb, ppStream);
269 //---------------------------------------------------------------------------------------
270 // Accessor for PE file.
273 // VMPTR_PEFile for this module. Should always be non-null
276 // A main usage of this is to find the proper internal MetaData importer.
277 // DACized code needs to map from PEFile --> IMDInternalImport.
279 VMPTR_PEFile CordbModule::GetPEFile()
284 //---------------------------------------------------------------------------------------
286 // Top-level getter for the public metadata importer for this module
289 // metadata importer.
290 // Never returns NULL. Will throw some hr (likely CORDBG_E_MISSING_METADATA) instead.
293 // This will lazily create the metadata, possibly invoking back into the data-target.
294 IMetaDataImport * CordbModule::GetMetaDataImporter()
303 // If we already have it, then we're done.
304 // This is critical to do at the top of this function to avoid potential recursion.
305 if (m_pIMImport != NULL)
313 // Fetch metadata from target
314 LOG((LF_CORDB,LL_INFO1000, "CM::GMI Lazy init refreshing metadata\n"));
316 ALLOW_DATATARGET_MISSING_MEMORY(
320 // If lookup failed from the Module & target memory, try the metadata locator interface
321 // from debugger, if we have one.
322 if (m_pIMImport == NULL)
324 bool isILMetaDataForNGENImage; // Not currently used for anything.
326 // The process's LookupMetaData will ping the debugger's ICorDebugMetaDataLocator iface.
327 CordbProcess * pProcess = GetProcess();
328 RSLockHolder processLockHolder(pProcess->GetProcessLock());
329 m_pInternalMetaDataImport.Clear();
331 // Do not call code:CordbProcess::LookupMetaData from this function. It will try to load
332 // through the CordbModule again which will end up back here, and on failure you'll fill the stack.
333 // Since we've already done everything possible from the Module anyhow, just call the
334 // stuff that talks to the debugger.
335 // Don't do anything with the ptr returned here, since it's really m_pInternalMetaDataImport.
336 pProcess->LookupMetaDataFromDebugger(m_vmPEFile, isILMetaDataForNGENImage, this);
339 // If we still can't get it, throw.
340 if (m_pIMImport == NULL)
342 ThrowHR(CORDBG_E_MISSING_METADATA);
348 // Refresh the metadata cache if a profiler added new rows.
351 // token - token that we want to ensure is in the metadata cache.
354 // In profiler case, this may be referred to new rows and we may need to update the metadata
355 // This only supports StandAloneSigs.
357 void CordbModule::UpdateMetaDataCacheIfNeeded(mdToken token)
365 LOG((LF_CORDB,LL_INFO10000, "CM::UMCIN token=0x%x\n", token));
367 // If we aren't trying to keep parity with our legacy profiler metadata update behavior
368 // then we should avoid this temporary update mechanism entirely
369 if(GetProcess()->GetWriteableMetadataUpdateMode() != LegacyCompatPolicy)
374 // the metadata in WinMD is currently static since there's no
375 // support for profilers or EnC so we can simply exit early.
378 LOG((LF_CORDB,LL_INFO10000, "CM::UMCIN token is in WinMD, exiting\n"));
383 // 1) Check if in-range? Compare against tables, etc.
385 if(CheckIfTokenInMetaData(token))
387 LOG((LF_CORDB,LL_INFO10000, "CM::UMCIN token was present\n"));
392 // 2) Copy over new MetaData. From now on we assume that the profiler is
393 // modifying module metadata and that we need to serialize in process
396 LOG((LF_CORDB,LL_INFO10000, "CM::UMCIN token was not present, refreshing\n"));
397 m_fForceMetaDataSerialize = TRUE;
400 // If we are dump debugging, we may still not have it. Nothing to be done.
403 // Returns TRUE if the token is present, FALSE if not.
404 BOOL CordbModule::CheckIfTokenInMetaData(mdToken token)
411 LOG((LF_CORDB,LL_INFO10000, "CM::CITIM token=0x%x\n", token));
412 _ASSERTE(TypeFromToken(token) == mdtSignature);
413 // we shouldn't be doing this on WinMD modules since they don't implement IID_IMetaDataTables
414 _ASSERTE(!IsWinMD());
415 RSExtSmartPtr<IMetaDataTables> pTable;
417 HRESULT hr = GetMetaDataImporter()->QueryInterface(IID_IMetaDataTables, (void**) &pTable);
419 _ASSERTE(SUCCEEDED(hr));
425 ULONG cbRowsAvailable; // number of rows in the table
427 hr = pTable->GetTableInfo(
428 mdtSignature >> 24, // [IN] Which table.
429 NULL, // [OUT] Size of a row, bytes.
430 &cbRowsAvailable, // [OUT] Number of rows.
431 NULL, // [OUT] Number of columns in each row.
432 NULL, // [OUT] Key column, or -1 if none.
433 NULL); // [OUT] Name of the table.
435 _ASSERTE(SUCCEEDED(hr));
442 // Rows start counting with number 1.
443 ULONG rowRequested = RidFromToken(token);
444 LOG((LF_CORDB,LL_INFO10000, "CM::UMCIN requested=0x%x available=0x%x\n", rowRequested, cbRowsAvailable));
445 return (rowRequested <= cbRowsAvailable);
448 // This helper class ensures the remote serailzied buffer gets deleted in the RefreshMetaData
450 class CleanupRemoteBuffer
453 CordbProcess* pProcess;
454 CordbModule* pModule;
455 TargetBuffer bufferMetaData;
458 CleanupRemoteBuffer() :
459 fDoCleanup(FALSE) { }
461 ~CleanupRemoteBuffer()
466 // Send 2nd event to free buffer.
468 DebuggerIPCEvent event;
469 pProcess->InitIPCEvent(&event,
470 DB_IPCE_RESOLVE_UPDATE_METADATA_2,
472 pModule->GetAppDomain()->GetADToken());
474 event.MetadataUpdateRequest.pMetadataStart = CORDB_ADDRESS_TO_PTR(bufferMetaData.pAddress);
476 // Note: two-way event here...
477 IfFailThrow(pProcess->SendIPCEvent(&event, sizeof(DebuggerIPCEvent)));
478 _ASSERTE(event.type == DB_IPCE_RESOLVE_UPDATE_METADATA_2_RESULT);
484 // Called to refetch metadata. This occurs when a dynamic module grows or the profiler
485 // has edited the metadata
486 void CordbModule::RefreshMetaData()
494 LOG((LF_CORDB,LL_INFO1000, "CM::RM\n"));
496 // There are several different ways we can get the metadata
497 // 1) [Most common] Module is loaded into VM and never changed. The importer
498 // will be constructed refering to the file on disk. This is a significant
499 // working set win because the VM and debugger share the image. If there is
500 // an error reading by file we can fall back to case #2 for these modules
501 // 2) Most modules have a buffer in target memory that represents their
502 // metadata. We copy that data over the RS and construct an in-memory
503 // importer on top of it.
504 // 3) The only modules that don't have a suitable buffer (case #2) are those
505 // modified in memory via the profiling API (or ENC). A message can be sent from
506 // the debugger to the debuggee instructing it to allocate a buffer and
507 // serialize the metadata into it. Then we copy that data to the RS and
508 // construct an in-memory importer on top of it.
509 // We don't need to send this message in the ENC case because the debugger
510 // has the same changes applied as the debuggee.
511 // 4) Case #3 won't work when dump debugging because we can't send IPC events.
512 // Instead we can locate chunks of the metadata pointed to in the implementation
513 // details of a remote MDInternalRW object, marshal that memory over to the
514 // debugger process, and then put a metadata reader on top of it.
515 // In time this DAC'ized metadata could be used in almost any scenario,
516 // although its probably worth keeping the file mapping technique in case
517 // #1 around for its performance wins.
519 CordbProcess * pProcess = GetProcess();
520 TargetBuffer bufferMetaData;
521 CleanupRemoteBuffer cleanup; // this local has a destructor to do some finally work
524 // check for scenarios we might want to handle with case #4
525 if (GetProcess()->GetShim() == NULL &&
526 GetProcess()->GetWriteableMetadataUpdateMode() == AlwaysShowUpdates &&
529 //None of the above requirements are particularly hard to change in the future as needed...
530 // a) dump-debugging mode - If we do this on a process that can move forward we need a mechanism to determine
531 // when to refetch the metadata.
532 // b) AlwaysShowUpdates - this is purely a risk mitigation choice, there aren't any known back-compat issues
533 // using DAC'ized metadata. If you want back-compat with the in-proc debugging behavior
534 // you need to figure out how to ReOpen the same public MD interface with new data.
535 // c) !m_fDynamic - A risk mitigation choice. Initial testing suggests it would work fine.
538 // So far we've only got a reader for in-memory-writable metadata (MDInternalRW implementation)
539 // We could make a reader for MDInternalRO, but no need yet. This also ensures we don't encroach into common
540 // scenario where we can map a file on disk.
541 TADDR remoteMDInternalRWAddr = NULL;
542 GetProcess()->GetDAC()->GetPEFileMDInternalRW(m_vmPEFile, &remoteMDInternalRWAddr);
543 if (remoteMDInternalRWAddr != NULL)
545 // we should only be doing this once to initialize, we don't support reopen with this technique
546 _ASSERTE(m_pIMImport == NULL);
547 ULONG32 mdStructuresVersion;
548 HRESULT hr = GetProcess()->GetDAC()->GetMDStructuresVersion(&mdStructuresVersion);
550 ULONG32 mdStructuresDefines;
551 hr = GetProcess()->GetDAC()->GetDefinesBitField(&mdStructuresDefines);
553 IMetaDataDispenserCustom* pDispCustom = NULL;
554 hr = GetProcess()->GetDispenser()->QueryInterface(IID_IMetaDataDispenserCustom, (void**)&pDispCustom);
556 IMDCustomDataSource* pDataSource = NULL;
557 hr = CreateRemoteMDInternalRWSource(remoteMDInternalRWAddr, GetProcess()->GetDataTarget(), mdStructuresDefines, mdStructuresVersion, &pDataSource);
559 IMetaDataImport* pImport = NULL;
560 hr = pDispCustom->OpenScopeOnCustomDataSource(pDataSource, 0, IID_IMetaDataImport, (IUnknown**)&m_pIMImport);
562 UpdateInternalMetaData();
567 if(!m_fForceMetaDataSerialize) // case 1 and 2
569 LOG((LF_CORDB,LL_INFO10000, "CM::RM !m_fForceMetaDataSerialize case\n"));
570 GetProcess()->GetDAC()->GetMetadata(m_vmModule, &bufferMetaData); // throws
572 else if (GetProcess()->GetShim() == NULL) // case 3 won't work on a dump so don't try
576 else // case 3 on a live process
578 LOG((LF_CORDB,LL_INFO10000, "CM::RM m_fForceMetaDataSerialize case\n"));
580 // Send 1 event to get metadata. This allocates a buffer
582 DebuggerIPCEvent event;
583 pProcess->InitIPCEvent(&event,
584 DB_IPCE_RESOLVE_UPDATE_METADATA_1,
586 GetAppDomain()->GetADToken());
588 event.MetadataUpdateRequest.vmModule = m_vmModule;
590 // Note: two-way event here...
591 IfFailThrow(pProcess->SendIPCEvent(&event, sizeof(DebuggerIPCEvent)));
593 _ASSERTE(event.type == DB_IPCE_RESOLVE_UPDATE_METADATA_1_RESULT);
596 // Update it on the RS
598 bufferMetaData.Init(PTR_TO_CORDB_ADDRESS(event.MetadataUpdateRequest.pMetadataStart), (ULONG) event.MetadataUpdateRequest.nMetadataSize);
600 // init the cleanup object to ensure the buffer gets destroyed later
601 cleanup.bufferMetaData = bufferMetaData;
602 cleanup.pProcess = pProcess;
603 cleanup.pModule = this;
604 cleanup.fDoCleanup = TRUE;
607 InitMetaData(bufferMetaData, IsFileMetaDataValid()); // throws
610 // Determines whether the on-disk metadata for this module is usable as the
612 BOOL CordbModule::IsFileMetaDataValid()
614 bool fOpenFromFile = true;
616 // Dynamic, In-memory, modules must be OpenScopeOnMemory.
617 // For modules that require the metadata to be serialized in memory, we must also OpenScopeOnMemory
618 // For Enc, we'll can use OpenScope(onFile) and it will get converted to Memory when we get an emitter.
619 // We're called from before the ModuleLoad callback, so EnC status hasn't been set yet, so
620 // EnC will be false.
621 if (m_fDynamic || m_fInMemory || m_fForceMetaDataSerialize)
623 LOG((LF_CORDB,LL_INFO10000, "CM::IFMV: m_fDynamic=0x%x m_fInMemory=0x%x m_fForceMetaDataSerialize=0x%x\n",
624 m_fDynamic, m_fInMemory, m_fForceMetaDataSerialize));
625 fOpenFromFile = false;
629 // Reg key override to force us to use Open-by-memory. This can let us run perf tests to
630 // compare the Open-by-mem vs. Open-by-file.
631 static DWORD openFromFile = 99;
632 if (openFromFile == 99)
633 openFromFile = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgNoOpenMDByFile);
637 LOG((LF_CORDB,LL_INFO10000, "CM::IFMV: INTERNAL_DbgNoOpenMDByFile is set\n"));
638 fOpenFromFile = false;
642 LOG((LF_CORDB,LL_INFO10000, "CM::IFMV: returns 0x%x\n", fOpenFromFile));
643 return fOpenFromFile;
646 //---------------------------------------------------------------------------------------
647 // Accessor for Internal MetaData importer. This is lazily initialized.
650 // Internal MetaDataImporter, which can be handed off to DAC. Not AddRef().
651 // Should be non-null. Throws on error.
654 // An internal metadata importer is used extensively by DAC-ized code (And Edit-and-continue).
655 // This should not be handed out through ICorDebug.
656 IMDInternalImport * CordbModule::GetInternalMD()
658 if (m_pInternalMetaDataImport == NULL)
660 UpdateInternalMetaData(); // throws
662 return m_pInternalMetaDataImport;
665 //---------------------------------------------------------------------------------------
666 // The one-stop top-level initialization function the metadata (both public and private) for this module.
669 // buffer - valid buffer into target containing the metadata.
670 // useFileMappingOptimization - if true this allows us to attempt just opening the importer
671 // by using the metadata in the module on disk. if false or
672 // if the attempt fails we open the metadata import on memory in
676 // This will initialize both the internal and public metadata from the buffer in the target.
677 // Only called as a helper from RefreshMetaData()
679 // This may throw (eg, target buffer is missing).
681 void CordbModule::InitMetaData(TargetBuffer buffer, BOOL allowFileMappingOptimization)
689 LOG((LF_CORDB,LL_INFO100000, "CM::IM: initing with remote buffer 0x%p length 0x%x\n",
690 CORDB_ADDRESS_TO_PTR(buffer.pAddress), buffer.cbSize));
692 // clear all the metadata
693 m_pInternalMetaDataImport.Clear();
695 if (m_pIMImport == NULL)
697 // The optimization we're going for here is that the OS will use the same physical memory to
698 // back multiple ReadOnly opens of the same file. Thus since we expect the target process in
699 // live debugging, or the debugger in dump debugging, has already opened the file we would
700 // like to not create a local buffer and spend time copying in metadata from the target when
701 // the OS will happily do address lookup magic against the same physical memory for everyone.
704 // Try getting the data from the file if allowed, and fall back to using the buffer
707 if (allowFileMappingOptimization)
709 hr = InitPublicMetaDataFromFile();
712 LOG((LF_CORDB,LL_INFO1000000, "CM::IPM: File mapping failed with hr=0x%x\n", hr));
716 if(!allowFileMappingOptimization || FAILED(hr))
718 // This is where the expensive copy of all metadata content from target memory
719 // that we would like to try and avoid happens.
720 InitPublicMetaData(buffer);
725 // We've already handed out an Import object, and so we can't create a new pointer instance.
726 // Instead, we update the existing instance with new data.
727 UpdatePublicMetaDataFromRemote(buffer);
730 // if we haven't set it by this point UpdateInternalMetaData below is going to get us
731 // in an infinite loop of refreshing public metadata
732 _ASSERTE(m_pIMImport != NULL);
734 // Now that public metadata has changed, force internal metadata to update too.
735 // Public and internal metadata expose different access interfaces to the same underlying storage.
736 UpdateInternalMetaData();
739 //---------------------------------------------------------------------------------------
740 // Updates the Internal MetaData object from the public importer. Lazily fetch public importer if needed.
743 // Caller has cleared Internal metadata before even updating public metadata.
744 // This way, if the caller fails halfway through updating the public metadata, we don't have
745 // stale internal MetaData.
746 void CordbModule::UpdateInternalMetaData()
754 // Caller should have already cleared it.
755 _ASSERTE(m_pInternalMetaDataImport == NULL);
757 // Get the importer. If it's currently null, this will go fetch it.
758 IMetaDataImport * pImport = GetMetaDataImporter(); // throws
760 // If both the public and the private interfaces are NULL on entry to this function, the call above will
761 // recursively call this function. This can happen if the caller calls GetInternalMD() directly
762 // instead of InitMetaData(). In this case, the above function call will have initialized the internal
763 // interface as well, so we need to check for it here.
765 if (m_pInternalMetaDataImport == NULL)
767 HRESULT hr = GetMDInternalInterfaceFromPublic(
769 IID_IMDInternalImport,
770 reinterpret_cast<void**> (&m_pInternalMetaDataImport));
772 if (m_pInternalMetaDataImport == NULL)
778 _ASSERTE(m_pInternalMetaDataImport != NULL);
781 // Initialize the public metadata.
783 // The debuggee already has a copy of the metadata in its process.
784 // If we OpenScope on file as read-only, the OS file-system will share our metadata with the
785 // copy in the debuggee. This can be a major perf win. FX metadata can be over 8 MB+.
786 // OpenScopeOnMemory can't be shared b/c we allocate a buffer.
787 HRESULT CordbModule::InitPublicMetaDataFromFile()
789 INTERNAL_API_ENTRY(this->GetProcess());
791 // @dbgtodo metadata - In v3, we can't assume we have the same path namespace as the target (i.e. it could be
792 // a dump or remote), so we can't just try and open the file. Instead we have to rely on interfaces
793 // on the datatarget to map the metadata here. Note that this must also work for minidumps where the
794 // metadata isn't necessarily in the dump image.
796 // Get filename. There are 2 filenames to choose from:
797 // - ngen (if applicable).
798 // - non-ngen (aka "normal").
799 // By loading metadata out of the same OS file as loaded into the debuggee space, the OS can share those pages.
800 const WCHAR * szFullPathName = NULL;
801 bool fDebuggerLoadingNgen = false;
802 bool fDebuggeeLoadedNgen = false;
803 szFullPathName = GetNGenImagePath();
805 if(szFullPathName != NULL)
807 fDebuggeeLoadedNgen = true;
808 fDebuggerLoadingNgen = true;
811 // NGEN images are large and we shouldn't load them if they won't be shared, therefore fail the NGEN mapping and
812 // fallback to IL image if the debugger doesn't have the image loaded already.
813 // Its possible that the debugger would still load the NGEN image sometime in the future and we will miss a sharing
814 // opportunity. Its an acceptable loss from an imperfect heuristic.
815 if (NULL == WszGetModuleHandle(szFullPathName))
818 szFullPathName = NULL;
819 fDebuggerLoadingNgen = false;
824 // If we don't have or decided not to load the NGEN image, check to see if IL image is available
825 if (!fDebuggerLoadingNgen)
827 szFullPathName = GetModulePath();
830 // If we are doing live debugging we shouldn't use metadata from an IL image because it doesn't match closely enough.
831 // In particular the RVAs for IL code headers are different between the two images which will cause all IL code and
832 // local var signature lookups to fail. With further work we could compensate for the RVAs by computing
833 // the image layout differences and adjusting the returned RVAs, but there may be other differences that need to be accounted
834 // for as well. If we did go that route we should do a binary diff across a variety of NGEN/IL image metadata blobs to
835 // get a concrete understanding of the format differences.
837 // This check should really be 'Are we OK with only getting the functionality level of mini-dump debugging?' but since we
838 // don't know the debugger's intent we guess whether or not we are doing dump debugging by checking if we are shimmed. Once
839 // the shim supports live debugging we should probably just stop automatically falling back to IL image and let the debugger
840 // decide via the ICorDebugMetadataLocator interface.
841 if(fDebuggeeLoadedNgen && !fDebuggerLoadingNgen && GetProcess()->GetShim()!=NULL)
843 // The IL image might be there, but we shouldn't use it for live debugging
844 return CORDBG_E_MISSING_METADATA;
848 // @dbgtodo metadata - This is really a CreateFile() call which we can't do. We must offload this to
849 // the data target for the dump-debugging scenarios.
851 // We're opening it as "read". If we QI for an IEmit interface (which we need for EnC),
852 // then the metadata engine will convert it to a "write" underneath us.
853 // We want "read" so that we can let the OS share the pages.
854 DWORD dwOpenFlags = 0;
856 // If we know we're never going to need to write (i.e. never do EnC), then we should indicate
857 // that to metadata by telling it this interface will always be read-only. By passing read-only,
858 // the metadata library will then also share the VM space for the image when the same image is
859 // opened multiple times for multiple AppDomains.
860 // We don't currently have a way to tell absolutely whether this module will support EnC, but we
861 // know that NGen modules NEVER support EnC, and NGen is the common case that eats up a lot of VM.
862 // So we'll use the heuristic of opening the metadata for all ngen images as read-only. Ideally
863 // we'd go even further here (perhaps even changing metadata to map only the region of the file it
865 if (fDebuggerLoadingNgen)
867 dwOpenFlags = ofReadOnly | ofTrustedImage;
870 // This is the only place we ever validate that the file matches, because we're potentially
871 // loading the file from disk ourselves. We're doing this without giving the debugger a chance
872 // to do anything. We should never load a file that isn't an exact match.
873 return InitPublicMetaDataFromFile(szFullPathName, dwOpenFlags, true);
876 // We should only ever validate we have the correct file if it's a file we found ourselves.
877 // We allow the debugger to choose their own policy with regard to using metadata from the IL image
878 // when debugging an NI, or even intentionally using mismatched metadata if they like.
879 HRESULT CordbModule::InitPublicMetaDataFromFile(const WCHAR * pszFullPathName,
881 bool validateFileInfo)
884 // UNIXTODO: Some intricate details of file mapping don't work on Linux as on Windows.
885 // We have to revisit this and try to fix it for POSIX system.
888 if (validateFileInfo)
890 // Check that we've got the right file to target.
891 // There's nothing to prevent some other file being copied in for live, and with
892 // dump debugging there's nothing to say that we're not on another machine where a different
893 // file is at the same path.
894 // If we can't validate we have a hold of the correct file, we should not open it.
895 // We will fall back on asking the debugger to get us the correct file, or copying
896 // target memory back to the debugger.
897 DWORD dwImageTimeStamp = 0;
898 DWORD dwImageSize = 0;
899 bool isNGEN = false; // unused
900 StringCopyHolder filePath;
903 _ASSERTE(!m_vmPEFile.IsNull());
904 // MetaData lookup favors the NGEN image, which is what we want here.
905 if (!this->GetProcess()->GetDAC()->GetMetaDataFileInfoFromPEFile(m_vmPEFile,
911 LOG((LF_CORDB,LL_WARNING, "CM::IM: Couldn't get metadata info for file \"%s\"\n", pszFullPathName));
912 return CORDBG_E_MISSING_METADATA;
915 // If the timestamp and size don't match, then this is the wrong file!
916 // Map the file and check them.
917 HandleHolder hMDFile = WszCreateFile(pszFullPathName,
920 NULL, // default security descriptor
922 FILE_ATTRIBUTE_NORMAL,
925 if (hMDFile == INVALID_HANDLE_VALUE)
927 LOG((LF_CORDB,LL_WARNING, "CM::IM: Couldn't open file \"%s\" (GLE=%x)\n", pszFullPathName, GetLastError()));
928 return CORDBG_E_MISSING_METADATA;
931 DWORD dwFileHigh = 0;
932 DWORD dwFileLow = GetFileSize(hMDFile, &dwFileHigh);
933 if (dwFileLow == INVALID_FILE_SIZE)
935 LOG((LF_CORDB,LL_WARNING, "CM::IM: File \"%s\" had invalid size.\n", pszFullPathName));
936 return CORDBG_E_MISSING_METADATA;
939 _ASSERTE(dwFileHigh == 0);
941 HandleHolder hMap = WszCreateFileMapping(hMDFile, NULL, PAGE_READONLY, dwFileHigh, dwFileLow, NULL);
944 LOG((LF_CORDB,LL_WARNING, "CM::IM: Couldn't create mapping of file \"%s\" (GLE=%x)\n", pszFullPathName, GetLastError()));
945 return CORDBG_E_MISSING_METADATA;
948 MapViewHolder hMapView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
949 if (hMapView == NULL)
951 LOG((LF_CORDB,LL_WARNING, "CM::IM: Couldn't map view of file \"%s\" (GLE=%x)\n", pszFullPathName, GetLastError()));
952 return CORDBG_E_MISSING_METADATA;
955 // Mapped as flat file, have PEDecoder go find what we want.
956 PEDecoder pedecoder(hMapView, (COUNT_T)dwFileLow);
958 if (!pedecoder.HasNTHeaders())
960 LOG((LF_CORDB,LL_WARNING, "CM::IM: \"%s\" did not have PE headers!\n", pszFullPathName));
961 return CORDBG_E_MISSING_METADATA;
964 if ((dwImageSize != pedecoder.GetVirtualSize()) ||
965 (dwImageTimeStamp != pedecoder.GetTimeDateStamp()))
967 LOG((LF_CORDB,LL_WARNING, "CM::IM: Validation of \"%s\" failed. "
968 "Expected size=%x, Expected timestamp=%x, Actual size=%x, Actual timestamp=%x\n",
970 pedecoder.GetVirtualSize(),
971 pedecoder.GetTimeDateStamp(),
974 return CORDBG_E_MISSING_METADATA;
977 // All checks passed, go ahead and load this file for real.
980 // Get metadata Dispenser.
981 IMetaDataDispenserEx * pDisp = GetProcess()->GetDispenser();
983 HRESULT hr = pDisp->OpenScope(pszFullPathName, dwOpenFlags, IID_IMetaDataImport, (IUnknown**)&m_pIMImport);
984 _ASSERTE(SUCCEEDED(hr) == (m_pIMImport != NULL));
988 // This should never happen in normal scenarios. It could happen if someone has renamed
989 // the assembly after it was opened by the debugee process, but this should be rare enough
990 // that we don't mind taking the perf. hit and loading from memory.
991 // @dbgtodo metadata - would this happen in the shadow-copy scenario?
992 LOG((LF_CORDB,LL_WARNING, "CM::IM: Couldn't open metadata in file \"%s\" (hr=%x)\n", pszFullPathName, hr));
996 #endif // FEATURE_PAL
999 //---------------------------------------------------------------------------------------
1000 // Initialize the public metadata.
1003 // buffer - valid buffer into target containing the metadata.
1006 // This is an internal function which should only be called once to initialize the
1007 // metadata. Future attempts to re-initialize (in dynamic cases) should call code:CordbModule::UpdatePublicMetaDataFromRemote
1008 // After the public metadata is initialized, initialize private metadata via code:CordbModule::UpdateInternalMetaData
1010 void CordbModule::InitPublicMetaData(TargetBuffer buffer)
1018 INTERNAL_API_ENTRY(this->GetProcess());
1019 LOG((LF_CORDB,LL_INFO100000, "CM::IPM: initing with remote buffer 0x%p length 0x%x\n",
1020 CORDB_ADDRESS_TO_PTR(buffer.pAddress), buffer.cbSize));
1021 ULONG nMetaDataSize = buffer.cbSize;
1023 if (nMetaDataSize == 0)
1025 // We should always have metadata, and if we don't, we want to know.
1026 // @dbgtodo metadata - we know metadata from dynamic modules doesn't work in V3
1027 // (non-shim) cases yet.
1028 // But our caller should already have handled that case.
1029 SIMPLIFYING_ASSUMPTION(!"Error: missing the metadata");
1035 // Get metadata Dispenser.
1036 IMetaDataDispenserEx * pDisp = GetProcess()->GetDispenser();
1038 // copy it over from the remote process
1040 CoTaskMemHolder<VOID> pMetaDataCopy;
1041 CopyRemoteMetaData(buffer, pMetaDataCopy.GetAddr());
1045 // Setup our metadata import object, m_pIMImport
1048 // Save the old mode for restoration
1050 hr = pDisp->GetOption(MetaDataSetUpdate, &valueOld);
1051 SIMPLIFYING_ASSUMPTION(!FAILED(hr));
1053 // Set R/W mode so that we can update the metadata when
1054 // we do EnC operations.
1056 V_VT(&valueRW) = VT_UI4;
1057 V_I4(&valueRW) = MDUpdateFull;
1058 hr = pDisp->SetOption(MetaDataSetUpdate, &valueRW);
1059 SIMPLIFYING_ASSUMPTION(!FAILED(hr));
1061 hr = pDisp->OpenScopeOnMemory(pMetaDataCopy,
1064 IID_IMetaDataImport,
1065 reinterpret_cast<IUnknown**>( &m_pIMImport ));
1067 // MetaData has taken ownership -don't free the memory
1068 pMetaDataCopy.SuppressRelease();
1070 // Immediately restore the old setting.
1071 HRESULT hrRestore = pDisp->SetOption(MetaDataSetUpdate, &valueOld);
1072 SIMPLIFYING_ASSUMPTION(!FAILED(hrRestore));
1076 IfFailThrow(hrRestore);
1081 //---------------------------------------------------------------------------------------
1082 // Update public MetaData by copying it from the target and updating our IMetaDataImport object.
1085 // buffer - buffer into target space containing metadata blob
1088 // Useful for additional class-loads into a dynamic module. A new class means new metadata
1089 // and so we need to update the RS metadata to stay in sync with the left-side.
1091 // This will call code:CordbModule::CopyRemoteMetaData to copy the remote buffer locally, and then
1092 // it can OpenScopeOnMemory().
1094 void CordbModule::UpdatePublicMetaDataFromRemote(TargetBuffer bufferRemoteMetaData)
1098 // @dbgtodo metadata - think about the error semantics here. These fails during dispatching an event; so
1099 // address this during event pipeline.
1104 if (bufferRemoteMetaData.IsEmpty())
1106 ThrowHR(E_INVALIDARG);
1109 INTERNAL_API_ENTRY(this->GetProcess()); //
1110 LOG((LF_CORDB,LL_INFO100000, "CM::UPMFR: updating with remote buffer 0x%p length 0x%x\n",
1111 CORDB_ADDRESS_TO_PTR(bufferRemoteMetaData.pAddress), bufferRemoteMetaData.cbSize));
1112 // We're re-initializing existing metadata.
1113 _ASSERTE(m_pIMImport != NULL);
1118 ULONG dwMetaDataSize = bufferRemoteMetaData.cbSize;
1120 // First copy it from the remote process
1121 CoTaskMemHolder<VOID> pLocalMetaDataPtr;
1122 CopyRemoteMetaData(bufferRemoteMetaData, pLocalMetaDataPtr.GetAddr());
1124 IMetaDataDispenserEx * pDisp = GetProcess()->GetDispenser();
1125 _ASSERTE(pDisp != NULL); // throws on error.
1127 LOG((LF_CORDB,LL_INFO100000, "CM::RI: converting to new metadata\n"));
1129 // now verify that the metadata is valid by opening a temporary scope on the memory
1131 ReleaseHolder<IMetaDataImport> pIMImport;
1132 hr = pDisp->OpenScopeOnMemory(pLocalMetaDataPtr,
1135 IID_IMetaDataImport,
1136 (IUnknown**)&pIMImport);
1140 // We reopen on an existing instance, not create a new instance.
1141 _ASSERTE(m_pIMImport != NULL); //
1143 // Now tell our current IMetaDataImport object to re-initialize by swapping in the new memory block.
1144 // This allows us to keep manipulating metadata objects on other threads without crashing.
1145 // This will also invalidate an existing associated Internal MetaData.
1146 hr = ReOpenMetaDataWithMemoryEx(m_pIMImport, pLocalMetaDataPtr, dwMetaDataSize, ofTakeOwnership );
1149 // Success. MetaData now owns the metadata memory
1150 pLocalMetaDataPtr.SuppressRelease();
1153 //---------------------------------------------------------------------------------------
1154 // Copy metadata memory from the remote process into a newly allocated local buffer.
1157 // pRemoteMetaDataPtr - pointer to remote buffer
1158 // dwMetaDataSize - size of buffer.
1159 // pLocalBuffer - holder to get local buffer.
1162 // pLocalBuffer may be allocated.
1163 // Throws on error (pLocalBuffer may contain garbage).
1164 // Else if successful, pLocalBuffer contains local copy of metadata.
1167 // This can copy metadata out for the dynamic case or the normal case.
1168 // Uses an allocator (CoTaskMemHolder) that lets us hand off the memory to the metadata.
1169 void CordbModule::CopyRemoteMetaData(
1170 TargetBuffer buffer,
1171 CoTaskMemHolder<VOID> * pLocalBuffer)
1179 _ASSERTE(pLocalBuffer != NULL);
1180 _ASSERTE(!buffer.IsEmpty());
1182 // Allocate space for the local copy of the metadata
1183 // No need to zero out the memory since we'll fill it all here.
1184 LPVOID pRawBuffer = CoTaskMemAlloc(buffer.cbSize);
1185 if (pRawBuffer == NULL)
1190 pLocalBuffer->Assign(pRawBuffer);
1194 // Copy the metadata from the left side
1195 GetProcess()->SafeReadBuffer(buffer, (BYTE *)pRawBuffer);
1200 HRESULT CordbModule::QueryInterface(REFIID id, void **pInterface)
1202 if (id == IID_ICorDebugModule)
1204 *pInterface = static_cast<ICorDebugModule*>(this);
1206 else if (id == IID_ICorDebugModule2)
1208 *pInterface = static_cast<ICorDebugModule2*>(this);
1210 else if (id == IID_ICorDebugModule3)
1212 *pInterface = static_cast<ICorDebugModule3*>(this);
1214 else if (id == IID_IUnknown)
1216 *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugModule*>(this));
1221 return E_NOINTERFACE;
1228 HRESULT CordbModule::GetProcess(ICorDebugProcess **ppProcess)
1230 PUBLIC_API_ENTRY(this);
1231 FAIL_IF_NEUTERED(this);
1232 VALIDATE_POINTER_TO_OBJECT(ppProcess, ICorDebugProcess **);
1234 *ppProcess = static_cast<ICorDebugProcess*> (GetProcess());
1235 GetProcess()->ExternalAddRef();
1240 HRESULT CordbModule::GetBaseAddress(CORDB_ADDRESS *pAddress)
1242 PUBLIC_API_ENTRY(this);
1243 FAIL_IF_NEUTERED(this);
1244 VALIDATE_POINTER_TO_OBJECT(pAddress, CORDB_ADDRESS *);
1246 *pAddress = m_PEBuffer.pAddress;
1250 HRESULT CordbModule::GetAssembly(ICorDebugAssembly **ppAssembly)
1252 PUBLIC_API_ENTRY(this);
1253 FAIL_IF_NEUTERED(this);
1254 VALIDATE_POINTER_TO_OBJECT(ppAssembly, ICorDebugAssembly **);
1256 *ppAssembly = static_cast<ICorDebugAssembly *> (m_pAssembly);
1257 if (m_pAssembly != NULL)
1259 m_pAssembly->ExternalAddRef();
1265 // Public implementation of ICorDebugModule::GetName,
1266 // wrapper around code:GetNameWorker (which throws).
1267 HRESULT CordbModule::GetName(ULONG32 cchName, ULONG32 *pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
1270 PUBLIC_API_BEGIN(this)
1274 hr = GetNameWorker(cchName, pcchName, szName);
1276 EX_CATCH_HRESULT(hr);
1278 // GetNameWorker can use metadata. If it fails due to missing metadata, or if we fail to find expected
1279 // target memory (dump debugging) then we should fall back to getting the file name without metadata.
1280 if ((hr == CORDBG_E_MISSING_METADATA) ||
1281 (hr == CORDBG_E_READVIRTUAL_FAILURE) ||
1282 (hr == HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY)))
1284 DWORD dwImageTimeStamp = 0; // unused
1285 DWORD dwImageSize = 0; // unused
1286 bool isNGEN = false;
1287 StringCopyHolder filePath;
1289 _ASSERTE(!m_vmPEFile.IsNull());
1290 if (this->GetProcess()->GetDAC()->GetMetaDataFileInfoFromPEFile(m_vmPEFile,
1296 _ASSERTE(filePath.IsSet());
1298 // Unfortunately, metadata lookup preferentially takes the ngen image - so in this case,
1299 // we need to go back and get the IL image's name instead.
1301 (this->GetProcess()->GetDAC()->GetILImageInfoFromNgenPEFile(m_vmPEFile,
1306 _ASSERTE(filePath.IsSet());
1309 hr = CopyOutString(filePath, cchName, pcchName, szName);
1318 //---------------------------------------------------------------------------------------
1319 // Gets the module pretty name (may be filename or faked up name)
1322 // cchName - count of characters in the szName buffer on input.
1323 // *pcchName - Optional Out parameter, which gets set to the fully requested size
1324 // (not just how many characters are written).
1325 // szName - buffer to get name.
1329 // S_FALSE if we fabricate the name.
1330 // Return failing HR (on common errors) or Throw on exceptional errors.
1333 // Filename isn't necessarily the same as the module name in the metadata.
1335 HRESULT CordbModule::GetNameWorker(ULONG32 cchName, ULONG32 *pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
1343 const WCHAR * szTempName = NULL;
1345 ALLOW_DATATARGET_MISSING_MEMORY(
1346 szTempName = GetModulePath();
1349 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
1350 // To support VS when debugging remotely we act like the Compact Framework and return the assembly name
1351 // when asked for the name of an in-memory module.
1352 if (szTempName == NULL)
1354 IMetaDataAssemblyImport *pAssemblyImport = NULL;
1355 if (SUCCEEDED(hr = GetMetaDataImporter()->QueryInterface(IID_IMetaDataAssemblyImport, (void**)&pAssemblyImport)))
1357 mdAssembly mda = TokenFromRid(1, mdtAssembly);
1358 hr = pAssemblyImport->GetAssemblyProps(mda, // [IN] The Assembly for which to get the properties.
1359 NULL, // [OUT] Pointer to the Originator blob.
1360 NULL, // [OUT] Count of bytes in the Originator Blob.
1361 NULL, // [OUT] Hash Algorithm.
1362 szName, // [OUT] Buffer to fill with name.
1363 cchName, // [IN] Size of buffer in wide chars.
1364 (ULONG*)pcchName, // [OUT] Actual # of wide chars in name.
1365 NULL, // [OUT] Assembly MetaData.
1366 NULL); // [OUT] Flags.
1368 pAssemblyImport->Release();
1378 #endif // FEATURE_DBGIPC_TRANSPORT_DI
1381 EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
1383 StringCopyHolder buffer;
1384 // If the module has no file name, then we'll fabricate a fake name
1387 // On MiniDumpNormal, if the debugger can't find the module then there's no way we will
1389 hr = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
1391 // Tempting to use the metadata-scope name, but that's a regression from Whidbey. For manifest modules,
1392 // the metadata scope name is not initialized with the string the user supplied to create the
1393 // dynamic assembly. So we call into the runtime to use CLR heuristics to get a more accurate name.
1394 m_pProcess->GetDAC()->GetModuleSimpleName(m_vmModule, &buffer);
1395 _ASSERTE(buffer.IsSet());
1396 szTempName = buffer;
1397 // Note that we considered returning S_FALSE for fabricated names like this, but that's a breaking
1398 // change from Whidbey that is known to trigger bugs in vS. If a debugger wants to differentiate
1399 // real path names from fake simple names, we'll just have to add a new API with the right semantics.
1402 hr = CopyOutString(szTempName, cchName, pcchName, szName);
1404 EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY
1409 //---------------------------------------------------------------------------------------
1410 // Gets actual name of loaded module. (no faked names)
1413 // string for full path to module name. This is a file that can be opened.
1414 // NULL if name is not available (such as in some dynamic module cases)
1415 // Throws if failed accessing target
1418 // We avoid using the method name "GetModuleFileName" because winbase.h #defines that
1419 // token (along with many others) to have an A or W suffix.
1420 const WCHAR * CordbModule::GetModulePath()
1422 // Lazily initialize. Module filenames cannot change, and so once
1423 // we've retrieved this successfully, it's stored for good.
1424 if (!m_strModulePath.IsSet())
1426 IDacDbiInterface * pDac = m_pProcess->GetDAC(); // throws
1427 pDac->GetModulePath(m_vmModule, &m_strModulePath); // throws
1428 _ASSERTE(m_strModulePath.IsSet());
1431 if (m_strModulePath.IsEmpty())
1433 return NULL; // module has no filename
1435 return m_strModulePath;
1438 //---------------------------------------------------------------------------------------
1439 // Get and caches ngen image path.
1442 // Null-terminated string to ngen image path.
1443 // NULL if there is no ngen filename (eg, file is not ngenned).
1444 // Throws on error (such as inability to read the path from the target).
1447 // This can be used to get the path to find metadata. For ngenned images,
1448 // the IL (and associated metadata) may not be loaded, so we may want to get the
1449 // metadata out of the ngen image.
1450 const WCHAR * CordbModule::GetNGenImagePath()
1455 // Lazily initialize. Module filenames cannot change, and so once
1456 // we've retrieved this successfully, it's stored for good.
1457 if (!m_strNGenImagePath.IsSet())
1459 IDacDbiInterface * pDac = m_pProcess->GetDAC(); // throws
1460 BOOL fNonEmpty = pDac->GetModuleNGenPath(m_vmModule, &m_strNGenImagePath); // throws
1461 (void)fNonEmpty; //prevent "unused variable" error from GCC
1462 _ASSERTE(m_strNGenImagePath.IsSet() && (m_strNGenImagePath.IsEmpty() == !fNonEmpty));
1465 EX_CATCH_HRESULT(hr);
1468 m_strNGenImagePath == NULL ||
1469 m_strNGenImagePath.IsEmpty())
1471 return NULL; // module has no ngen filename
1473 return m_strNGenImagePath;
1476 // Implementation of ICorDebugModule::EnableJITDebugging
1477 // See also code:CordbModule::SetJITCompilerFlags
1478 HRESULT CordbModule::EnableJITDebugging(BOOL bTrackJITInfo, BOOL bAllowJitOpts)
1480 // Leftside will enforce that this is a valid time to change jit flags.
1481 // V1.0 behavior allowed setting these in the middle of a module's lifetime, which meant
1482 // that different methods throughout the module may have been jitted differently.
1483 // Since V2, this has to be set when the module is first loaded, before anything is jitted.
1485 PUBLIC_API_ENTRY(this);
1486 FAIL_IF_NEUTERED(this);
1488 DWORD dwFlags = CORDEBUG_JIT_DEFAULT;
1490 // Since V2, bTrackJITInfo is the default and cannot be turned off.
1493 dwFlags |= CORDEBUG_JIT_DISABLE_OPTIMIZATION;
1495 return SetJITCompilerFlags(dwFlags);
1498 HRESULT CordbModule::EnableClassLoadCallbacks(BOOL bClassLoadCallbacks)
1500 PUBLIC_API_ENTRY(this);
1501 FAIL_IF_NEUTERED(this);
1502 ATT_ALLOW_LIVE_DO_STOPGO(GetProcess());
1504 // You must receive ClassLoad callbacks for dynamic modules so that we can keep the metadata up-to-date on the Right
1505 // Side. Therefore, we refuse to turn them off for all dynamic modules (they were forced on when the module was
1506 // loaded on the Left Side.)
1507 if (m_fDynamic && !bClassLoadCallbacks)
1508 return E_INVALIDARG;
1510 if (m_vmDomainFile.IsNull())
1511 return E_UNEXPECTED;
1513 // Send a Set Class Load Flag event to the left side. There is no need to wait for a response, and this can be
1514 // called whether or not the process is synchronized.
1515 CordbProcess *pProcess = GetProcess();
1517 DebuggerIPCEvent event;
1518 pProcess->InitIPCEvent(&event,
1519 DB_IPCE_SET_CLASS_LOAD_FLAG,
1521 (GetAppDomain()->GetADToken()));
1522 event.SetClassLoad.vmDomainFile = this->m_vmDomainFile;
1523 event.SetClassLoad.flag = (bClassLoadCallbacks == TRUE);
1525 HRESULT hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event,
1526 sizeof(DebuggerIPCEvent));
1527 hr = WORST_HR(hr, event.hr);
1531 //-----------------------------------------------------------------------------
1532 // Public implementation of ICorDebugModule::GetFunctionFromToken
1533 // Get the CordbFunction matches this token / module pair.
1534 // Each time a function is Enc-ed, it gets its own CordbFunction object.
1535 // This will return the latest EnC version of the function for this Module,Token pair.
1536 HRESULT CordbModule::GetFunctionFromToken(mdMethodDef token,
1537 ICorDebugFunction **ppFunction)
1539 // This is not reentrant. DBI should call code:CordbModule::LookupOrCreateFunctionLatestVersion instead.
1540 PUBLIC_API_ENTRY(this);
1541 ATT_ALLOW_LIVE_DO_STOPGO(GetProcess()); // @todo - can this be RequiredStop?
1544 FAIL_IF_NEUTERED(this);
1545 VALIDATE_POINTER_TO_OBJECT(ppFunction, ICorDebugFunction **);
1550 RSLockHolder lockHolder(GetProcess()->GetProcessLock());
1552 // Check token is valid.
1553 if ((token == mdMethodDefNil) ||
1554 (!GetMetaDataImporter()->IsValidToken(token)))
1556 ThrowHR(E_INVALIDARG);
1559 CordbFunction * pFunction = LookupOrCreateFunctionLatestVersion(token);
1561 *ppFunction = static_cast<ICorDebugFunction*> (pFunction);
1562 pFunction->ExternalAddRef();
1565 EX_CATCH_HRESULT(hr);
1569 HRESULT CordbModule::GetFunctionFromRVA(CORDB_ADDRESS rva,
1570 ICorDebugFunction **ppFunction)
1572 PUBLIC_API_ENTRY(this);
1573 FAIL_IF_NEUTERED(this);
1574 VALIDATE_POINTER_TO_OBJECT(ppFunction, ICorDebugFunction **);
1579 HRESULT CordbModule::LookupClassByToken(mdTypeDef token,
1580 CordbClass **ppClass)
1582 INTERNAL_API_ENTRY(this->GetProcess()); //
1583 FAIL_IF_NEUTERED(this);
1586 EX_TRY // @dbgtodo exceptions - push this up
1590 if ((token == mdTypeDefNil) || (TypeFromToken(token) != mdtTypeDef))
1592 ThrowHR(E_INVALIDARG);
1595 RSLockHolder lockHolder(GetProcess()->GetProcessLock()); // @dbgtodo synchronization - Push this up
1597 CordbClass *pClass = m_classes.GetBase(token);
1600 // Validate the token.
1601 if (!GetMetaDataImporter()->IsValidToken(token))
1603 ThrowHR(E_INVALIDARG);
1606 RSInitHolder<CordbClass> pClassInit(new CordbClass(this, token));
1607 pClass = pClassInit.TransferOwnershipToHash(&m_classes);
1613 EX_CATCH_HRESULT(hr);
1617 HRESULT CordbModule::GetClassFromToken(mdTypeDef token,
1618 ICorDebugClass **ppClass)
1620 PUBLIC_API_ENTRY(this);
1621 FAIL_IF_NEUTERED(this);
1622 ATT_ALLOW_LIVE_DO_STOPGO(this->GetProcess()); // @todo - could this be RequiredStopped?
1623 VALIDATE_POINTER_TO_OBJECT(ppClass, ICorDebugClass **);
1628 CordbClass *pClass = NULL;
1631 // Validate the token.
1632 if (!GetMetaDataImporter()->IsValidToken(token))
1634 ThrowHR(E_INVALIDARG);
1637 hr = LookupClassByToken(token, &pClass);
1640 *ppClass = static_cast<ICorDebugClass*> (pClass);
1641 pClass->ExternalAddRef();
1643 EX_CATCH_HRESULT(hr);
1647 HRESULT CordbModule::CreateBreakpoint(ICorDebugModuleBreakpoint **ppBreakpoint)
1649 PUBLIC_API_ENTRY(this);
1650 FAIL_IF_NEUTERED(this);
1651 VALIDATE_POINTER_TO_OBJECT(ppBreakpoint, ICorDebugModuleBreakpoint **);
1657 // Return the token for the Module table entry for this object. The token
1658 // may then be passed to the meta data import api's.
1660 HRESULT CordbModule::GetToken(mdModule *pToken)
1662 PUBLIC_API_ENTRY(this);
1663 FAIL_IF_NEUTERED(this);
1664 VALIDATE_POINTER_TO_OBJECT(pToken, mdModule *);
1669 hr = GetMetaDataImporter()->GetModuleFromScope(pToken);
1672 EX_CATCH_HRESULT(hr);
1677 // public implementation for ICorDebugModule::GetMetaDataInterface
1678 // Return a meta data interface pointer that can be used to examine the
1679 // meta data for this module.
1680 HRESULT CordbModule::GetMetaDataInterface(REFIID riid, IUnknown **ppObj)
1682 PUBLIC_API_ENTRY(this);
1683 FAIL_IF_NEUTERED(this);
1684 VALIDATE_POINTER_TO_OBJECT(ppObj, IUnknown **);
1689 // QI the importer that we already have and return the result.
1690 hr = GetMetaDataImporter()->QueryInterface(riid, (void**)ppObj);
1693 EX_CATCH_HRESULT(hr);
1698 //-----------------------------------------------------------------------------
1699 // LookupFunctionLatestVersion finds the latest cached version of an existing CordbFunction
1700 // in the given module. If the function doesn't exist, it returns NULL.
1703 // funcMetaDataToken - methoddef token for function to lookup
1707 // If no CordbFunction instance was cached, then this returns NULL.
1708 // use code:CordbModule::LookupOrCreateFunctionLatestVersion to do a lookup that will
1709 // populate the cache if needed.
1710 CordbFunction* CordbModule::LookupFunctionLatestVersion(mdMethodDef funcMetaDataToken)
1712 INTERNAL_API_ENTRY(this);
1713 return m_functions.GetBase(funcMetaDataToken);
1717 //-----------------------------------------------------------------------------
1718 // Lookup (or create) the CordbFunction for the latest EnC version.
1721 // funcMetaDataToken - methoddef token for function to lookup
1724 // CordbFunction instance for that token. This will create an instance if needed, and so never returns null.
1725 // Throws on critical error.
1728 // This creates the latest EnC version. Use code:CordbModule::LookupOrCreateFunction to do an
1729 // enc-version aware function lookup.
1731 CordbFunction* CordbModule::LookupOrCreateFunctionLatestVersion(mdMethodDef funcMetaDataToken)
1733 INTERNAL_API_ENTRY(this);
1734 CordbFunction * pFunction = m_functions.GetBase(funcMetaDataToken);
1735 if (pFunction != NULL)
1740 // EnC adds each version to the hash. So if the hash lookup fails, then it must not be an EnC case,
1741 // and so we can use the default version number.
1742 return CreateFunction(funcMetaDataToken, CorDB_DEFAULT_ENC_FUNCTION_VERSION);
1745 //-----------------------------------------------------------------------------
1746 // LookupOrCreateFunction finds an existing version of CordbFunction in the given module.
1747 // If the function doesn't exist, it creates it.
1749 // The outgoing function is not yet fully inititalized. For eg, the Class field is not set.
1750 // However, ICorDebugFunction::GetClass() will check that and lazily initialize the field.
1754 CordbFunction * CordbModule::LookupOrCreateFunction(mdMethodDef funcMetaDataToken, SIZE_T enCVersion)
1756 INTERNAL_API_ENTRY(this);
1758 _ASSERTE(GetProcess()->ThreadHoldsProcessLock());
1760 CordbFunction * pFunction = m_functions.GetBase(funcMetaDataToken);
1762 // special case non-existance as need to add to the hash table too
1763 if (pFunction == NULL)
1765 // EnC adds each version to the hash. So if the hash lookup fails,
1766 // then it must not be an EnC case.
1767 return CreateFunction(funcMetaDataToken, enCVersion);
1770 // linked list sorted with most recent version at front. Version numbers correspond
1771 // to actual edit count against the module, so version numbers not necessarily contiguous.
1772 // Any valid EnC version must already exist as we would have created it on the ApplyChanges
1773 for (CordbFunction *pf=pFunction; pf != NULL; pf = pf->GetPrevVersion())
1775 if (pf->GetEnCVersionNumber() == enCVersion)
1781 _ASSERTE(!"Couldn't find EnC version of function\n");
1785 HRESULT CordbModule::IsDynamic(BOOL *pDynamic)
1787 PUBLIC_API_ENTRY(this);
1788 FAIL_IF_NEUTERED(this);
1789 VALIDATE_POINTER_TO_OBJECT(pDynamic, BOOL *);
1791 (*pDynamic) = m_fDynamic;
1796 BOOL CordbModule::IsDynamic()
1802 HRESULT CordbModule::IsInMemory(BOOL *pInMemory)
1804 PUBLIC_API_ENTRY(this);
1805 FAIL_IF_NEUTERED(this);
1806 VALIDATE_POINTER_TO_OBJECT(pInMemory, BOOL *);
1808 (*pInMemory) = m_fInMemory;
1813 HRESULT CordbModule::GetGlobalVariableValue(mdFieldDef fieldDef,
1814 ICorDebugValue **ppValue)
1816 PUBLIC_API_ENTRY(this);
1817 FAIL_IF_NEUTERED(this);
1818 VALIDATE_POINTER_TO_OBJECT(ppValue, ICorDebugValue **);
1819 ATT_REQUIRE_STOPPED_MAY_FAIL(this->GetProcess());
1825 if (m_pClass == NULL)
1827 CordbClass * pGlobalClass = NULL;
1828 hr = LookupClassByToken(COR_GLOBAL_PARENT_TOKEN, &pGlobalClass);
1831 m_pClass.Assign(pGlobalClass);
1832 _ASSERTE(m_pClass != NULL);
1835 hr = m_pClass->GetStaticFieldValue(fieldDef, NULL, ppValue);
1838 EX_CATCH_HRESULT(hr);
1845 // CreateFunction creates a new function from the given information and
1846 // adds it to the module.
1848 CordbFunction * CordbModule::CreateFunction(mdMethodDef funcMetaDataToken, SIZE_T enCVersion)
1850 INTERNAL_API_ENTRY(this);
1852 // In EnC cases, the token may not yet be valid. We may be caching the CordbFunction
1853 // for a token for an added method before the metadata is updated on the RS.
1854 // We rely that our caller has done token validation.
1856 // Create a new CordbFunction object or throw.
1857 RSInitHolder<CordbFunction> pFunction(new CordbFunction(this, funcMetaDataToken, enCVersion)); // throws
1858 CordbFunction * pCopy = pFunction.TransferOwnershipToHash(&m_functions);
1862 #ifdef EnC_SUPPORTED
1863 //---------------------------------------------------------------------------------------
1865 // Creates a new CordbFunction object to represent this new version of a function and
1866 // updates the module's function collection to mark this as the latest version.
1869 // funcMetaDataToken - the functions methodDef token in this module
1870 // enCVerison - The new version number of this function
1871 // ppFunction - Output param for the new instance - optional
1874 // Assumes the specified version of this function doesn't already exist (i.e. enCVersion
1875 // is newer than all existing versions).
1877 HRESULT CordbModule::UpdateFunction(mdMethodDef funcMetaDataToken,
1879 CordbFunction** ppFunction)
1881 INTERNAL_API_ENTRY(this);
1885 _ASSERTE(funcMetaDataToken);
1887 RSLockHolder lockHolder(GetProcess()->GetProcessLock());
1889 // pOldVersion is the 2nd newest version
1890 CordbFunction* pOldVersion = LookupFunctionLatestVersion(funcMetaDataToken);
1892 // if don't have an old version, then create a default versioned one as will most likely
1893 // go looking for it later and easier to put it in now than have code to insert it later.
1896 LOG((LF_ENC, LL_INFO10000, "CM::UF: adding %8.8x with version %d\n", funcMetaDataToken, enCVersion));
1900 pOldVersion = CreateFunction(funcMetaDataToken, CorDB_DEFAULT_ENC_FUNCTION_VERSION);
1902 EX_CATCH_HRESULT(hr);
1909 // This method should not be called for versions that already exist
1910 _ASSERTE( enCVersion > pOldVersion->GetEnCVersionNumber());
1912 LOG((LF_ENC, LL_INFO10000, "CM::UF: updating %8.8x with version %d\n", funcMetaDataToken, enCVersion));
1913 // Create a new function object.
1914 CordbFunction * pNewVersion = new (nothrow) CordbFunction(this, funcMetaDataToken, enCVersion);
1916 if (pNewVersion == NULL)
1917 return E_OUTOFMEMORY;
1919 // Chain the 2nd most recent version onto this instance (this will internal addref).
1920 pNewVersion->SetPrevVersion(pOldVersion);
1922 // Add the function to the Module's hash of all functions.
1923 HRESULT hr = m_functions.SwapBase(pOldVersion, pNewVersion);
1931 // Do cleanup for function which is no longer the latest version
1932 pNewVersion->GetPrevVersion()->MakeOld();
1935 *ppFunction = pNewVersion;
1939 #endif // EnC_SUPPORTED
1942 HRESULT CordbModule::LookupOrCreateClass(mdTypeDef classMetaDataToken,CordbClass** ppClass)
1944 INTERNAL_API_ENTRY(this);
1945 FAIL_IF_NEUTERED(this);
1947 RSLockHolder lockHolder(GetProcess()->GetProcessLock()); // @dbgtodo exceptions synchronization-
1948 // Push this lock up, convert to exceptions.
1951 *ppClass = LookupClass(classMetaDataToken);
1952 if (*ppClass == NULL)
1954 hr = CreateClass(classMetaDataToken,ppClass);
1959 _ASSERTE(*ppClass != NULL);
1965 // LookupClass finds an existing CordbClass in the given module.
1966 // If the class doesn't exist, it returns NULL.
1968 CordbClass* CordbModule::LookupClass(mdTypeDef classMetaDataToken)
1970 INTERNAL_API_ENTRY(this);
1971 _ASSERTE(GetProcess()->ThreadHoldsProcessLock());
1972 return m_classes.GetBase(classMetaDataToken);
1976 // CreateClass creates a new class from the given information and
1977 // adds it to the module.
1979 HRESULT CordbModule::CreateClass(mdTypeDef classMetaDataToken,
1980 CordbClass** ppClass)
1982 INTERNAL_API_ENTRY(this);
1983 FAIL_IF_NEUTERED(this);
1985 _ASSERTE(GetProcess()->ThreadHoldsProcessLock());
1987 CordbClass* pClass = new (nothrow) CordbClass(this, classMetaDataToken);
1990 return E_OUTOFMEMORY;
1992 HRESULT hr = m_classes.AddBase(pClass);
1999 if (classMetaDataToken == COR_GLOBAL_PARENT_TOKEN)
2001 _ASSERTE( m_pClass == NULL ); //redundant create
2002 m_pClass.Assign(pClass);
2009 // Resolve a type-ref from this module to a CordbClass
2012 // token - a Type Ref in this module's scope.
2013 // ppClass - out parameter to get the class we resolve to.
2017 // CORDBG_E_CLASS_NOT_LOADED is the TypeRef is not yet resolved because the type it will refer
2018 // to is not yet loaded.
2021 // In general, a TypeRef refers to a type in another module. (Although as a corner case, it could
2022 // refer to this module too). This resolves a TypeRef within the current module's scope to a
2023 // (TypeDef, metadata scope), which is in turn encapsulated as a CordbClass.
2025 // A TypeRef has a resolution scope (ModuleRef or AssemblyRef) and string name for the type
2026 // within that scope. Resolving means:
2027 // 1. Determining the actual metadata scope loaded for the resolution scope.
2028 // See also code:CordbModule::ResolveAssemblyInternal
2029 // If the resolved module hasn't been loaded yet, the resolution will fail.
2030 // 2. Doing a string lookup of the TypeRef's name within that resolved scope to find the TypeDef.
2031 // 3. Returning the (resolved scope, TypeDef) pair.
2033 HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass)
2035 FAIL_IF_NEUTERED(this);
2036 INTERNAL_SYNC_API_ENTRY(GetProcess()); //
2038 CordbProcess * pProcess = GetProcess();
2040 _ASSERTE((pProcess->GetShim() == NULL) || pProcess->GetSynchronized());
2043 if ((token == mdTypeRefNil) || (TypeFromToken(token) != mdtTypeRef))
2045 return E_INVALIDARG;
2048 if (m_vmDomainFile.IsNull() || m_pAppDomain == NULL)
2050 return E_UNEXPECTED;
2057 TypeRefData inData = {m_vmDomainFile, token};
2058 TypeRefData outData;
2061 RSLockHolder lockHolder(pProcess->GetProcessLock());
2062 pProcess->GetDAC()->ResolveTypeReference(&inData, &outData);
2065 CordbModule * pModule = m_pAppDomain->LookupOrCreateModule(outData.vmDomainFile);
2066 IfFailThrow(pModule->LookupClassByToken(outData.typeToken, ppClass));
2068 EX_CATCH_HRESULT(hr);
2072 } // CordbModule::ResolveTypeRef
2074 // Resolve a type ref or def to a CordbClass
2077 // token - a mdTypeDef or mdTypeRef in this module's scope to be resolved
2078 // ppClass - out parameter to get the CordbClass for this type
2081 // See code:CordbModule::ResolveTypeRef for more details.
2082 HRESULT CordbModule::ResolveTypeRefOrDef(mdToken token, CordbClass **ppClass)
2084 FAIL_IF_NEUTERED(this);
2085 INTERNAL_SYNC_API_ENTRY(this->GetProcess()); //
2087 if ((token == mdTypeRefNil) ||
2088 (TypeFromToken(token) != mdtTypeRef && TypeFromToken(token) != mdtTypeDef))
2089 return E_INVALIDARG;
2091 if (TypeFromToken(token)==mdtTypeRef)
2093 // It's a type-ref. That means the type is defined in another module.
2094 // That other module is determined at runtime by Fusion / Loader policy. So we need to
2095 // ultimately ask the runtime which module was actually loaded.
2096 return ( ResolveTypeRef(token, ppClass) );
2100 // It's a type-def. This is the easy case because the type is defined in this same module.
2101 return ( LookupClassByToken(token, ppClass) );
2107 // GetSize returns the size of the module.
2109 HRESULT CordbModule::GetSize(ULONG32 *pcBytes)
2111 PUBLIC_API_ENTRY(this);
2112 FAIL_IF_NEUTERED(this);
2113 VALIDATE_POINTER_TO_OBJECT(pcBytes, ULONG32 *);
2115 *pcBytes = m_PEBuffer.cbSize;
2120 CordbAssembly *CordbModule::GetCordbAssembly()
2122 INTERNAL_API_ENTRY(this);
2127 // This is legacy from the aborted V1 EnC attempt - not used in V2 EnC support
2128 HRESULT CordbModule::GetEditAndContinueSnapshot(
2129 ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot)
2135 //---------------------------------------------------------------------------------------
2137 // Requests that an edit be applied to the module for edit and continue and updates
2138 // the right-side state and metadata.
2141 // cbMetaData - number of bytes in pbMetaData
2142 // pbMetaData - a delta metadata blob describing the metadata edits to be made
2143 // cbIL - number of bytes in pbIL
2144 // pbIL - a new method body stream containing all of the method body information
2145 // (IL, EH info, etc) for edited and added methods.
2148 // S_OK on success, various errors on failure
2153 // This applies the same changes to the RS's copy of the metadata that the left-side will apply to
2154 // it's copy of the metadata. see code:EditAndContinueModule::ApplyEditAndContinue
2156 HRESULT CordbModule::ApplyChanges(ULONG cbMetaData,
2161 PUBLIC_API_ENTRY(this);
2162 FAIL_IF_NEUTERED(this);
2163 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2165 #ifdef EnC_SUPPORTED
2166 // We enable EnC back in code:CordbModule::SetJITCompilerFlags.
2167 // If EnC isn't enabled, then we'll fail in the LS when we try to ApplyChanges.
2168 // We'd expect a well-behaved debugger to never actually land here.
2171 LOG((LF_CORDB,LL_INFO10000, "CP::AC: applying changes"));
2173 VALIDATE_POINTER_TO_OBJECT_ARRAY(pbMetaData,
2178 VALIDATE_POINTER_TO_OBJECT_ARRAY(pbIL,
2185 RSExtSmartPtr<IUnknown> pUnk;
2186 RSExtSmartPtr<IMDInternalImport> pMDImport;
2187 RSExtSmartPtr<IMDInternalImport> pMDImport2;
2190 // Edit was successful - update the right-side state to reflect the edit
2195 // apply the changes to our copy of the metadata
2197 _ASSERTE(m_pIMImport != NULL); // must have metadata at this point in EnC
2198 IfFailGo(m_pIMImport->QueryInterface(IID_IUnknown, (void**)&pUnk));
2200 IfFailGo(GetMDInternalInterfaceFromPublic(pUnk, IID_IMDInternalImport,
2201 (void **)&pMDImport));
2203 // The left-side will call this same method on its copy of the metadata.
2204 hr = pMDImport->ApplyEditAndContinue(pbMetaData, cbMetaData, &pMDImport2);
2205 if (pMDImport2 != NULL)
2207 // ApplyEditAndContinue() expects IMDInternalImport**, but we give it RSExtSmartPtr<IMDInternalImport>
2208 // Silent cast of RSExtSmartPtr to IMDInternalImport* leads to assignment of a raw pointer
2209 // without calling AddRef(), thus we need to do it manually.
2211 // @todo - ApplyEditAndContinue should probably AddRef the out parameter.
2212 pMDImport2->AddRef();
2217 // We're about to get a new importer object, so release the old one.
2218 m_pIMImport.Clear();
2219 IfFailGo(GetMDPublicInterfaceFromInternal(pMDImport2, IID_IMetaDataImport, (void **)&m_pIMImport));
2220 // set the new RVA value
2222 // Send the delta over to the debugee and request that it apply the edit
2223 IfFailGo( ApplyChangesInternal(cbMetaData, pbMetaData, cbIL, pbIL) );
2228 m_pInternalMetaDataImport.Clear();
2229 UpdateInternalMetaData();
2231 EX_CATCH_HRESULT(hr);
2232 _ASSERTE(SUCCEEDED(hr));
2235 // MetaData interface pointers will be automatically released via SmartPtr dtors.
2237 // @todo : prevent further execution of program
2247 //---------------------------------------------------------------------------------------
2249 // Requests that an edit be applied to the module for edit and continue and updates
2250 // some right-side state, but does not update our copy of the metadata.
2253 // cbMetaData - number of bytes in pbMetaData
2254 // pbMetaData - a delta metadata blob describing the metadata edits to be made
2255 // cbIL - number of bytes in pbIL
2256 // pbIL - a new method body stream containing all of the method body information
2257 // (IL, EH info, etc) for edited and added methods.
2260 // S_OK on success, various errors on failure
2262 HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData,
2273 LOG((LF_ENC,LL_INFO100, "CordbProcess::ApplyChangesInternal\n"));
2275 FAIL_IF_NEUTERED(this);
2276 INTERNAL_SYNC_API_ENTRY(this->GetProcess()); //
2278 if (m_vmDomainFile.IsNull())
2279 return E_UNEXPECTED;
2281 #ifdef EnC_SUPPORTED
2284 void * pRemoteBuf = NULL;
2289 // Create and initialize the event as synchronous
2290 // We'll be sending a NULL appdomain pointer since the individual modules
2291 // will contains pointers to their respective A.D.s
2292 DebuggerIPCEvent event;
2293 GetProcess()->InitIPCEvent(&event, DB_IPCE_APPLY_CHANGES, false, VMPTR_AppDomain::NullPtr());
2295 event.ApplyChanges.vmDomainFile = this->m_vmDomainFile;
2297 // Have the left-side create a buffer for us to store the delta into
2298 ULONG cbSize = cbMetaData+cbIL;
2299 TargetBuffer tbFull = GetProcess()->GetRemoteBuffer(cbSize);
2300 pRemoteBuf = CORDB_ADDRESS_TO_PTR(tbFull.pAddress);
2302 TargetBuffer tbMetaData = tbFull.SubBuffer(0, cbMetaData); // 1st half
2303 TargetBuffer tbIL = tbFull.SubBuffer(cbMetaData); // 2nd half
2305 // Copy the delta metadata over to the debugee
2307 GetProcess()->SafeWriteBuffer(tbMetaData, pbMetaData); // throws
2308 GetProcess()->SafeWriteBuffer(tbIL, pbIL); // throws
2310 // Send a synchronous event requesting the debugee apply the edit
2311 event.ApplyChanges.pDeltaMetadata = tbMetaData.pAddress;
2312 event.ApplyChanges.cbDeltaMetadata = tbMetaData.cbSize;
2313 event.ApplyChanges.pDeltaIL = tbIL.pAddress;
2314 event.ApplyChanges.cbDeltaIL = tbIL.cbSize;
2316 LOG((LF_ENC,LL_INFO100, "CordbProcess::ApplyChangesInternal sending event\n"));
2317 hr = GetProcess()->SendIPCEvent(&event, sizeof(event));
2318 hr = WORST_HR(hr, event.hr);
2321 // Allocate space for the return event.
2322 // We always copy over the whole buffer size which is bigger than sizeof(DebuggerIPCEvent)
2323 // This seems ugly, in this case we know the exact size of the event we want to read
2324 // why copy over all the extra data?
2325 DebuggerIPCEvent *retEvent = (DebuggerIPCEvent *) _alloca(CorDBIPC_BUFFER_SIZE);
2329 // Wait for events to return from the RC. We expect zero or more add field,
2330 // add function or update function events and one completion event.
2334 hr = GetProcess()->m_cordb->WaitForIPCEventFromProcess(GetProcess(),
2339 if (retEvent->type == DB_IPCE_APPLY_CHANGES_RESULT)
2341 // Done receiving update events
2342 hr = retEvent->ApplyChangesResult.hr;
2343 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: EnC apply changes result %8.8x.\n", hr));
2347 _ASSERTE(retEvent->type == DB_IPCE_ENC_UPDATE_FUNCTION ||
2348 retEvent->type == DB_IPCE_ENC_ADD_FUNCTION ||
2349 retEvent->type == DB_IPCE_ENC_ADD_FIELD);
2350 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: EnC %s %8.8x to version %d.\n",
2351 GetCurrentThreadId(),
2352 retEvent->type == DB_IPCE_ENC_UPDATE_FUNCTION ? "Update function" :
2353 retEvent->type == DB_IPCE_ENC_ADD_FUNCTION ? "Add function" : "Add field",
2354 retEvent->EnCUpdate.memberMetadataToken, retEvent->EnCUpdate.newVersionNumber));
2356 CordbAppDomain *pAppDomain = GetAppDomain();
2357 _ASSERTE(NULL != pAppDomain);
2358 CordbModule* pModule = NULL;
2361 pModule = pAppDomain->LookupOrCreateModule(retEvent->EnCUpdate.vmDomainFile); // throws
2362 _ASSERTE(pModule != NULL);
2364 // update to the newest version
2366 if (retEvent->type == DB_IPCE_ENC_UPDATE_FUNCTION ||
2367 retEvent->type == DB_IPCE_ENC_ADD_FUNCTION)
2369 // Update the function collection to reflect this edit
2370 hr = pModule->UpdateFunction(retEvent->EnCUpdate.memberMetadataToken, retEvent->EnCUpdate.newVersionNumber, NULL);
2373 // mark the class and relevant type as old so we update it next time we try to query it
2374 if (retEvent->type == DB_IPCE_ENC_ADD_FUNCTION ||
2375 retEvent->type == DB_IPCE_ENC_ADD_FIELD)
2377 RSLockHolder lockHolder(GetProcess()->GetProcessLock()); // @dbgtodo synchronization - push this up
2378 CordbClass* pClass = pModule->LookupClass(retEvent->EnCUpdate.classMetadataToken);
2379 // if don't find class, that is fine because it hasn't been loaded yet so doesn't
2380 // need to be updated
2389 LOG((LF_ENC,LL_INFO100, "CordbProcess::ApplyChangesInternal complete.\n"));
2391 EX_CATCH_HRESULT(hr);
2393 // process may have gone away by the time we get here so don't assume is there.
2394 CordbProcess *pProcess = GetProcess();
2397 HRESULT hr2 = pProcess->ReleaseRemoteBuffer(&pRemoteBuf);
2398 TESTANDRETURNHR(hr2);
2401 #else // EnC_SUPPORTED
2403 #endif // EnC_SUPPORTED
2407 // Set the JMC status for the entire module.
2408 // All methods specified in others[] will have jmc status !fIsUserCode
2409 // All other methods will have jmc status fIsUserCode.
2410 HRESULT CordbModule::SetJMCStatus(
2415 PUBLIC_API_ENTRY(this);
2416 FAIL_IF_NEUTERED(this);
2417 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
2419 if (m_vmDomainFile.IsNull())
2420 return E_UNEXPECTED;
2422 // @todo -allow the other parameters. These are functions that have default status
2423 // opposite of fIsUserCode.
2426 _ASSERTE(!"not yet impl for cOthers != 0");
2430 // Send event to the LS.
2431 CordbProcess* pProcess = this->GetProcess();
2432 _ASSERTE(pProcess != NULL);
2435 // Tell the LS that this module is/is not user code
2436 DebuggerIPCEvent event;
2437 pProcess->InitIPCEvent(&event, DB_IPCE_SET_MODULE_JMC_STATUS, true, this->GetAppDomain()->GetADToken());
2438 event.SetJMCFunctionStatus.vmDomainFile = m_vmDomainFile;
2439 event.SetJMCFunctionStatus.dwStatus = fIsUserCode;
2442 // Note: two-way event here...
2443 HRESULT hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event, sizeof(DebuggerIPCEvent));
2445 // Stop now if we can't even send the event.
2448 LOG((LF_CORDB, LL_INFO10, "CordbModule::SetJMCStatus failed 0x%08x...\n", hr));
2453 _ASSERTE(event.type == DB_IPCE_SET_MODULE_JMC_STATUS_RESULT);
2455 LOG((LF_CORDB, LL_INFO10, "returning from CordbModule::SetJMCStatus 0x%08x...\n", hr));
2462 // Resolve an assembly given an AssemblyRef token. Note that
2463 // this will not trigger the loading of assembly. If assembly is not yet loaded,
2464 // this will return an CORDBG_E_CANNOT_RESOLVE_ASSEMBLY error
2466 HRESULT CordbModule::ResolveAssembly(mdToken tkAssemblyRef,
2467 ICorDebugAssembly **ppAssembly)
2469 PUBLIC_API_ENTRY(this);
2470 FAIL_IF_NEUTERED(this);
2471 ATT_REQUIRE_STOPPED_MAY_FAIL(this->GetProcess());
2481 CordbAssembly *pCordbAsm = ResolveAssemblyInternal(tkAssemblyRef);
2482 if (pCordbAsm == NULL)
2484 // Don't throw here. It's a common-case failure path and not exceptional.
2485 hr = CORDBG_E_CANNOT_RESOLVE_ASSEMBLY;
2489 _ASSERTE(pCordbAsm != NULL);
2490 *ppAssembly = pCordbAsm;
2491 pCordbAsm->ExternalAddRef();
2494 EX_CATCH_HRESULT(hr);
2498 //---------------------------------------------------------------------------------------
2499 // Worker to resolve an assembly ref.
2502 // tkAssemblyRef - token of assembly ref to resolve
2505 // Assembly that this token resolves to.
2506 // NULL if it's a valid token but the assembly has not yet been resolved.
2507 // (This is a non-exceptional error case).
2510 // MetaData has tokens to represent a reference to another assembly.
2511 // But Loader/Fusion policy ultimately decides which specific assembly is actually loaded
2513 // This does the lookup of actual assembly and reports back to the debugger.
2515 CordbAssembly * CordbModule::ResolveAssemblyInternal(mdToken tkAssemblyRef)
2517 INTERNAL_SYNC_API_ENTRY(GetProcess()); //
2519 if (TypeFromToken(tkAssemblyRef) != mdtAssemblyRef || tkAssemblyRef == mdAssemblyRefNil)
2521 // Not a valid token
2522 ThrowHR(E_INVALIDARG);
2525 CordbAssembly * pAssembly = NULL;
2527 if (!m_vmDomainFile.IsNull())
2529 // Get DAC to do the real work to resolve the assembly
2530 VMPTR_DomainAssembly vmDomainAssembly = GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainFile, tkAssemblyRef);
2532 // now find the ICorDebugAssembly corresponding to it
2533 if (!vmDomainAssembly.IsNull() && m_pAppDomain != NULL)
2535 RSLockHolder lockHolder(GetProcess()->GetProcessLock());
2536 // Don't throw here because if the lookup fails, we want to throw CORDBG_E_CANNOT_RESOLVE_ASSEMBLY.
2537 pAssembly = m_pAppDomain->LookupOrCreateAssembly(vmDomainAssembly);
2545 // CreateReaderForInMemorySymbols - create an ISymUnmanagedReader object for symbols
2546 // which are loaded into memory in the CLR. See interface definition in cordebug.idl for
2549 HRESULT CordbModule::CreateReaderForInMemorySymbols(REFIID riid, void** ppObj)
2551 PUBLIC_API_ENTRY(this);
2552 FAIL_IF_NEUTERED(this);
2554 CordbProcess *pProcess = GetProcess();
2555 ATT_REQUIRE_STOPPED_MAY_FAIL(pProcess);
2560 // Get the symbol memory in a stream to give to the reader.
2561 ReleaseHolder<IStream> pStream;
2562 IDacDbiInterface::SymbolFormat symFormat = GetInMemorySymbolStream(&pStream);
2564 // First create the symbol binder corresponding to the format of the stream
2565 ReleaseHolder<ISymUnmanagedBinder> pBinder;
2566 if (symFormat == IDacDbiInterface::kSymbolFormatPDB)
2569 // PDB format - use diasymreader.dll with COM activation
2570 InlineSString<_MAX_PATH> ssBuf;
2571 IfFailThrow(GetHModuleDirectory(GetModuleInst(), ssBuf));
2572 IfFailThrow(FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS,
2574 IID_ISymUnmanagedBinder,
2578 IfFailThrow(FakeCoCreateInstance(CLSID_CorSymBinder_SxS,
2579 IID_ISymUnmanagedBinder,
2583 else if (symFormat == IDacDbiInterface::kSymbolFormatILDB)
2585 // ILDB format - use statically linked-in ildbsymlib
2586 IfFailThrow(IldbSymbolsCreateInstance(CLSID_CorSymBinder_SxS,
2587 IID_ISymUnmanagedBinder,
2592 // No in-memory symbols, return the appropriate error
2593 _ASSERTE(symFormat == IDacDbiInterface::kSymbolFormatNone);
2594 if (m_fDynamic || m_fInMemory)
2596 // This is indeed an in-memory or dynamic module, we just don't have any symbols for it.
2597 // This means the application didn't supply any, or they are not yet available. Symbols
2598 // first become available at LoadClass time for dynamic modules and UpdateModuleSymbols
2599 // time for non-dynamic in-memory modules.
2600 ThrowHR(CORDBG_E_SYMBOLS_NOT_AVAILABLE);
2603 // This module is on disk - the debugger should use it's normal symbol-loading logic.
2604 ThrowHR(CORDBG_E_MODULE_LOADED_FROM_DISK);
2607 // In the attach or dump case, if we attach or take the dump after we have defined a dynamic module, we may
2608 // have already set the symbol format to "PDB" by the time we call CreateReaderForInMemorySymbols during initialization
2609 // for loaded modules. (In the launch case, we do this initialization when the module is actually loaded, and before we
2610 // set the symbol format.) When we call CreateReaderForInMemorySymbols, we can't assume the initialization was already
2611 // performed or specifically, that we already have m_pIMImport initialized. We can't call into diasymreader with a NULL
2612 // pointer as the value for m_pIMImport, so we need to check that here.
2613 if (m_pIMImport == NULL)
2615 ThrowHR(CORDBG_E_SYMBOLS_NOT_AVAILABLE);
2618 // Now create the symbol reader from the data
2619 ReleaseHolder<ISymUnmanagedReader> pReader;
2620 IfFailThrow(pBinder->GetReaderFromStream(m_pIMImport, pStream, &pReader));
2622 // Attempt to return the interface requested
2623 // Note that this does an AddRef for our return value ppObj, so we don't suppress the release
2624 // of the pReader holder.
2625 IfFailThrow(pReader->QueryInterface(riid, ppObj));
2627 EX_CATCH_HRESULT(hr);
2631 /* ------------------------------------------------------------------------- *
2633 * ------------------------------------------------------------------------- */
2635 //---------------------------------------------------------------------------------------
2636 // Set the continue counter that marks when the module is in its Load event
2639 // Jit flags can only be changed in the real module Load event. We may
2640 // have multiple module load events on different threads coming at the
2641 // same time. So each module load tracks its continue counter.
2643 // This can be used by code:CordbModule::EnsureModuleIsInLoadCallback to
2644 // properly return CORDBG_E_MUST_BE_IN_LOAD_MODULE
2645 void CordbModule::SetLoadEventContinueMarker()
2647 // Well behaved targets should only set this once.
2648 GetProcess()->TargetConsistencyCheck(m_nLoadEventContinueCounter == 0);
2650 m_nLoadEventContinueCounter = GetProcess()->m_continueCounter;
2653 //---------------------------------------------------------------------------------------
2654 // Return CORDBG_E_MUST_BE_IN_LOAD_MODULE if the module is not in the load module callback.
2657 // The comparison is done via continue counters. The counter of the load
2658 // event is cached via code:CordbModule::SetLoadEventContinueMarker.
2660 // This state is currently stored on the RS. Alternatively, it could likely be retreived from the LS state as
2661 // well. One disadvantage of the current model is that if we detach during the load-module callback and
2662 // then reattach, the RS state is flushed and we lose the fact that we can toggle the jit flags.
2663 HRESULT CordbModule::EnsureModuleIsInLoadCallback()
2665 if (this->m_nLoadEventContinueCounter < GetProcess()->m_continueCounter)
2667 return CORDBG_E_MUST_BE_IN_LOAD_MODULE;
2675 // Implementation of ICorDebugModule2::SetJITCompilerFlags
2676 // See also code:CordbModule::EnableJITDebugging
2677 HRESULT CordbModule::SetJITCompilerFlags(DWORD dwFlags)
2679 PUBLIC_REENTRANT_API_ENTRY(this);
2680 FAIL_IF_NEUTERED(this);
2682 CordbProcess *pProcess = GetProcess();
2684 ATT_REQUIRE_STOPPED_MAY_FAIL(pProcess);
2689 // can't have a subset of these, eg 0x101, so make sure we have an exact match
2690 if ((dwFlags != CORDEBUG_JIT_DEFAULT) &&
2691 (dwFlags != CORDEBUG_JIT_DISABLE_OPTIMIZATION) &&
2692 (dwFlags != CORDEBUG_JIT_ENABLE_ENC))
2698 BOOL fAllowJitOpts = ((dwFlags & CORDEBUG_JIT_DISABLE_OPTIMIZATION) != CORDEBUG_JIT_DISABLE_OPTIMIZATION);
2699 BOOL fEnableEnC = ((dwFlags & CORDEBUG_JIT_ENABLE_ENC) == CORDEBUG_JIT_ENABLE_ENC);
2701 // Can only change jit flags when module is first loaded and before there's any jitted code.
2702 // This ensures all code in the module is jitted the same way.
2703 hr = EnsureModuleIsInLoadCallback();
2707 // DD interface will check if it's a valid time to change the flags.
2708 hr = pProcess->GetDAC()->SetCompilerFlags(GetRuntimeDomainFile(), fAllowJitOpts, fEnableEnC);
2712 EX_CATCH_HRESULT(hr);
2714 // emulate v2 hresults
2715 if (GetProcess()->GetShim() != NULL)
2717 // Emulate Whidbey error hresults
2718 hr = GetProcess()->GetShim()->FilterSetJitFlagsHresult(hr);
2724 // Implementation of ICorDebugModule2::GetJitCompilerFlags
2725 HRESULT CordbModule::GetJITCompilerFlags(DWORD *pdwFlags )
2727 PUBLIC_REENTRANT_API_ENTRY(this);
2728 FAIL_IF_NEUTERED(this);
2729 VALIDATE_POINTER_TO_OBJECT(pdwFlags, DWORD*);
2730 *pdwFlags = CORDEBUG_JIT_DEFAULT;;
2732 CordbProcess *pProcess = GetProcess();
2735 ATT_REQUIRE_STOPPED_MAY_FAIL(pProcess);
2743 pProcess->GetDAC()->GetCompilerFlags (
2744 GetRuntimeDomainFile(),
2750 *pdwFlags = CORDEBUG_JIT_ENABLE_ENC;
2752 else if (! fAllowJitOpts)
2754 *pdwFlags = CORDEBUG_JIT_DISABLE_OPTIMIZATION;
2758 EX_CATCH_HRESULT(hr);
2762 BOOL CordbModule::IsWinMD()
2770 if (m_isIlWinMD == Uninitialized)
2773 HRESULT hr = E_FAIL;
2776 RSLockHolder processLockHolder(GetProcess()->GetProcessLock());
2777 hr = GetProcess()->GetDAC()->IsWinRTModule(m_vmModule, isWinRT);
2780 _ASSERTE(SUCCEEDED(hr));
2787 m_isIlWinMD = False;
2790 return m_isIlWinMD == True;
2793 /* ------------------------------------------------------------------------- *
2795 * ------------------------------------------------------------------------- */
2796 //-----------------------------------------------------------------------------
2797 // CordbCode constructor
2800 // pFunction - CordbFunction instance for this function
2801 // encVersion - Edit and Continue version number for this code chunk
2802 // fIsIL - indicates whether the instance is a CordbILCode (as
2803 // opposed to a CordbNativeCode)
2804 // id - This is the hashtable key for CordbCode objects
2805 // - for native code, the code start address
2807 // - for ReJit IL code, the remote pointer to the ReJitSharedInfo
2809 // fields of the CordbCode instance have been initialized
2810 //-----------------------------------------------------------------------------
2812 CordbCode::CordbCode(CordbFunction * pFunction, UINT_PTR id, SIZE_T encVersion, BOOL fIsIL)
2813 : CordbBase(pFunction->GetProcess(), id, enumCordbCode),
2815 m_nVersion(encVersion),
2817 m_continueCounterLastSync(0),
2818 m_pFunction(pFunction)
2820 _ASSERTE(pFunction != NULL);
2821 _ASSERTE(m_nVersion >= CorDB_DEFAULT_ENC_FUNCTION_VERSION);
2822 } // CordbCode::CordbCode
2824 //-----------------------------------------------------------------------------
2825 // Destructor for CordbCode object
2826 //-----------------------------------------------------------------------------
2827 CordbCode::~CordbCode()
2829 _ASSERTE(IsNeutered());
2832 //-----------------------------------------------------------------------------
2833 // Neutered by CordbFunction
2834 // See CordbBase::Neuter for neuter semantics.
2835 //-----------------------------------------------------------------------------
2836 void CordbCode::Neuter()
2840 delete [] m_rgbCode;
2843 CordbBase::Neuter();
2846 //-----------------------------------------------------------------------------
2847 // Public method for IUnknown::QueryInterface.
2848 // Has standard QI semantics.
2849 //-----------------------------------------------------------------------------
2850 HRESULT CordbCode::QueryInterface(REFIID id, void ** pInterface)
2852 if (id == IID_ICorDebugCode)
2854 *pInterface = static_cast<ICorDebugCode*>(this);
2856 else if (id == IID_IUnknown)
2858 *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugCode *>(this));
2863 return E_NOINTERFACE;
2870 //-----------------------------------------------------------------------------
2871 // NOT IMPLEMENTED. Remap sequence points are entirely private to the LS,
2872 // and ICorDebug will dispatch a RemapOpportunity callback to notify the
2873 // debugger instead of letting the debugger query for the points.
2875 // Returns: E_NOTIMPL
2876 //-----------------------------------------------------------------------------
2877 HRESULT CordbCode::GetEnCRemapSequencePoints(ULONG32 cMap, ULONG32 * pcMap, ULONG32 offsets[])
2879 FAIL_IF_NEUTERED(this);
2880 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pcMap, ULONG32*);
2881 VALIDATE_POINTER_TO_OBJECT_ARRAY_OR_NULL(offsets, ULONG32*, cMap, true, true);
2884 // Old EnC interface - deprecated
2887 } // CordbCode::GetEnCRemapSequencePoints
2890 //-----------------------------------------------------------------------------
2892 // Public method to determine if this Code object represents IL or native code.
2895 // pbIL - OUT: on return, set to True if IL code, else False.
2899 //-----------------------------------------------------------------------------
2900 HRESULT CordbCode::IsIL(BOOL *pbIL)
2902 PUBLIC_API_ENTRY(this);
2903 FAIL_IF_NEUTERED(this);
2904 VALIDATE_POINTER_TO_OBJECT(pbIL, BOOL *);
2911 //-----------------------------------------------------------------------------
2912 // CordbCode::GetFunction
2913 // Public method to get the Function object associated with this Code object.
2914 // Function:Code = 1:1 for IL, and 1:n for Native. So there is always a single
2915 // unique Function object to return.
2918 // ppFunction - OUT: returns the Function object for this Code.
2921 // S_OK - on success.
2922 //-----------------------------------------------------------------------------
2923 HRESULT CordbCode::GetFunction(ICorDebugFunction **ppFunction)
2925 PUBLIC_API_ENTRY(this);
2926 FAIL_IF_NEUTERED(this);
2927 VALIDATE_POINTER_TO_OBJECT(ppFunction, ICorDebugFunction **);
2929 *ppFunction = static_cast<ICorDebugFunction*> (m_pFunction);
2930 m_pFunction->ExternalAddRef();
2935 //-----------------------------------------------------------------------------
2936 // CordbCode::GetSize
2937 // Get the size of the code in bytes. If this is IL code, it will be bytes of IL.
2938 // If this is native code, it will be bytes of native code.
2941 // pcBytes - OUT: on return, set to the size of the code in bytes.
2945 //-----------------------------------------------------------------------------
2946 HRESULT CordbCode::GetSize(ULONG32 *pcBytes)
2948 PUBLIC_REENTRANT_API_ENTRY(this);
2949 FAIL_IF_NEUTERED(this);
2950 VALIDATE_POINTER_TO_OBJECT(pcBytes, ULONG32 *);
2952 *pcBytes = GetSize();
2956 //-----------------------------------------------------------------------------
2957 // CordbCode::CreateBreakpoint
2958 // public method to create a breakpoint in the code.
2961 // offset - offset in bytes to set the breakpoint at. If this is a Native
2962 // code object (IsIl == false), then units are bytes of native code. If
2963 // this is an IL code object, then units are bytes of IL code.
2964 // ppBreakpoint- out-parameter to hold newly created breakpoint object.
2967 // S_OK iff *ppBreakpoint is set. Else some error.
2968 //-----------------------------------------------------------------------------
2969 HRESULT CordbCode::CreateBreakpoint(ULONG32 offset,
2970 ICorDebugFunctionBreakpoint **ppBreakpoint)
2972 PUBLIC_REENTRANT_API_ENTRY(this);
2973 FAIL_IF_NEUTERED(this);
2974 VALIDATE_POINTER_TO_OBJECT(ppBreakpoint, ICorDebugFunctionBreakpoint **);
2977 ULONG32 size = GetSize();
2978 LOG((LF_CORDB, LL_INFO10000, "CCode::CreateBreakpoint, offset=%d, size=%d, IsIl=%d, this=0x%p\n",
2979 offset, size, m_fIsIL, this));
2981 // Make sure the offset is within range of the method.
2982 // If we're native code, then both offset & total code size are bytes of native code,
2983 // else they're both bytes of IL.
2986 return CORDBG_E_UNABLE_TO_SET_BREAKPOINT;
2989 CordbFunctionBreakpoint *bp = new (nothrow) CordbFunctionBreakpoint(this, offset);
2992 return E_OUTOFMEMORY;
2994 hr = bp->Activate(TRUE);
2997 *ppBreakpoint = static_cast<ICorDebugFunctionBreakpoint*> (bp);
2998 bp->ExternalAddRef();
3008 //-----------------------------------------------------------------------------
3009 // CordbCode::GetCode
3010 // Public method to get the code-bytes for this Code object. For an IL-code
3011 // object, this will be bytes of IL. For a native-code object, this will be
3012 // bytes of native opcodes.
3013 // The units of the offsets are the same as the units on the CordbCode object.
3014 // (eg, IL offsets for an IL code object, and native offsets for a native code object)
3015 // This will glue together hot + cold regions into a single blob.
3017 // Units are also logical (aka linear) values, which
3019 // startOffset - linear offset in Code to start copying from.
3020 // endOffset - linear offset in Code to end copying from. Total bytes copied would be (endOffset - startOffset)
3021 // cBufferAlloc - number of bytes in the buffer supplied by the buffer[] parameter.
3022 // buffer - caller allocated storage to copy bytes into.
3023 // pcBufferSize - required out-parameter, holds number of bytes copied into buffer.
3026 // S_OK if copy successful. Else error.
3027 //-----------------------------------------------------------------------------
3028 HRESULT CordbCode::GetCode(ULONG32 startOffset,
3030 ULONG32 cBufferAlloc,
3032 ULONG32 *pcBufferSize)
3034 PUBLIC_REENTRANT_API_ENTRY(this);
3035 FAIL_IF_NEUTERED(this);
3036 VALIDATE_POINTER_TO_OBJECT_ARRAY(buffer, BYTE, cBufferAlloc, true, true);
3037 VALIDATE_POINTER_TO_OBJECT(pcBufferSize, ULONG32 *);
3039 LOG((LF_CORDB,LL_EVERYTHING, "CC::GC: for token:0x%x\n", m_pFunction->GetMetadataToken()));
3041 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
3047 ULONG32 totalSize = GetSize();
3049 if (cBufferAlloc < endOffset - startOffset)
3050 endOffset = startOffset + cBufferAlloc;
3052 if (endOffset > totalSize)
3053 endOffset = totalSize;
3055 if (startOffset > totalSize)
3056 startOffset = totalSize;
3058 // Check the continue counter since WriteMemory bumps it up.
3059 if ((m_rgbCode == NULL) ||
3060 (m_continueCounterLastSync < GetProcess()->m_continueCounter))
3063 m_continueCounterLastSync = GetProcess()->m_continueCounter;
3066 // if we just got the code, we'll have to copy it over
3067 if (*pcBufferSize == 0 && m_rgbCode != NULL)
3070 m_rgbCode+startOffset,
3071 endOffset - startOffset);
3072 *pcBufferSize = endOffset - startOffset;
3076 } // CordbCode::GetCode
3078 #include "dbgipcevents.h"
3080 //-----------------------------------------------------------------------------
3081 // CordbCode::GetVersionNumber
3082 // Public method to get the EnC version number of the code.
3085 // nVersion - OUT: on return, set to the version number.
3089 //-----------------------------------------------------------------------------
3090 HRESULT CordbCode::GetVersionNumber( ULONG32 *nVersion)
3092 PUBLIC_API_ENTRY(this);
3093 FAIL_IF_NEUTERED(this);
3094 VALIDATE_POINTER_TO_OBJECT(nVersion, ULONG32 *);
3096 LOG((LF_CORDB,LL_INFO10000,"R:CC:GVN:Returning 0x%x "
3097 "as version\n",m_nVersion));
3099 *nVersion = (ULONG32)m_nVersion;
3101 #ifndef EnC_SUPPORTED
3102 _ASSERTE(*nVersion == 1);
3103 #endif // EnC_SUPPORTED
3108 // get the CordbFunction instance for this code object
3109 CordbFunction * CordbCode::GetFunction()
3111 _ASSERTE(m_pFunction != NULL);
3115 /* ------------------------------------------------------------------------- *
3117 * ------------------------------------------------------------------------- */
3119 //-----------------------------------------------------------------------------
3120 // CordbILCode ctor to make IL code.
3123 // pFunction - pointer to the CordbFunction instance for this function
3124 // codeRegionInfo - starting address and size in bytes of IL code blob
3125 // nVersion - EnC version number for this IL code blob
3126 // localVarSigToken - LocalVarSig for this IL blob
3127 // id - the key when using ILCode in a CordbHashTable
3129 // fields of this instance of CordbILCode have been initialized
3130 //-----------------------------------------------------------------------------
3131 CordbILCode::CordbILCode(CordbFunction * pFunction,
3132 TargetBuffer codeRegionInfo,
3134 mdSignature localVarSigToken,
3136 : CordbCode(pFunction, id, nVersion, TRUE),
3137 #ifdef EnC_SUPPORTED
3140 m_codeRegionInfo(codeRegionInfo),
3141 m_localVarSigToken(localVarSigToken)
3143 } // CordbILCode::CordbILCode
3146 #ifdef EnC_SUPPORTED
3147 //-----------------------------------------------------------------------------
3148 // CordbILCode::MakeOld
3149 // Internal method to perform any cleanup necessary when a code blob is no longer
3150 // the most current.
3151 //-----------------------------------------------------------------------------
3152 void CordbILCode::MakeOld()
3158 //-----------------------------------------------------------------------------
3159 // CordbILCode::GetAddress
3160 // Public method to get the Entry address for the code. This is the address
3161 // where the method first starts executing.
3164 // pStart - out-parameter to hold start address.
3167 // S_OK if *pStart is properly updated.
3168 //-----------------------------------------------------------------------------
3169 HRESULT CordbILCode::GetAddress(CORDB_ADDRESS * pStart)
3171 PUBLIC_REENTRANT_API_ENTRY(this);
3172 FAIL_IF_NEUTERED(this);
3173 VALIDATE_POINTER_TO_OBJECT(pStart, CORDB_ADDRESS *);
3176 _ASSERTE(this != NULL);
3177 _ASSERTE(this->GetFunction() != NULL);
3178 _ASSERTE(this->GetFunction()->GetModule() != NULL);
3179 _ASSERTE(this->GetFunction()->GetModule()->GetProcess() == GetProcess());
3181 *pStart = (m_codeRegionInfo.pAddress);
3184 } // CordbILCode::GetAddress
3186 //-----------------------------------------------------------------------------
3187 // CordbILCode::ReadCodeBytes
3188 // Reads the actual bytes of IL code into the data member m_rgbCode
3190 // none (uses data members)
3192 // standard HRESULT values
3193 // also allocates and initializes m_rgbCode
3194 // Notes: assumes that the caller has checked to ensure that m_rgbCode doesn't
3196 //-----------------------------------------------------------------------------
3197 HRESULT CordbILCode::ReadCodeBytes()
3202 // We have an address & size, so we'll just call ReadMemory.
3203 // This will conveniently strip out any patches too.
3204 CORDB_ADDRESS pStart = m_codeRegionInfo.pAddress;
3205 ULONG32 cbSize = (ULONG32) m_codeRegionInfo.cbSize;
3207 delete [] m_rgbCode;
3208 m_rgbCode = new BYTE[cbSize]; // throws
3211 hr = GetProcess()->ReadMemory(pStart, cbSize, m_rgbCode, &cbRead);
3214 SIMPLIFYING_ASSUMPTION(cbRead == cbSize);
3216 EX_CATCH_HRESULT(hr);
3218 } // CordbILCode::ReadCodeBytes
3220 //-----------------------------------------------------------------------------
3221 // CordbILCode::GetILToNativeMapping
3222 // Public method (implements ICorDebugCode) to get the IL-->{ Native Start, Native End} mapping.
3223 // Since 1 CordbILCode can map to multiple CordbNativeCode due to generics, we cannot reliably return the
3224 // mapping information in all cases. So we always fail with CORDBG_E_NON_NATIVE_FRAME. The caller should
3225 // call code:CordbNativeCode::GetILToNativeMapping instead.
3228 // cMap - size of incoming map[] array (in elements).
3229 // pcMap - OUT: full size of IL-->Native map (in elements).
3230 // map - caller allocated array to be filled in.
3233 // CORDBG_E_NON_NATIVE_FRAME in all cases
3234 //-----------------------------------------------------------------------------
3235 HRESULT CordbILCode::GetILToNativeMapping(ULONG32 cMap,
3237 COR_DEBUG_IL_TO_NATIVE_MAP map[])
3239 PUBLIC_API_ENTRY(this);
3240 FAIL_IF_NEUTERED(this);
3241 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pcMap, ULONG32 *);
3242 VALIDATE_POINTER_TO_OBJECT_ARRAY_OR_NULL(map, COR_DEBUG_IL_TO_NATIVE_MAP *, cMap, true, true);
3244 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
3246 return CORDBG_E_NON_NATIVE_FRAME;
3247 } // CordbILCode::GetILToNativeMapping
3251 * CordbILCode::GetLocalVarSig
3253 * Get the method's local variable metadata signature. This may be cached, but for dynamic modules we'll always
3254 * read it from the metadata. This function also returns the count of local variables in the method.
3257 * pLocalSigParser - OUT: the local variable signature for the method.
3258 * pLocalCount - OUT: the number of locals the method has.
3261 * HRESULT for success or failure.
3264 HRESULT CordbILCode::GetLocalVarSig(SigParser *pLocalSigParser,
3265 ULONG *pLocalVarCount)
3267 INTERNAL_SYNC_API_ENTRY(GetProcess());
3269 CONTRACTL // @dbgtodo exceptions - convert to throws...
3275 FAIL_IF_NEUTERED(this);
3278 // A function will not have a local var sig if it has no locals!
3279 if (m_localVarSigToken != mdSignatureNil)
3281 PCCOR_SIGNATURE localSignature;
3285 EX_TRY // // @dbgtodo exceptions - push this up
3287 GetFunction()->GetModule()->UpdateMetaDataCacheIfNeeded(m_localVarSigToken);
3288 hr = GetFunction()->GetModule()->GetMetaDataImporter()->GetSigFromToken(m_localVarSigToken,
3292 EX_CATCH_HRESULT(hr);
3295 LOG((LF_CORDB, LL_WARNING, "CICF::GLVS caught hr=0x%x\n", hr));
3299 LOG((LF_CORDB, LL_INFO100000, "CIC::GLVS creating sig parser sig=0x%x size=0x%x\n", localSignature, size));
3300 SigParser sigParser = SigParser(localSignature, size);
3304 IfFailRet(sigParser.GetCallingConvInfo(&data));
3306 _ASSERTE(data == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
3308 // Snagg the count of locals in the sig.
3309 IfFailRet(sigParser.GetData(&localCount));
3310 LOG((LF_CORDB, LL_INFO100000, "CIC::GLVS localCount=0x%x\n", localCount));
3311 if (pLocalSigParser != NULL)
3313 *pLocalSigParser = sigParser;
3315 if (pLocalVarCount != NULL)
3317 *pLocalVarCount = localCount;
3323 // Signature is Nil, so fill in everything with NULLs and zeros
3325 if (pLocalSigParser != NULL)
3327 *pLocalSigParser = SigParser(NULL, 0);
3330 if (pLocalVarCount != NULL)
3332 *pLocalVarCount = 0;
3335 LOG((LF_CORDB, LL_INFO100000, "CIC::GLVS returning hr=0x%x\n", hr));
3339 //-----------------------------------------------------------------------------
3340 // CordbILCode::GetLocalVariableType
3341 // Internal method. Return the type of an IL local, specified by 0-based index.
3344 // dwIndex - 0-based index for IL local number.
3345 // inst - instantiation information if this is a generic function. Eg,
3346 // if function is List<T>, inst describes T.
3347 // res - out parameter, yields to CordbType of the local.
3352 HRESULT CordbILCode::GetLocalVariableType(DWORD dwIndex,
3353 const Instantiation * pInst,
3354 CordbType ** ppResultType)
3356 ATT_ALLOW_LIVE_DO_STOPGO(GetProcess());
3357 LOG((LF_CORDB, LL_INFO10000, "CIC::GLVT dwIndex=0x%x pInst=0x%p\n", dwIndex, pInst));
3362 // Get the local variable signature.
3363 SigParser sigParser;
3366 IfFailThrow(GetLocalVarSig(&sigParser, &cLocals));
3369 if (dwIndex >= cLocals)
3371 ThrowHR(E_INVALIDARG);
3374 // Run the signature and find the required argument.
3375 for (unsigned int i = 0; i < dwIndex; i++)
3377 LOG((LF_CORDB, LL_INFO10000, "CIC::GLVT scanning index 0x%x\n", dwIndex));
3378 IfFailThrow(sigParser.SkipExactlyOne());
3381 hr = CordbType::SigToType(GetFunction()->GetModule(), &sigParser, pInst, ppResultType);
3382 LOG((LF_CORDB, LL_INFO10000, "CIC::GLVT CT::SigToType returned hr=0x%x\n", hr));
3385 } EX_CATCH_HRESULT(hr);
3389 mdSignature CordbILCode::GetLocalVarSigToken()
3391 return m_localVarSigToken;
3394 CordbReJitILCode::CordbReJitILCode(CordbFunction *pFunction, SIZE_T encVersion, VMPTR_SharedReJitInfo vmSharedReJitInfo) :
3395 CordbILCode(pFunction, TargetBuffer(), encVersion, mdSignatureNil, VmPtrToCookie(vmSharedReJitInfo)),
3400 _ASSERTE(!vmSharedReJitInfo.IsNull());
3401 DacSharedReJitInfo data = { 0 };
3402 IfFailThrow(GetProcess()->GetDAC()->GetSharedReJitInfoData(vmSharedReJitInfo, &data));
3403 IfFailThrow(Init(&data));
3406 //-----------------------------------------------------------------------------
3407 // CordbReJitILCode::Init
3410 // S_OK if all fields are inited. Else error.
3411 HRESULT CordbReJitILCode::Init(DacSharedReJitInfo* pSharedReJitInfo)
3415 // Instrumented IL map
3416 if (pSharedReJitInfo->m_cInstrumentedMapEntries)
3418 if (pSharedReJitInfo->m_cInstrumentedMapEntries > 100000)
3419 return CORDBG_E_TARGET_INCONSISTENT;
3420 m_cILMap = pSharedReJitInfo->m_cInstrumentedMapEntries;
3421 m_pILMap = new (nothrow)COR_IL_MAP[m_cILMap];
3422 TargetBuffer mapBuffer(pSharedReJitInfo->m_rgInstrumentedMapEntries, m_cILMap*sizeof(COR_IL_MAP));
3423 IfFailRet(GetProcess()->SafeReadBuffer(mapBuffer, (BYTE*)m_pILMap.GetValue(), FALSE /* bThrowOnError */));
3426 // Read the method's IL header
3427 CORDB_ADDRESS pIlHeader = pSharedReJitInfo->m_pbIL;
3428 IMAGE_COR_ILMETHOD_FAT header = { 0 };
3429 bool headerMustBeTiny = false;
3430 ULONG32 headerSize = 0;
3431 hr = GetProcess()->SafeReadStruct(pIlHeader, &header);
3434 // Its possible the header is tiny and there isn't enough memory to read a complete
3436 headerMustBeTiny = true;
3437 IfFailRet(GetProcess()->SafeReadStruct(pIlHeader, (IMAGE_COR_ILMETHOD_TINY *)&header));
3440 // Read the ILCodeSize and LocalVarSigTok from header
3441 ULONG32 ilCodeSize = 0;
3442 IMAGE_COR_ILMETHOD_TINY *pMethodTinyHeader = (IMAGE_COR_ILMETHOD_TINY *)&header;
3443 bool isTinyHeader = ((pMethodTinyHeader->Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat);
3446 ilCodeSize = (((unsigned)pMethodTinyHeader->Flags_CodeSize) >> (CorILMethod_FormatShift - 1));
3447 headerSize = sizeof(IMAGE_COR_ILMETHOD_TINY);
3448 m_localVarSigToken = mdSignatureNil;
3450 else if (headerMustBeTiny)
3452 // header was not CorILMethod_TinyFormat
3453 // this is not possible, must be an error when reading from data target
3454 return CORDBG_E_READVIRTUAL_FAILURE;
3458 ilCodeSize = header.CodeSize;
3459 headerSize = header.Size * 4;
3460 m_localVarSigToken = header.LocalVarSigTok;
3462 if (ilCodeSize == 0 || ilCodeSize > 100000)
3464 return CORDBG_E_TARGET_INCONSISTENT;
3467 m_codeRegionInfo.Init(pIlHeader + headerSize, ilCodeSize);
3468 m_pLocalIL = new (nothrow) BYTE[ilCodeSize];
3469 if (m_pLocalIL == NULL)
3470 return E_OUTOFMEMORY;
3471 m_cbLocalIL = ilCodeSize;
3472 IfFailRet(GetProcess()->SafeReadBuffer(m_codeRegionInfo, m_pLocalIL, FALSE /*throwOnError*/));
3474 // Check if this il code has exception clauses
3475 if ((pMethodTinyHeader->Flags_CodeSize & CorILMethod_MoreSects) == 0)
3477 return S_OK; // no EH, done initing
3480 // EH section starts at the 4 byte aligned address after the code
3481 CORDB_ADDRESS ehClauseHeader = ((pIlHeader + headerSize + ilCodeSize - 1) & ~3) + 4;
3483 IfFailRet(GetProcess()->SafeReadStruct(ehClauseHeader, &kind));
3484 if ((kind & CorILMethod_Sect_KindMask) != CorILMethod_Sect_EHTable)
3488 if (kind & CorILMethod_Sect_FatFormat)
3490 // Read the section header to see how many clauses there are
3491 IMAGE_COR_ILMETHOD_SECT_FAT sectionHeader = { 0 };
3492 IfFailRet(GetProcess()->SafeReadStruct(ehClauseHeader, §ionHeader));
3493 m_cClauses = (sectionHeader.DataSize - 4) / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT);
3494 if (m_cClauses > 10000) // sanity check the data before allocating
3496 return CORDBG_E_TARGET_INCONSISTENT;
3499 // Read in the clauses
3500 TargetBuffer buffer(ehClauseHeader + sizeof(IMAGE_COR_ILMETHOD_SECT_FAT), m_cClauses*sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
3501 NewArrayHolder<IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT> pClauses = new (nothrow)IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT[m_cClauses];
3502 if (pClauses == NULL)
3503 return E_OUTOFMEMORY;
3504 IfFailRet(GetProcess()->SafeReadBuffer(buffer, (BYTE*)pClauses.GetValue(), FALSE /*throwOnError*/));
3507 m_pClauses = new (nothrow)CorDebugEHClause[m_cClauses];
3508 if (m_pClauses == NULL)
3509 return E_OUTOFMEMORY;
3510 for (ULONG32 i = 0; i < m_cClauses; i++)
3512 BOOL isFilter = ((pClauses[i].Flags & COR_ILEXCEPTION_CLAUSE_FILTER) != 0);
3513 m_pClauses[i].Flags = pClauses[i].Flags;
3514 m_pClauses[i].TryOffset = pClauses[i].TryOffset;
3515 m_pClauses[i].TryLength = pClauses[i].TryLength;
3516 m_pClauses[i].HandlerOffset = pClauses[i].HandlerOffset;
3517 m_pClauses[i].HandlerLength = pClauses[i].HandlerLength;
3518 // these two fields are a union in the image, but are seperate in the struct ICorDebug returns
3519 m_pClauses[i].ClassToken = isFilter ? 0 : pClauses[i].ClassToken;
3520 m_pClauses[i].FilterOffset = isFilter ? pClauses[i].FilterOffset : 0;
3525 // Read in the section header to see how many small clauses there are
3526 IMAGE_COR_ILMETHOD_SECT_SMALL sectionHeader = { 0 };
3527 IfFailRet(GetProcess()->SafeReadStruct(ehClauseHeader, §ionHeader));
3528 ULONG32 m_cClauses = (sectionHeader.DataSize - 4) / sizeof(IMAGE_COR_ILMETHOD_SECT_SMALL);
3529 if (m_cClauses > 10000) // sanity check the data before allocating
3531 return CORDBG_E_TARGET_INCONSISTENT;
3534 // Read in the clauses
3535 TargetBuffer buffer(ehClauseHeader + sizeof(IMAGE_COR_ILMETHOD_SECT_SMALL), m_cClauses*sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL));
3536 NewArrayHolder<IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL> pClauses = new (nothrow)IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL[m_cClauses];
3537 if (pClauses == NULL)
3538 return E_OUTOFMEMORY;
3539 IfFailRet(GetProcess()->SafeReadBuffer(buffer, (BYTE*)pClauses.GetValue(), FALSE /*throwOnError*/));
3542 m_pClauses = new (nothrow)CorDebugEHClause[m_cClauses];
3543 if (m_pClauses == NULL)
3544 return E_OUTOFMEMORY;
3545 for (ULONG32 i = 0; i < m_cClauses; i++)
3547 BOOL isFilter = ((pClauses[i].Flags & COR_ILEXCEPTION_CLAUSE_FILTER) != 0);
3548 m_pClauses[i].Flags = pClauses[i].Flags;
3549 m_pClauses[i].TryOffset = pClauses[i].TryOffset;
3550 m_pClauses[i].TryLength = pClauses[i].TryLength;
3551 m_pClauses[i].HandlerOffset = pClauses[i].HandlerOffset;
3552 m_pClauses[i].HandlerLength = pClauses[i].HandlerLength;
3553 // these two fields are a union in the image, but are seperate in the struct ICorDebug returns
3554 m_pClauses[i].ClassToken = isFilter ? 0 : pClauses[i].ClassToken;
3555 m_pClauses[i].FilterOffset = isFilter ? pClauses[i].FilterOffset : 0;
3562 #define MIN(a,b) ((a) < (b) ? (a) : (b))
3565 //-----------------------------------------------------------------------------
3566 // CordbReJitILCode::GetEHClauses
3567 // Public method to get the EH clauses for IL code
3570 // cClauses - size of incoming clauses array (in elements).
3571 // pcClauses - OUT param: cClauses>0 -> the number of elements written to in the clauses array.
3572 // cClauses=0 -> the number of EH clauses this IL code has
3573 // clauses - caller allocated storage to hold the EH clauses.
3576 // S_OK if successfully copied elements to clauses array.
3577 HRESULT CordbReJitILCode::GetEHClauses(ULONG32 cClauses, ULONG32 * pcClauses, CorDebugEHClause clauses[])
3579 PUBLIC_API_ENTRY(this);
3580 FAIL_IF_NEUTERED(this);
3581 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pcClauses, ULONG32 *);
3582 VALIDATE_POINTER_TO_OBJECT_ARRAY_OR_NULL(clauses, CorDebugEHClause *, cClauses, true, true);
3583 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
3585 if (cClauses != 0 && clauses == NULL)
3587 return E_INVALIDARG;
3590 if (pcClauses != NULL)
3594 *pcClauses = m_cClauses;
3598 *pcClauses = MIN(cClauses, m_cClauses);
3602 if (clauses != NULL)
3604 memcpy_s(clauses, sizeof(CorDebugEHClause)*cClauses, m_pClauses, sizeof(CorDebugEHClause)*MIN(cClauses, m_cClauses));
3609 ULONG CordbReJitILCode::AddRef()
3611 return CordbCode::AddRef();
3613 ULONG CordbReJitILCode::Release()
3615 return CordbCode::Release();
3618 HRESULT CordbReJitILCode::QueryInterface(REFIID riid, void** ppInterface)
3620 if (riid == IID_ICorDebugILCode)
3622 *ppInterface = static_cast<ICorDebugILCode*>(this);
3624 else if (riid == IID_ICorDebugILCode2)
3626 *ppInterface = static_cast<ICorDebugILCode2*>(this);
3630 return CordbILCode::QueryInterface(riid, ppInterface);
3637 HRESULT CordbReJitILCode::GetLocalVarSigToken(mdSignature *pmdSig)
3639 PUBLIC_API_ENTRY(this);
3640 FAIL_IF_NEUTERED(this);
3641 VALIDATE_POINTER_TO_OBJECT(pmdSig, mdSignature *);
3642 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
3644 *pmdSig = m_localVarSigToken;
3648 HRESULT CordbReJitILCode::GetInstrumentedILMap(ULONG32 cMap, ULONG32 *pcMap, COR_IL_MAP map[])
3650 PUBLIC_API_ENTRY(this);
3651 FAIL_IF_NEUTERED(this);
3652 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pcClauses, ULONG32 *);
3653 VALIDATE_POINTER_TO_OBJECT_ARRAY_OR_NULL(map, COR_IL_MAP *, cMap, true, true);
3654 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
3656 if (cMap != 0 && map == NULL)
3658 return E_INVALIDARG;
3669 *pcMap = MIN(cMap, m_cILMap);
3675 memcpy_s(map, sizeof(COR_IL_MAP)*cMap, m_pILMap, sizeof(COR_IL_MAP)*MIN(cMap, m_cILMap));
3680 // FindNativeInfoInILVariableArray
3681 // Linear search through an array of NativeVarInfos, to find the variable of index dwIndex, valid
3682 // at the given ip. Returns CORDBG_E_IL_VAR_NOT_AVAILABLE if the variable isn't valid at the given ip.
3684 // input: dwIndex - variable number
3686 // nativeInfoList - list of instances of NativeVarInfo
3687 // output: ppNativeInfo - the element of nativeInfoList that corresponds to the IP and variable number
3688 // if we find such an element or NULL otherwise
3689 // Return value: HRESULT: returns S_OK or CORDBG_E_IL_VAR_NOT_AVAILABLE if the variable isn't found
3691 HRESULT FindNativeInfoInILVariableArray(DWORD dwIndex,
3693 const DacDbiArrayList<ICorDebugInfo::NativeVarInfo> * nativeInfoList,
3694 const ICorDebugInfo::NativeVarInfo ** ppNativeInfo)
3696 _ASSERTE(ppNativeInfo != NULL);
3697 *ppNativeInfo = NULL;
3699 // A few words about this search: it must be linear, and the
3700 // comparison of startOffset and endOffset to ip must be
3701 // <=/>. startOffset points to the first instruction that will
3702 // make the variable's home valid. endOffset points to the first
3703 // instruction at which the variable's home invalid.
3704 int lastGoodOne = -1;
3705 for (unsigned int i = 0; i < (unsigned)nativeInfoList->Count(); i++)
3707 if ((*nativeInfoList)[i].varNumber == dwIndex)
3709 if ( (lastGoodOne == -1) ||
3710 ((*nativeInfoList)[lastGoodOne].startOffset < (*nativeInfoList)[i].startOffset) )
3715 if (((*nativeInfoList)[i].startOffset <= ip) &&
3716 ((*nativeInfoList)[i].endOffset > ip))
3718 *ppNativeInfo = &((*nativeInfoList)[i]);
3727 // We didn't find the variable. Was the endOffset of the last range for this variable
3728 // equal to the current IP? If so, go ahead and "lie" and report that as the
3729 // variable's home for now.
3733 // * See TODO comment in code:Compiler::siUpdate (jit\scopeinfo.cpp). In optimized
3734 // code, the JIT can report var lifetimes as being one instruction too short.
3735 // This workaround makes up for that. Example code:
3737 // static void foo(int x)
3739 // int b = x; // Value of "x" would not be reported in optimized code without the workaround
3743 // * Since this is the first instruction after the last range a variable was alive,
3744 // we're essentially assuming that since that instruction hasn't been executed
3745 // yet, and since there isn't a new home for the variable, that the last home is
3746 // still good. This actually turns out to be true 99.9% of the time, so we'll go
3748 // * We've been lying like this since 1999, so surely it's safe.
3749 if ((lastGoodOne > -1) && ((*nativeInfoList)[lastGoodOne].endOffset == ip))
3751 *ppNativeInfo = &((*nativeInfoList)[lastGoodOne]);
3755 return CORDBG_E_IL_VAR_NOT_AVAILABLE;
3756 } // FindNativeInfoInILVariableArray
3759 // * ------------------------------------------------------------------------- *
3760 // * Variable Enum class
3761 // * ------------------------------------------------------------------------- *
3762 //-----------------------------------------------------------------------------
3763 // CordbVariableHome constructor
3766 // pCode - CordbNativeCode instance containing this variable home
3767 // pNativeVarInfo - native location, lifetime, and index information for
3769 // isLocal - indicates whether the instance is a local variable,
3770 // as opposed to an argument
3771 // index - the argument or slot index
3773 // fields of the CordbVariableHome instance have been initialized
3774 //-----------------------------------------------------------------------------
3775 CordbVariableHome::CordbVariableHome(CordbNativeCode *pCode,
3776 const ICorDebugInfo::NativeVarInfo nativeVarInfo,
3779 CordbBase(pCode->GetModule()->GetProcess(), 0)
3781 _ASSERTE(pCode != NULL);
3783 m_pCode.Assign(pCode);
3784 m_nativeVarInfo = nativeVarInfo;
3785 m_isLocal = isLocal;
3789 CordbVariableHome::~CordbVariableHome()
3791 _ASSERTE(this->IsNeutered());
3794 void CordbVariableHome::Neuter()
3797 CordbBase::Neuter();
3800 //-----------------------------------------------------------------------------
3801 // Public method for IUnknown::QueryInterface.
3802 // Has standard QI semantics.
3803 //-----------------------------------------------------------------------------
3804 HRESULT CordbVariableHome::QueryInterface(REFIID id, void **pInterface)
3806 if (id == IID_ICorDebugVariableHome)
3808 *pInterface = static_cast<ICorDebugVariableHome *>(this);
3810 else if (id == IID_IUnknown)
3812 *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugVariableHome *>(this));
3817 return E_NOINTERFACE;
3824 //-----------------------------------------------------------------------------
3825 // CordbVariableHome::GetCode
3826 // Public method to get the Code object containing this variable home.
3829 // ppCode - OUT: returns the Code object for this variable home.
3832 // S_OK - on success.
3833 //-----------------------------------------------------------------------------
3834 HRESULT CordbVariableHome::GetCode(ICorDebugCode **ppCode)
3836 PUBLIC_REENTRANT_API_ENTRY(this);
3837 FAIL_IF_NEUTERED(this);
3838 VALIDATE_POINTER_TO_OBJECT(ppCode, ICorDebugCode **);
3839 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
3841 HRESULT hr = m_pCode->QueryInterface(IID_ICorDebugCode, (LPVOID*)ppCode);
3846 //-----------------------------------------------------------------------------
3847 // CordbVariableHome::GetSlotIndex
3848 // Public method to get the slot index for this variable home.
3851 // pSlotIndex - OUT: returns the managed slot-index of this variable home.
3854 // S_OK - on success
3855 // E_FAIL - if the variable is not a local variable, but an argument
3856 //-----------------------------------------------------------------------------
3857 HRESULT CordbVariableHome::GetSlotIndex(ULONG32 *pSlotIndex)
3859 PUBLIC_REENTRANT_API_ENTRY(this);
3860 FAIL_IF_NEUTERED(this);
3861 VALIDATE_POINTER_TO_OBJECT(pSlotIndex, ULONG32 *);
3862 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
3868 *pSlotIndex = m_index;
3872 //-----------------------------------------------------------------------------
3873 // CordbVariableHome::GetArgumentIndex
3874 // Public method to get the slot index for this variable home.
3877 // pSlotIndex - OUT: returns the managed argument-index of this variable home.
3880 // S_OK - on success
3881 // E_FAIL - if the variable is not an argument, but a local variable
3882 //-----------------------------------------------------------------------------
3883 HRESULT CordbVariableHome::GetArgumentIndex(ULONG32 *pArgumentIndex)
3885 PUBLIC_REENTRANT_API_ENTRY(this);
3886 FAIL_IF_NEUTERED(this);
3887 VALIDATE_POINTER_TO_OBJECT(pArgumentIndex, ULONG32 *);
3888 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
3894 *pArgumentIndex = m_index;
3898 //-----------------------------------------------------------------------------
3899 // CordbVariableHome::GetLiveRange
3900 // Public method to get the native range over which this variable is live.
3903 // pStartOffset - OUT: returns the logical offset at which the variable is
3905 // pEndOffset - OUT: returns the logical offset immediately after that at
3906 // which the variable is last live
3909 // S_OK - on success
3910 //-----------------------------------------------------------------------------
3911 HRESULT CordbVariableHome::GetLiveRange(ULONG32 *pStartOffset,
3912 ULONG32 *pEndOffset)
3914 PUBLIC_REENTRANT_API_ENTRY(this);
3915 FAIL_IF_NEUTERED(this);
3916 VALIDATE_POINTER_TO_OBJECT(pStartOffset, ULONG32 *);
3917 VALIDATE_POINTER_TO_OBJECT(pEndOffset, ULONG32 *);
3918 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
3920 *pStartOffset = m_nativeVarInfo.startOffset;
3921 *pEndOffset = m_nativeVarInfo.endOffset;
3925 //-----------------------------------------------------------------------------
3926 // CordbVariableHome::GetLocationType
3927 // Public method to get the type of native location for this variable home.
3930 // pLocationType - OUT: the type of native location
3933 // S_OK - on success
3934 //-----------------------------------------------------------------------------
3935 HRESULT CordbVariableHome::GetLocationType(VariableLocationType *pLocationType)
3937 PUBLIC_REENTRANT_API_ENTRY(this);
3938 FAIL_IF_NEUTERED(this);
3939 VALIDATE_POINTER_TO_OBJECT(pLocationType, VariableLocationType *);
3940 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
3942 switch (m_nativeVarInfo.loc.vlType)
3944 case ICorDebugInfo::VLT_REG:
3945 *pLocationType = VLT_REGISTER;
3947 case ICorDebugInfo::VLT_STK:
3948 *pLocationType = VLT_REGISTER_RELATIVE;
3951 *pLocationType = VLT_INVALID;
3956 //-----------------------------------------------------------------------------
3957 // CordbVariableHome::GetRegister
3958 // Public method to get the register or base register for this variable hom.
3961 // pRegister - OUT: for VLT_REGISTER location types, gives the register.
3962 // for VLT_REGISTER_RELATIVE location types, gives the base
3966 // S_OK - on success
3967 // E_FAIL - for VLT_INVALID location types
3968 //-----------------------------------------------------------------------------
3969 HRESULT CordbVariableHome::GetRegister(CorDebugRegister *pRegister)
3971 PUBLIC_REENTRANT_API_ENTRY(this);
3972 FAIL_IF_NEUTERED(this);
3973 VALIDATE_POINTER_TO_OBJECT(pRegister, CorDebugRegister *);
3974 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
3976 switch (m_nativeVarInfo.loc.vlType)
3978 case ICorDebugInfo::VLT_REG:
3979 *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlReg.vlrReg);
3981 case ICorDebugInfo::VLT_STK:
3982 *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlStk.vlsBaseReg);
3990 //-----------------------------------------------------------------------------
3991 // CordbVariableHome::GetOffset
3992 // Public method to get the offset from the base register for this variable home.
3995 // pOffset - OUT: gives the offset from the base register
3998 // S_OK - on success
3999 // E_FAIL - for location types other than VLT_REGISTER_RELATIVE
4000 //-----------------------------------------------------------------------------
4001 HRESULT CordbVariableHome::GetOffset(LONG *pOffset)
4003 PUBLIC_REENTRANT_API_ENTRY(this);
4004 FAIL_IF_NEUTERED(this);
4005 VALIDATE_POINTER_TO_OBJECT(pOffset, LONG *);
4006 ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess());
4008 switch (m_nativeVarInfo.loc.vlType)
4010 case ICorDebugInfo::VLT_STK:
4011 *pOffset = m_nativeVarInfo.loc.vlStk.vlsOffset;
4020 // * ------------------------------------------------------------------------- *
4021 // * Native Code class
4022 // * ------------------------------------------------------------------------- */
4025 //-----------------------------------------------------------------------------
4026 // CordbNativeCode ctor to make Native code.
4029 // pFunction - the function for which this is the native code object
4030 // pJitData - the information about this code object retrieved from the DAC
4031 // fIsInstantiatedGeneric - indicates whether this code object is an instantiated
4034 // fields of this instance of CordbNativeCode have been initialized
4035 //-----------------------------------------------------------------------------
4036 CordbNativeCode::CordbNativeCode(CordbFunction * pFunction,
4037 const NativeCodeFunctionData * pJitData,
4038 BOOL fIsInstantiatedGeneric)
4039 : CordbCode(pFunction, (UINT_PTR)pJitData->m_rgCodeRegions[kHot].pAddress, pJitData->encVersion, FALSE),
4040 m_vmNativeCodeMethodDescToken(pJitData->vmNativeCodeMethodDescToken),
4041 m_fCodeAvailable(TRUE),
4042 m_fIsInstantiatedGeneric(fIsInstantiatedGeneric != FALSE)
4044 _ASSERTE(GetVersion() >= CorDB_DEFAULT_ENC_FUNCTION_VERSION);
4046 for (CodeBlobRegion region = kHot; region < MAX_REGIONS; ++region)
4048 m_rgCodeRegions[region] = pJitData->m_rgCodeRegions[region];
4050 } //CordbNativeCode::CordbNativeCode
4052 //-----------------------------------------------------------------------------
4053 // Public method for IUnknown::QueryInterface.
4054 // Has standard QI semantics.
4055 //-----------------------------------------------------------------------------
4056 HRESULT CordbNativeCode::QueryInterface(REFIID id, void ** pInterface)
4058 if (id == IID_ICorDebugCode)
4060 *pInterface = static_cast<ICorDebugCode *>(this);
4062 else if (id == IID_ICorDebugCode2)
4064 *pInterface = static_cast<ICorDebugCode2 *>(this);
4066 else if (id == IID_ICorDebugCode3)
4068 *pInterface = static_cast<ICorDebugCode3 *>(this);
4070 else if (id == IID_ICorDebugCode4)
4072 *pInterface = static_cast<ICorDebugCode4 *>(this);
4074 else if (id == IID_IUnknown)
4076 *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugCode *>(this));
4081 return E_NOINTERFACE;
4088 //-----------------------------------------------------------------------------
4089 // CordbNativeCode::GetAddress
4090 // Public method to get the Entry address for the code. This is the address
4091 // where the method first starts executing.
4094 // pStart - out-parameter to hold start address.
4097 // S_OK if *pStart is properly updated.
4098 //-----------------------------------------------------------------------------
4099 HRESULT CordbNativeCode::GetAddress(CORDB_ADDRESS * pStart)
4101 PUBLIC_REENTRANT_API_ENTRY(this);
4102 FAIL_IF_NEUTERED(this);
4103 VALIDATE_POINTER_TO_OBJECT(pStart, CORDB_ADDRESS *);
4106 _ASSERTE(this != NULL);
4107 _ASSERTE(this->GetFunction() != NULL);
4108 _ASSERTE(this->GetFunction()->GetModule() != NULL);
4109 _ASSERTE(this->GetFunction()->GetModule()->GetProcess() == GetProcess());
4111 // Since we don't do code-pitching, the address points directly to the code.
4112 *pStart = (m_rgCodeRegions[kHot].pAddress);
4114 if (*pStart == NULL)
4116 return CORDBG_E_CODE_NOT_AVAILABLE;
4119 } // CordbNativeCode::GetAddress
4121 //-----------------------------------------------------------------------------
4122 // CordbNativeCode::ReadCodeBytes
4123 // Reads the actual bytes of native code from both the hot and cold regions
4124 // into the data member m_rgbCode
4126 // none (uses data members)
4128 // standard HRESULT values
4129 // also allocates and initializes m_rgbCode
4130 // Notes: assumes that the caller has checked to ensure that m_rgbCode doesn't
4132 //-----------------------------------------------------------------------------
4133 HRESULT CordbNativeCode::ReadCodeBytes()
4139 // We have an address & size, so we'll just call ReadMemory.
4140 // This will conveniently strip out any patches too.
4141 CORDB_ADDRESS pHotStart = m_rgCodeRegions[kHot].pAddress;
4142 CORDB_ADDRESS pColdStart = m_rgCodeRegions[kCold].pAddress;
4143 ULONG32 cbHotSize = (ULONG32) m_rgCodeRegions[kHot].cbSize;
4144 ULONG32 cbColdSize = GetColdSize();
4146 delete [] m_rgbCode;
4147 m_rgbCode = new BYTE[cbHotSize + cbColdSize];
4150 hr = GetProcess()->ReadMemory(pHotStart, cbHotSize, m_rgbCode, &cbRead);
4153 SIMPLIFYING_ASSUMPTION(cbRead == cbHotSize);
4155 if (HasColdRegion())
4157 hr = GetProcess()->ReadMemory(pColdStart, cbColdSize, (BYTE *) m_rgbCode + cbHotSize, &cbRead);
4160 SIMPLIFYING_ASSUMPTION(cbRead == cbColdSize);
4163 EX_CATCH_HRESULT(hr);
4166 } // CordbNativeCode::ReadCodeBytes
4168 //-----------------------------------------------------------------------------
4169 // CordbNativeCode::GetColdSize
4170 // Get the size of the cold regions in bytes.
4173 // none--uses data member m_rgCodeRegions to compute total size.
4176 // the size of the code in bytes.
4177 //-----------------------------------------------------------------------------
4178 ULONG32 CordbNativeCode::GetColdSize()
4180 ULONG32 pcBytes = 0;
4181 for (CodeBlobRegion index = kCold; index < MAX_REGIONS; ++index)
4183 pcBytes += m_rgCodeRegions[index].cbSize;
4186 } // CordbNativeCode::GetColdSize
4188 //-----------------------------------------------------------------------------
4189 // CordbNativeCode::GetSize
4190 // Get the size of the code in bytes.
4193 // none--uses data member m_rgCodeRegions to compute total size.
4196 // the size of the code in bytes.
4197 //-----------------------------------------------------------------------------
4198 ULONG32 CordbNativeCode::GetSize()
4200 ULONG32 pcBytes = 0;
4201 for (CodeBlobRegion index = kHot; index < MAX_REGIONS; ++index)
4203 pcBytes += m_rgCodeRegions[index].cbSize;
4206 } // CordbNativeCode::GetSize
4208 //-----------------------------------------------------------------------------
4209 // CordbNativeCode::GetILToNativeMapping
4210 // Public method (implements ICorDebugCode) to get the IL-->{ Native Start, Native End} mapping.
4211 // This can only be retrieved for native code.
4212 // This will copy as much of the map as can fit in the incoming buffer.
4215 // cMap - size of incoming map[] array (in elements).
4216 // pcMap - OUT: full size of IL-->Native map (in elements).
4217 // map - caller allocated array to be filled in.
4220 // S_OK on successful copying.
4221 //-----------------------------------------------------------------------------
4222 HRESULT CordbNativeCode::GetILToNativeMapping(ULONG32 cMap,
4224 COR_DEBUG_IL_TO_NATIVE_MAP map[])
4226 PUBLIC_REENTRANT_API_ENTRY(this);
4227 FAIL_IF_NEUTERED(this);
4228 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pcMap, ULONG32 *);
4229 VALIDATE_POINTER_TO_OBJECT_ARRAY_OR_NULL(map, COR_DEBUG_IL_TO_NATIVE_MAP *,cMap,true,true);
4231 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
4238 SequencePoints * pSeqPts = GetSequencePoints();
4239 DebuggerILToNativeMap * rgMapInt = pSeqPts->GetMapAddr();
4240 ULONG32 cMapIntCount = pSeqPts->GetEntryCount();
4242 // If they gave us space to copy into...
4245 // Only copy as much as either they gave us or we have to copy.
4246 ULONG32 cMapToCopy = min(cMap, cMapIntCount);
4248 // Remember that we need to translate between our internal DebuggerILToNativeMap and the external
4249 // COR_DEBUG_IL_TO_NATIVE_MAP!
4250 ULONG32 size = GetSize();
4251 ExportILToNativeMap(cMapToCopy, map, rgMapInt, size);
4254 // return the full count of map entries
4257 *pcMap = cMapIntCount;
4260 EX_CATCH_HRESULT(hr);
4262 } // CordbNativeCode::GetILToNativeMapping
4264 //-----------------------------------------------------------------------------
4265 // CordbNativeCode::GetCodeChunks
4266 // Public method to get the code regions of code. If the code
4267 // is broken into discontinuous regions (hot + cold), this lets a debugger
4268 // find the number of regions, and (start,size) of each.
4271 // cbufSize - size of incoming chunks array (in elements).
4272 // pcnumChunks - OUT param: the number of elements written to in the chunk array.//
4273 // chunks - caller allocated storage to hold the code chunks.
4276 // S_OK if successfully copied elements to Chunk array.
4277 //-----------------------------------------------------------------------------
4278 HRESULT CordbNativeCode::GetCodeChunks(
4280 ULONG32 * pcnumChunks,
4281 CodeChunkInfo chunks[]
4284 PUBLIC_API_ENTRY(this);
4286 if (pcnumChunks == NULL)
4288 return E_INVALIDARG;
4290 if ((chunks == NULL) != (cbufSize == 0))
4292 return E_INVALIDARG;
4295 // Current V2.0 implementation has at most 2 possible chunks right now (1 hot, and 1 cold).
4296 ULONG32 cActualChunks = HasColdRegion() ? 2 : 1;
4298 // If no buf size, then we're querying the total number of chunks.
4301 *pcnumChunks = cActualChunks;
4305 // Else give them as many as they asked for.
4306 for (CodeBlobRegion index = kHot; (index < MAX_REGIONS) && ((int)cbufSize > index); ++index)
4308 // Fill in the region information
4309 chunks[index].startAddr = m_rgCodeRegions[index].pAddress;
4310 chunks[index].length = (ULONG32) (m_rgCodeRegions[index].cbSize);
4311 *pcnumChunks = cbufSize;
4315 } // CordbNativeCode::GetCodeChunks
4317 //-----------------------------------------------------------------------------
4318 // CordbNativeCode::GetCompilerFlags
4319 // Public entry point to get code flags for this Code object.
4320 // Originally, ICDCode had this method implemented independently from the
4321 // ICDModule method GetJitCompilerFlags. This was because it was considered that
4322 // the flags would be per function, rather than per module.
4323 // In addition, GetCompilerFlags did two different things depending on whether
4324 // the code had a native image. It turned out that was the wrong thing to do
4328 // pdwFlags - OUT: code gen flags (see CorDebugJITCompilerFlags)
4331 // S_OK if pdwFlags is set properly.
4332 //-----------------------------------------------------------------------------
4333 HRESULT CordbNativeCode::GetCompilerFlags(DWORD * pdwFlags)
4335 PUBLIC_API_ENTRY(this);
4336 FAIL_IF_NEUTERED(this);
4337 VALIDATE_POINTER_TO_OBJECT(pdwFlags, DWORD *);
4339 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
4341 return GetFunction()->GetModule()->GetJITCompilerFlags(pdwFlags);
4343 } // CordbNativeCode::GetCompilerFlags
4345 //-----------------------------------------------------------------------------
4346 // Given an IL local variable number and a native IP offset, return the
4347 // location of the variable in jitted code.
4348 //-----------------------------------------------------------------------------
4349 HRESULT CordbNativeCode::ILVariableToNative(DWORD dwIndex,
4351 const ICorDebugInfo::NativeVarInfo ** ppNativeInfo)
4353 _ASSERTE(m_nativeVarData.IsInitialized());
4355 return FindNativeInfoInILVariableArray(dwIndex,
4357 m_nativeVarData.GetOffsetInfoList(),
4359 } // CordbNativeCode::ILVariableToNative
4362 HRESULT CordbNativeCode::GetReturnValueLiveOffset(ULONG32 ILoffset, ULONG32 bufferSize, ULONG32 *pFetched, ULONG32 *pOffsets)
4366 PUBLIC_API_ENTRY(this);
4367 FAIL_IF_NEUTERED(this);
4369 VALIDATE_POINTER_TO_OBJECT(pFetched, ULONG32 *);
4371 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
4374 hr = GetReturnValueLiveOffsetImpl(NULL, ILoffset, bufferSize, pFetched, pOffsets);
4376 EX_CATCH_HRESULT(hr);
4380 //-----------------------------------------------------------------------------
4381 // CordbNativeCode::EnumerateVariableHomes
4382 // Public method to get an enumeration of native variable homes. This may
4383 // include multiple ICorDebugVariableHomes for the same slot or argument index
4384 // if they have different homes at different points in the function.
4387 // ppEnum - OUT: returns the enum of variable homes.
4390 // HRESULT for success or failure.
4391 //-----------------------------------------------------------------------------
4392 HRESULT CordbNativeCode::EnumerateVariableHomes(ICorDebugVariableHomeEnum **ppEnum)
4394 PUBLIC_REENTRANT_API_ENTRY(this);
4395 FAIL_IF_NEUTERED(this);
4396 VALIDATE_POINTER_TO_OBJECT(ppEnum, ICorDebugVariableHomeEnum **);
4397 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
4401 // Get the argument count
4403 CordbFunction *func = GetFunction();
4404 _ASSERTE(func != NULL);
4405 IfFailRet(func->GetSig(NULL, &argCount, NULL));
4408 // Get the number of locals
4409 ULONG localCount = 0;
4412 GetFunction()->GetILCode()->GetLocalVarSig(NULL, &localCount);
4414 EX_CATCH_HRESULT(hr);
4418 RSSmartPtr<CordbVariableHome> *rsHomes = NULL;
4422 CordbProcess *pProcess = GetProcess();
4423 _ASSERTE(pProcess != NULL);
4425 const DacDbiArrayList<ICorDebugInfo::NativeVarInfo> *pOffsetInfoList = m_nativeVarData.GetOffsetInfoList();
4426 _ASSERTE(pOffsetInfoList != NULL);
4427 DWORD countHomes = 0;
4428 for (int i = 0; i < pOffsetInfoList->Count(); i++)
4430 const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]);
4431 _ASSERTE(pNativeVarInfo != NULL);
4433 // The variable information list can include variables
4434 // with special varNumbers representing, for instance, the
4435 // parameter types for generic methods. Here we are only
4436 // interested in local variables and arguments.
4437 if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM)
4442 rsHomes = new RSSmartPtr<CordbVariableHome>[countHomes];
4444 DWORD varHomeInd = 0;
4445 for (int i = 0; i < pOffsetInfoList->Count(); i++)
4447 const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]);
4449 // Again, only look for native var info representing local
4450 // variables and arguments.
4451 if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM)
4453 // determine whether this variable home represents and argument or local variable
4454 BOOL isLocal = ((ULONG)pNativeVarInfo->varNumber >= argCount);
4456 // determine the argument-index or slot-index of this variable home
4457 ULONG argOrSlotIndex;
4459 argOrSlotIndex = pNativeVarInfo->varNumber - argCount;
4460 _ASSERTE(argOrSlotIndex < localCount);
4462 argOrSlotIndex = pNativeVarInfo->varNumber;
4465 RSInitHolder<CordbVariableHome> pCVH(new CordbVariableHome(this,
4466 (*pOffsetInfoList)[i],
4469 pProcess->GetContinueNeuterList()->Add(pProcess, pCVH);
4470 _ASSERTE(varHomeInd < countHomes);
4471 rsHomes[varHomeInd].Assign(pCVH);
4472 pCVH.ClearAndMarkDontNeuter();
4477 RSInitHolder<CordbVariableHomeEnumerator> pCDVHE(
4478 new CordbVariableHomeEnumerator(GetProcess(), &rsHomes, countHomes));
4479 pProcess->GetContinueNeuterList()->Add(pProcess, pCDVHE);
4480 pCDVHE.TransferOwnershipExternal(ppEnum);
4482 EX_CATCH_HRESULT(hr);
4487 int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count)
4489 #if defined(DBG_TARGET_ARM)
4490 return MAX_INSTRUCTION_LENGTH;
4491 #elif defined(DBG_TARGET_ARM64)
4492 return MAX_INSTRUCTION_LENGTH;
4493 #elif defined(DBG_TARGET_X86)
4497 // Skip instruction prefixes
4502 // Segment overrides
4511 case 0x66: // Operand-Size
4512 case 0x67: // Address-Size
4517 // String REP prefixes
4519 case 0xf2: // REPNE/REPNZ
4531 BYTE opcode = *ip++;
4534 // todo: Can we actually get this result? Doesn't ICorDebug hand out un-patched assembly?
4535 _ASSERTE(!"Hit break opcode!");
4539 // Analyze what we can of the opcode
4544 // Count may have been decremented by prefixes.
4549 BYTE mod = (modrm & 0xC0) >> 6;
4550 BYTE reg = (modrm & 0x38) >> 3;
4551 BYTE rm = (modrm & 0x07);
4555 if ((reg != 2) && (reg != 3) && (reg != 4) && (reg != 5))
4558 // This is not a CALL or JMP instruction, return, unknown.
4560 _ASSERTE(!"Unhandled opcode!");
4565 // Only try to decode registers if we actually have reg sets.
4578 // Get values from the SIB byte
4580 BYTE ss = (*ip & 0xC0) >> 6;
4581 BYTE index = (*ip & 0x38) >> 3;
4582 BYTE base = (*ip & 0x7);
4585 // Finally add in the offset
4630 } // end of 0xFF case
4641 _ASSERTE(!"Unhandled opcode!");
4644 #elif defined(DBG_TARGET_AMD64)
4647 BOOL fContainsPrefix = FALSE;
4649 // Should not happen.
4653 // Skip instruction prefixes
4655 //This "loop" can't be really executed more than once so if CALL can really have more than one prefix we'll crash.
4656 //Some of these prefixes are not allowed for CALL instruction and we should treat them as invalid code.
4657 //It appears that this code was mostly copy/pasted from \NDP\clr\src\Debug\EE\amd64\amd64walker.cpp
4658 //with very minimum fixes.
4663 // Segment overrides
4672 case 0x66: // Operand-Size
4673 case 0x67: // Address-Size
4678 // String REP prefixes
4679 case 0xf2: // REPNE/REPNZ
4682 fContainsPrefix = TRUE;
4685 // REX register extension prefixes
4702 // make sure to set rex to prefix, not *ip because *ip still represents the
4703 // codestream which has a 0xcc in it.
4706 fContainsPrefix = TRUE;
4715 BYTE opcode = *ip++;
4717 // Should not happen.
4722 // Setup rex bits if needed
4729 rex_b = (rex & 0x1); // high bit to modrm r/m field or SIB base field or OPCODE reg field -- Hmm, when which?
4730 rex_x = (rex & 0x2) >> 1; // high bit to sib index field
4731 rex_r = (rex & 0x4) >> 2; // high bit to modrm reg field
4734 // Analyze what we can of the opcode
4741 _ASSERT(modrm != NULL);
4743 BYTE mod = (modrm & 0xC0) >> 6;
4744 BYTE reg = (modrm & 0x38) >> 3;
4745 BYTE rm = (modrm & 0x07);
4747 reg |= (rex_r << 3);
4750 if ((reg < 2) || (reg > 5 && reg < 8) || (reg > 15)) {
4751 // not a valid register for a CALL or BRANCH
4752 _ASSERTE(!"Invalid opcode!");
4759 // See: Tables A-15,16,17 in AMD Dev Manual 3 for information
4760 // about how the ModRM/SIB/REX bytes interact.
4767 if ((rm & 0x07) == 4) // we have an SIB byte following
4770 // Get values from the SIB byte
4773 _ASSERT(sib != NULL);
4775 BYTE base = (sib & 0x07);
4776 base |= (rex_b << 3);
4781 // Finally add in the offset
4785 if ((base & 0x07) == 5)
4802 // Get the value we need from the register.
4805 // Check for RIP-relative addressing mode.
4806 if ((mod == 0) && ((rm & 0x07) == 5))
4808 displace = 6; // 1 byte opcode + 1 byte modrm + 4 byte displacement (signed)
4828 // Displace should be set by one of the cases above
4831 _ASSERTE(!"GetCallInstructionLength() encountered unexpected call instruction");
4835 // Account for the 1 byte prefix (REX or otherwise)
4836 if (fContainsPrefix)
4839 // reg == 4 or 5 means that it is not a CALL, but JMP instruction
4840 // so we will fall back to ASSERT after break
4841 if ((reg != 4) && (reg != 5))
4847 //Near call with the target specified by a 32-bit relative displacement.
4848 //[maybe 1 byte prefix] + [1 byte opcode E8h] + [4 bytes offset]
4849 return 5 + (fContainsPrefix ? 1 : 0);
4855 _ASSERTE(!"Invalid opcode!");
4858 #error Platform not implemented
4862 HRESULT CordbNativeCode::GetSigParserFromFunction(mdToken mdFunction, mdToken *pClass, SigParser &parser, SigParser &methodGenerics)
4864 // mdFunction may be a MemberRef, a MethodDef, or a MethodSpec. We must handle all three cases.
4866 IMetaDataImport* pImport = m_pFunction->GetModule()->GetMetaDataImporter();
4867 RSExtSmartPtr<IMetaDataImport2> pImport2;
4868 IfFailRet(pImport->QueryInterface(IID_IMetaDataImport2, (void**)&pImport2));
4870 if (TypeFromToken(mdFunction) == mdtMemberRef)
4872 PCCOR_SIGNATURE sig = 0;
4874 IfFailRet(pImport->GetMemberRefProps(mdFunction, pClass, NULL, 0, 0, &sig, &sigSize));
4875 parser = SigParser(sig, sigSize);
4877 else if (TypeFromToken(mdFunction) == mdtMethodDef)
4879 PCCOR_SIGNATURE sig = 0;
4881 IfFailRet(pImport->GetMethodProps(mdFunction, pClass, NULL, 0, NULL, NULL, &sig, &sigSize, NULL, NULL));
4882 parser = SigParser(sig, sigSize);
4884 else if (TypeFromToken(mdFunction) == mdtMethodSpec)
4886 // For a method spec, we use GetMethodSpecProps to get the generic singature and the parent token
4887 // (which is a MethodDef token). We'll recurse to get the other properties from the parent token.
4889 PCCOR_SIGNATURE sig = 0;
4891 mdToken parentToken = 0;
4892 IfFailRet(pImport2->GetMethodSpecProps(mdFunction, &parentToken, &sig, &sigSize));
4893 methodGenerics = SigParser(sig, sigSize);
4896 *pClass = parentToken;
4898 return GetSigParserFromFunction(parentToken, pClass, parser, methodGenerics);
4902 // According to ECMA III.3.19, this can never happen.
4903 return E_UNEXPECTED;
4909 HRESULT CordbNativeCode::EnsureReturnValueAllowed(Instantiation *currentInstantiation, mdToken targetClass, SigParser &parser, SigParser &methodGenerics)
4913 IfFailRet(SkipToReturn(parser, &genCount));
4915 return EnsureReturnValueAllowedWorker(currentInstantiation, targetClass, parser, methodGenerics, genCount);
4918 HRESULT CordbNativeCode::EnsureReturnValueAllowedWorker(Instantiation *currentInstantiation, mdToken targetClass, SigParser &parser, SigParser &methodGenerics, ULONG genCount)
4920 // There are a few considerations here:
4921 // 1. Generic instantiations. This is a "Foo<T>", and we need to check if that "Foo"
4922 // fits one of the categories we disallow (such as a struct).
4924 // 3. ValueType - Unsupported this release.
4925 // 4. MVAR - Method generics. We need to get the actual generic type and recursively
4926 // check if we allow that.
4927 // 5. VAR - Class generics. We need to get the actual generic type and recurse.
4929 SigParser original(parser);
4931 CorElementType returnType;
4932 IfFailRet(parser.GetElemType(&returnType));
4933 if (returnType == ELEMENT_TYPE_GENERICINST)
4935 IfFailRet(parser.GetElemType(&returnType));
4937 if (returnType == ELEMENT_TYPE_CLASS)
4940 if (returnType != ELEMENT_TYPE_VALUETYPE)
4941 return META_E_BAD_SIGNATURE;
4943 if (currentInstantiation == NULL)
4944 return S_OK; // We will check again when we have the instantiation.
4946 NewArrayHolder<CordbType*> types;
4948 IfFailRet(CordbJITILFrame::BuildInstantiationForCallsite(GetModule(), types, inst, currentInstantiation, targetClass, SigParser(methodGenerics)));
4950 CordbType *pType = 0;
4951 IfFailRet(CordbType::SigToType(GetModule(), &original, &inst, &pType));
4954 IfFailRet(hr = pType->ReturnedByValue());
4955 if (hr == S_OK) // not S_FALSE
4958 return CORDBG_E_UNSUPPORTED;
4961 if (returnType == ELEMENT_TYPE_VALUETYPE)
4964 CordbType *pType = 0;
4965 IfFailRet(CordbType::SigToType(GetModule(), &original, &inst, &pType));
4967 IfFailRet(hr = pType->ReturnedByValue());
4968 if (hr == S_OK) // not S_FALSE
4971 return CORDBG_E_UNSUPPORTED;
4974 if (returnType == ELEMENT_TYPE_TYPEDBYREF)
4975 return CORDBG_E_UNSUPPORTED;
4977 if (returnType == ELEMENT_TYPE_VOID)
4978 return E_UNEXPECTED;
4980 if (returnType == ELEMENT_TYPE_MVAR)
4982 // Get which generic parameter is referenced.
4984 IfFailRet(parser.GetData(&genParam));
4986 // Grab the calling convention of the method, ensure it's GENERICINST.
4987 ULONG callingConv = 0;
4988 IfFailRet(methodGenerics.GetCallingConvInfo(&callingConv));
4989 if (callingConv != IMAGE_CEE_CS_CALLCONV_GENERICINST)
4990 return META_E_BAD_SIGNATURE;
4992 // Ensure sensible bounds.
4993 SigParser generics(methodGenerics); // Make a copy since operations are destructive.
4995 IfFailRet(generics.GetData(&maxCount));
4996 if (maxCount <= genParam || genParam > 1024)
4997 return META_E_BAD_SIGNATURE;
4999 // Walk to the parameter referenced.
5001 IfFailRet(generics.SkipExactlyOne());
5003 // Now recurse with "generics" at the location to continue parsing.
5004 return EnsureReturnValueAllowedWorker(currentInstantiation, targetClass, generics, methodGenerics, genCount);
5008 if (returnType == ELEMENT_TYPE_VAR)
5010 // Get which type parameter is reference.
5011 ULONG typeParam = 0;
5012 parser.GetData(&typeParam);
5014 // Ensure something reasonable.
5015 if (typeParam > 1024)
5016 return META_E_BAD_SIGNATURE;
5018 // Lookup the containing class's signature so we can get the referenced generic parameter.
5019 IMetaDataImport *pImport = m_pFunction->GetModule()->GetMetaDataImporter();
5020 PCCOR_SIGNATURE sig;
5022 IfFailRet(pImport->GetTypeSpecFromToken(targetClass, &sig, &countSig));
5024 // Enusre the type's typespec is GENERICINST.
5025 SigParser typeParser(sig, countSig);
5027 IfFailRet(typeParser.GetElemType(&et));
5028 if (et != ELEMENT_TYPE_GENERICINST)
5029 return META_E_BAD_SIGNATURE;
5031 // Move to the correct location.
5032 IfFailRet(typeParser.GetElemType(&et));
5033 if (et != ELEMENT_TYPE_VALUETYPE && et != ELEMENT_TYPE_CLASS)
5034 return META_E_BAD_SIGNATURE;
5036 IfFailRet(typeParser.GetToken(NULL));
5038 ULONG totalTypeCount = 0;
5039 IfFailRet(typeParser.GetData(&totalTypeCount));
5040 if (totalTypeCount < typeParam)
5041 return META_E_BAD_SIGNATURE;
5044 IfFailRet(typeParser.SkipExactlyOne());
5046 // This is a temporary workaround for an infinite recursion here. ALL of this code will
5047 // go away when we allow struct return values, but in the mean time this avoids a corner
5048 // case in the type system we haven't solved yet.
5049 IfFailRet(typeParser.PeekElemType(&et));
5050 if (et == ELEMENT_TYPE_VAR)
5053 // Now that typeParser is at the location of the correct generic parameter, recurse.
5054 return EnsureReturnValueAllowedWorker(currentInstantiation, targetClass, typeParser, methodGenerics, genCount);
5057 // Everything else supported
5061 HRESULT CordbNativeCode::SkipToReturn(SigParser &parser, ULONG *genCount)
5063 // Takes a method signature parser (at the beginning of a signature) and skips to the
5067 // Skip calling convention
5069 IfFailRet(parser.GetCallingConvInfo(&uCallConv));
5070 if ((uCallConv == IMAGE_CEE_CS_CALLCONV_FIELD) || (uCallConv == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG))
5071 return META_E_BAD_SIGNATURE;
5073 // Skip type parameter count if function is generic
5074 if (uCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
5075 IfFailRet(parser.GetData(genCount));
5077 // Skip argument count
5078 IfFailRet(parser.GetData(NULL));
5083 HRESULT CordbNativeCode::GetCallSignature(ULONG32 ILoffset, mdToken *pClass, mdToken *pFunction, SigParser &parser, SigParser &generics)
5085 // check if specified IL offset is at a call instruction
5086 CordbILCode *pCode = this->m_pFunction->GetILCode();
5088 ULONG32 fetched = 0;
5089 HRESULT hr = pCode->GetCode(ILoffset, ILoffset+_countof(buffer), _countof(buffer), buffer, &fetched);
5093 else if (fetched != _countof(buffer))
5094 return CORDBG_E_INVALID_OPCODE;
5096 // tail. - fe 14 (ECMA III.2.4)
5097 BYTE instruction = buffer[0];
5098 if (buffer[0] == 0xfe && buffer[1] == 0x14)
5100 // tail call case. We don't allow managed return values for tailcalls.
5101 return CORDBG_E_INVALID_OPCODE;
5104 // call - 28 (ECMA III.3.19)
5105 // callvirt - 6f (ECMA III.4.2)
5106 if (instruction != 0x28 && instruction != 0x6f)
5107 return CORDBG_E_INVALID_OPCODE;
5109 // Now grab the MD token of the call
5110 mdToken mdFunction = 0;
5111 const ULONG32 offset = ILoffset + 1;
5112 hr = pCode->GetCode(offset, offset+sizeof(mdToken), sizeof(mdToken), (BYTE*)&mdFunction, &fetched);
5113 if (FAILED(hr) || fetched != sizeof(mdToken))
5114 return CORDBG_E_INVALID_OPCODE;
5117 *pFunction = mdFunction;
5119 // Convert to a signature parser
5120 return GetSigParserFromFunction(mdFunction, pClass, parser, generics);
5123 HRESULT CordbNativeCode::GetReturnValueLiveOffsetImpl(Instantiation *currentInstantiation, ULONG32 ILoffset, ULONG32 bufferSize, ULONG32 *pFetched, ULONG32 *pOffsets)
5125 if (pFetched == NULL)
5126 return E_INVALIDARG;
5131 // verify that the call target actually returns something we allow
5132 SigParser signature, generics;
5133 mdToken mdClass = 0;
5134 IfFailRet(GetCallSignature(ILoffset, &mdClass, NULL, signature, generics));
5135 IfFailRet(EnsureReturnValueAllowed(currentInstantiation, mdClass, signature, generics));
5137 // now find the native offset
5138 SequencePoints *pSP = GetSequencePoints();
5139 DebuggerILToNativeMap *pMap = pSP->GetCallsiteMapAddr();
5141 for (ULONG32 i = 0; i < pSP->GetCallsiteEntryCount() && pMap; ++i, pMap++)
5143 if (pMap->ilOffset == ILoffset && (pMap->source & ICorDebugInfo::CALL_INSTRUCTION) == ICorDebugInfo::CALL_INSTRUCTION)
5145 // if we have a buffer, fill it in.
5146 if (pOffsets && found < bufferSize)
5148 // Fetch the actual assembly instructions
5149 BYTE nativeBuffer[8];
5151 ULONG32 fetched = 0;
5152 IfFailRet(GetCode(pMap->nativeStartOffset, pMap->nativeStartOffset+_countof(nativeBuffer), _countof(nativeBuffer), nativeBuffer, &fetched));
5156 #if defined(DBG_TARGET_X86) && defined(FEATURE_CORESYSTEM)
5157 // Skip nop sleds on x86 coresystem. The JIT adds these instructions as a security measure,
5158 // and incorrectly reports to us the wrong offset of the call instruction.
5159 const BYTE nop_opcode = 0x90;
5160 while (fetched && nativeBuffer[0] == nop_opcode)
5164 for (int j = 1; j < _countof(nativeBuffer) && nativeBuffer[j] == nop_opcode; ++j)
5167 // We must have at least one skip byte since the outer while ensures it. Thus we always need to reread
5168 // the buffer at the end of this loop.
5169 IfFailRet(GetCode(pMap->nativeStartOffset+skipBytes, pMap->nativeStartOffset+skipBytes+_countof(nativeBuffer), _countof(nativeBuffer), nativeBuffer, &fetched));
5173 // Get the length of the call instruction.
5174 int offset = GetCallInstructionLength(nativeBuffer, fetched);
5176 return E_UNEXPECTED; // Could not decode instruction, this should never happen.
5178 pOffsets[found] = pMap->nativeStartOffset + offset + skipBytes;
5186 *pFetched = found < bufferSize ? found : bufferSize;
5193 if (pOffsets && found > bufferSize)
5199 //-----------------------------------------------------------------------------
5200 // Creates a CordbNativeCode (if it's not already created) and adds it to the
5201 // hash table of CordbNativeCode instances belonging to this module.
5202 // Used by CordbFunction::InitNativeCodeInfo.
5206 // methodToken - the methodDef token of the function this native code belongs to
5207 // methodDesc - the methodDesc for the jitted method
5208 // startAddress - the hot code startAddress for this method
5211 // found or created CordbNativeCode pointer
5212 // Assumptions: methodToken is in the metadata for this module
5213 // methodDesc and startAddress should be consistent for
5214 // a jitted instance of methodToken's method
5215 //-----------------------------------------------------------------------------
5216 CordbNativeCode * CordbModule::LookupOrCreateNativeCode(mdMethodDef methodToken,
5217 VMPTR_MethodDesc methodDesc,
5218 CORDB_ADDRESS startAddress)
5220 INTERNAL_SYNC_API_ENTRY(GetProcess());
5221 _ASSERTE(startAddress != NULL);
5222 _ASSERTE(methodDesc != VMPTR_MethodDesc::NullPtr());
5224 CordbNativeCode * pNativeCode = NULL;
5225 NativeCodeFunctionData codeInfo;
5226 RSLockHolder lockHolder(GetProcess()->GetProcessLock());
5228 // see if we already have this--if not, we'll make an instance, otherwise we'll just return the one we have.
5229 pNativeCode = m_nativeCodeTable.GetBase((UINT_PTR) startAddress);
5231 if (pNativeCode == NULL)
5233 GetProcess()->GetDAC()->GetNativeCodeInfoForAddr(methodDesc, startAddress, &codeInfo);
5235 // We didn't have an instance, so we'll build one and add it to the hash table
5238 "R:CT::RSCreating code w/ ver:0x%x, md:0x%x, nativeStart=0x%08x, nativeSize=0x%08x\n",
5239 codeInfo.encVersion,
5240 VmPtrToCookie(codeInfo.vmNativeCodeMethodDescToken),
5241 codeInfo.m_rgCodeRegions[kHot].pAddress,
5242 codeInfo.m_rgCodeRegions[kHot].cbSize));
5244 // Lookup the function object that this code should be bound to
5245 CordbFunction* pFunction = CordbModule::LookupOrCreateFunction(methodToken, codeInfo.encVersion);
5246 _ASSERTE(pFunction != NULL);
5248 // There are bugs with the on-demand class load performed by CordbFunction in some cases. The old stack
5249 // tracing code avoided them by eagerly loading the parent class so I am following suit
5250 pFunction->InitParentClassOfFunction();
5252 // First, create a new CordbNativeCode instance--we'll need this to make the CordbJITInfo instance
5253 pNativeCode = new (nothrow)CordbNativeCode(pFunction, &codeInfo, codeInfo.isInstantiatedGeneric != 0);
5254 _ASSERTE(pNativeCode != NULL);
5256 m_nativeCodeTable.AddBaseOrThrow(pNativeCode);
5260 } // CordbNativeCode::LookupOrCreateFromJITData
5262 // LoadNativeInfo loads from the left side any native variable info
5265 void CordbNativeCode::LoadNativeInfo()
5267 THROW_IF_NEUTERED(this);
5268 INTERNAL_API_ENTRY(this->GetProcess());
5271 // If we've either never done this before (no info), or we have, but the version number has increased, we
5272 // should try and get a newer version of our JIT info.
5273 if(m_nativeVarData.IsInitialized())
5278 // You can't do this if the function is implemented as part of the Runtime.
5279 if (GetFunction()->IsNativeImpl() == CordbFunction::kNativeOnly)
5281 ThrowHR(CORDBG_E_FUNCTION_NOT_IL);
5283 CordbProcess *pProcess = GetProcess();
5284 // Get everything via the DAC
5285 if (m_fCodeAvailable)
5287 RSLockHolder lockHolder(pProcess->GetProcessLock());
5288 pProcess->GetDAC()->GetNativeCodeSequencePointsAndVarInfo(GetVMNativeCodeMethodDescToken(),
5295 } // CordbNativeCode::LoadNativeInfo