// Find the code manager containing the given address, which might be a return address from a managed function. The // address may be to another managed function, or it may be to an unmanaged function, or it may be to a GC // hijack. The address may also refer to an EEType if we've been called from RhpGetClasslibFunction. If it is // a GC hijack, we will recognize that and use the real return address. static ICodeManager * FindCodeManagerRespectingReturnAddressHijacks(void * address) { RuntimeInstance * pRI = GetRuntimeInstance(); // Try looking up the code manager assuming the address is for code first. This is expected to be most common. ICodeManager * pCodeManager = pRI->FindCodeManagerByAddress(address); if (pCodeManager != NULL) return pCodeManager; // @TODO: CORERT: Do we need to make this work for CoreRT? // Less common, we will look for the address in any of the sections of the module. This is slower, but is // necessary for EEType pointers and jump stubs. Module * pModule = pRI->FindModuleByAddress(address); if (pModule != NULL) return pModule; // Corner-case: The thread might be hijacked -- @TODO: this is a bit brittle because there is no validation that // the hijacked return address from the thread is actually related to place where the caller got the hijack // target. Thread * pCurThread = ThreadStore::GetCurrentThread(); if (pCurThread->IsHijacked() && Thread::IsHijackTarget(address)) { ICodeManager * pCodeManagerForHijack = pRI->FindCodeManagerByAddress(pCurThread->GetHijackedReturnAddress()); ASSERT_MSG(pCodeManagerForHijack != NULL, "expected to find the module for a hijacked return address"); return pCodeManagerForHijack; } return NULL; }
// Find the module containing the given address, which is a return address from a managed function. The // address may be to another managed function, or it may be to an unmanaged function, or it may be to a GC // hijack. The address may also refer to an EEType if we've been called from RhpGetClasslibFunction. If it is // a GC hijack, we will recgonize that and use the real return address, updating the address passed in. static Module * FindModuleRespectingReturnAddressHijacks(void ** pAddress) { RuntimeInstance * pRI = GetRuntimeInstance(); // Try looking up the module assuming the address is for code first. Fall back to a read-only data looukp // if that fails. If we have data indicating that the data case is more common then we can reverse the // order of checks. Finally check read/write data: generic EETypes live there since they need to be fixed // up at runtime to support unification. Module * pModule = pRI->FindModuleByCodeAddress(*pAddress); if (pModule == NULL) { pModule = pRI->FindModuleByReadOnlyDataAddress(*pAddress); if (pModule == NULL) pModule = pRI->FindModuleByDataAddress(*pAddress); if (pModule == NULL) { // Hmmm... we didn't find a managed module for the given PC. We have a return address in unmanaged // code, but it could be because the thread is hijacked for GC suspension. If it is then we should // get the real return address and try again. Thread * pCurThread = ThreadStore::GetCurrentThread(); if (!pCurThread->IsHijacked()) { // The PC isn't in a managed module, and there is no hijack in place, so we have no EH info. return NULL; } // Update the PC passed in to reflect the correct return address. *pAddress = pCurThread->GetHijackedReturnAddress(); pModule = pRI->FindModuleByCodeAddress(*pAddress); } } return pModule; }