Remove always defined FEATURE_CORECLR
[platform/upstream/coreclr.git] / src / vm / proftoeeinterfaceimpl.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //
5 // FILE: ProfToEEInterfaceImpl.cpp
6 //
7 // This module implements the ICorProfilerInfo* interfaces, which allow the 
8 // Profiler to communicate with the EE.  This allows the Profiler DLL to get
9 // access to private EE data structures and other things that should never be
10 // exported outside of the EE.
11 //
12
13 // 
14 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
15 // NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! 
16 //
17 // PLEASE READ!
18 //
19 // There are strict rules for how to implement ICorProfilerInfo* methods.  Please read
20 // https://github.com/dotnet/coreclr/blob/master/Documentation/botr/profilability.md
21 // to understand the rules and why they exist.
22 //
23 // As a reminder, here is a short summary of your responsibilities.  Every PUBLIC
24 // ENTRYPOINT (from profiler to EE) must have:
25 //
26 // - An entrypoint macro at the top (see code:#P2CLRRestrictionsOverview).  Your choices are:
27 //       PROFILER_TO_CLR_ENTRYPOINT_SYNC (typical choice):
28 //          Indicates the method may only be called by the profiler from within
29 //          a callback (from EE to profiler).
30 //       PROFILER_TO_CLR_ENTRYPOINT_CALLABLE_ON_INIT_ONLY
31 //          Even more restrictive, this indicates the method may only be called
32 //          from within the Initialize() callback
33 //       PROFILER_TO_CLR_ENTRYPOINT_ASYNC
34 //          Indicates this method may be called anytime.
35 //          THIS IS DANGEROUS.  PLEASE READ ABOVE DOC FOR GUIDANCE ON HOW TO SAFELY
36 //          CODE AN ASYNCHRONOUS METHOD.
37 //   You may use variants of these macros ending in _EX that accept bit flags (see
38 //   code:ProfToClrEntrypointFlags) if you need to specify additional parameters to how
39 //   the entrypoint should behave, though typically you can omit the flags and the
40 //   default (kP2EENone) will be used.
41 //
42 // - A complete contract block with comments over every contract choice.  Wherever
43 //   possible, use the preferred contracts (if not possible, you must comment why):
44 //       NOTHROW
45 //       GC_NOTRIGGER
46 //       MODE_ANY
47 //       CANNOT_TAKE_LOCK
48 //       SO_NOT_MAINLINE
49 //       (EE_THREAD_(NOT)_REQUIRED are unenforced and are thus optional.  If you wish
50 //       to specify these, EE_THREAD_NOT_REQUIRED is preferred.)
51 //   Note that the preferred contracts in this file are DIFFERENT than the preferred
52 //   contracts for eetoprofinterfaceimpl.cpp.
53 //
54 // Private helper functions in this file do not have the same preferred contracts as
55 // public entrypoints, and they should be contracted following the same guidelines
56 // as per the rest of the EE.
57 //
58 // NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! 
59 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
60 //
61 //
62 // #P2CLRRestrictionsOverview
63 // 
64 // The public ICorProfilerInfo(N) functions below have different restrictions on when
65 // they're allowed to be called. Listed roughly in order from most to least restrictive:
66 //     * PROFILER_TO_CLR_ENTRYPOINT_CALLABLE_ON_INIT_ONLY: Functions that are only
67 //         allowed to be called while the profiler is initializing on startup, from
68 //         inside the profiler's ICorProfilerCallback::Initialize method
69 //     * PROFILER_TO_CLR_ENTRYPOINT_SYNC: Functions that may be called from within any of
70 //         the profiler's callbacks, or anytime from a thread created by the profiler.
71 //         These functions may only be called by profilers loaded on startup
72 //     * PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach): Same as above,
73 //         except these may be called by startup AND attaching profilers.
74 //     * PROFILER_TO_CLR_ENTRYPOINT_ASYNC: Functions that may be called at any time and
75 //         from any thread by a profiler loaded on startup
76 //     * PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach): Same as above,
77 //         except these may be called by startup AND attaching profilers.
78 //         
79 //  The above restrictions are lifted for certain tests that run with these environment
80 //  variables set. (These are only available on DEBUG builds--including chk--not retail
81 //  builds.)
82 //    * COMPlus_TestOnlyEnableSlowELTHooks:
83 //         * If nonzero, then on startup the runtime will act as if a profiler was loaded
84 //             on startup and requested ELT slow-path (even if no profiler is loaded on
85 //             startup). This will also allow the SetEnterLeaveFunctionHooks(2) info
86 //             functions to be called outside of Initialize(). If a profiler later
87 //             attaches and calls these functions, then the slow-path wrapper will call
88 //             into the profiler's ELT hooks.
89 //    * COMPlus_TestOnlyEnableObjectAllocatedHook:
90 //         * If nonzero, then on startup the runtime will act as if a profiler was loaded
91 //             on startup and requested ObjectAllocated callback (even if no profiler is loaded
92 //             on startup). If a profiler later attaches and calls these functions, then the 
93 //             ObjectAllocated notifications will call into the profiler's ObjectAllocated callback.
94 //    * COMPlus_TestOnlyEnableICorProfilerInfo:
95 //         * If nonzero, then attaching profilers allows to call ICorProfilerInfo inteface, 
96 //             which would otherwise be disallowed for attaching profilers
97 //    * COMPlus_TestOnlyAllowedEventMask
98 //         * If a profiler needs to work around the restrictions of either
99 //             COR_PRF_ALLOWABLE_AFTER_ATTACH or COR_PRF_MONITOR_IMMUTABLE it may set
100 //             this environment variable. Its value should be a bitmask containing all
101 //             the flags that are:
102 //             * normally immutable or disallowed after attach, AND
103 //             * that the test plans to set after startup and / or by an attaching
104 //                 profiler.
105 //     
106 //
107
108 // 
109 // ======================================================================================
110
111 #include "common.h"
112 #include <posterror.h>
113 #include "proftoeeinterfaceimpl.h"
114 #include "proftoeeinterfaceimpl.inl"
115 #include "dllimport.h"
116 #include "threads.h"
117 #include "method.hpp"
118 #include "vars.hpp"
119 #include "dbginterface.h"
120 #include "corprof.h"
121 #include "class.h"
122 #include "object.h"
123 #include "ceegen.h"
124 #include "eeconfig.h"
125 #include "generics.h"
126 #include "gcinfo.h"
127 #include "safemath.h"
128 #include "threadsuspend.h"
129 #include "inlinetracking.h"
130
131 #ifdef PROFILING_SUPPORTED
132 #include "profilinghelper.h"
133 #include "profilinghelper.inl"
134 #include "eetoprofinterfaceimpl.inl"
135 #include "profilingenumerators.h"
136 #endif
137
138 #include "profdetach.h"
139
140 #include "metadataexports.h"
141
142 //---------------------------------------------------------------------------------------
143 // Helpers
144
145 // An OR'd combination of these flags may be specified in the _EX entrypoint macros to
146 // customize the behavior.
147 enum ProfToClrEntrypointFlags
148 {
149     // Just use the default behavior (this one is used if the non-_EX entrypoint macro is
150     // specified without any flags).
151     kP2EENone                       = 0x00000000,
152     
153     // By default, Info functions are not allowed to be used by an attaching profiler. 
154     // Specify this flag to override the default.
155     kP2EEAllowableAfterAttach       = 0x00000001,
156
157     // This info method has a GC_TRIGGERS contract.  Whereas contracts are debug-only,
158     // this flag is used in retail builds as well.
159     kP2EETriggers                   = 0x00000002,
160 };
161
162 // Default versions of the entrypoint macros use kP2EENone if no
163 // ProfToClrEntrypointFlags are specified
164
165 #define PROFILER_TO_CLR_ENTRYPOINT_ASYNC(logParams)             \
166     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EENone, logParams)
167
168 #define PROFILER_TO_CLR_ENTRYPOINT_SYNC(logParams)              \
169     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EENone, logParams)
170
171 // ASYNC entrypoints log and ensure an attaching profiler isn't making a call that's
172 // only supported by startup profilers.
173
174 #define CHECK_IF_ATTACHING_PROFILER_IS_ALLOWED_HELPER(p2eeFlags)                           \
175     do                                                                                     \
176     {                                                                                      \
177         if ((((p2eeFlags) & kP2EEAllowableAfterAttach) == 0) &&                            \
178             (g_profControlBlock.pProfInterface->IsLoadedViaAttach()))                      \
179         {                                                                                  \
180             LOG((LF_CORPROF,                                                               \
181                  LL_ERROR,                                                                 \
182                  "**PROF: ERROR: Returning CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER "  \
183                  "due to a call illegally made by an attaching profiler \n"));             \
184             return CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER;                           \
185         }                                                                                  \
186     } while(0)
187
188 #ifdef _DEBUG
189
190 #define CHECK_IF_ATTACHING_PROFILER_IS_ALLOWED(p2eeFlags)                           \
191     do                                                                              \
192     {                                                                               \
193         if (!((&g_profControlBlock)->fTestOnlyEnableICorProfilerInfo))              \
194         {                                                                           \
195             CHECK_IF_ATTACHING_PROFILER_IS_ALLOWED_HELPER(p2eeFlags);               \
196         }                                                                           \
197     } while(0)
198
199
200
201 #else  //_DEBUG
202
203 #define CHECK_IF_ATTACHING_PROFILER_IS_ALLOWED(p2eeFlags)                           \
204     do                                                                              \
205     {                                                                               \
206         CHECK_IF_ATTACHING_PROFILER_IS_ALLOWED_HELPER(p2eeFlags);                   \
207     } while(0)
208
209 #endif //_DEBUG
210
211 #define PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(p2eeFlags, logParams)                           \
212     do                                                                                      \
213     {                                                                                       \
214         INCONTRACT(AssertTriggersContract(((p2eeFlags) & kP2EETriggers)));                  \
215         _ASSERTE(g_profControlBlock.curProfStatus.Get() != kProfStatusNone);                \
216         LOG(logParams);                                                                     \
217         /* If profiler was neutered, disallow call */                                       \
218         if (g_profControlBlock.curProfStatus.Get() == kProfStatusDetaching)                 \
219         {                                                                                   \
220             LOG((LF_CORPROF,                                                                \
221                  LL_ERROR,                                                                  \
222                  "**PROF: ERROR: Returning CORPROF_E_PROFILER_DETACHING "                   \
223                  "due to a post-neutered profiler call\n"));                                \
224             return CORPROF_E_PROFILER_DETACHING;                                            \
225         }                                                                                   \
226         CHECK_IF_ATTACHING_PROFILER_IS_ALLOWED(p2eeFlags);                                  \
227     } while(0)
228
229 // SYNC entrypoints must ensure the current EE Thread shows evidence that we're
230 // inside a callback.  If there's no EE Thread, then we automatically "pass"
231 // the check, and the SYNC call is allowed.
232 #define PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(p2eeFlags, logParams)                    \
233     do                                                                              \
234     {                                                                               \
235         PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(p2eeFlags, logParams);                  \
236         DWORD __dwExpectedCallbackState = COR_PRF_CALLBACKSTATE_INCALLBACK;         \
237         if (((p2eeFlags) & kP2EETriggers) != 0)                                     \
238         {                                                                           \
239             __dwExpectedCallbackState |= COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE;   \
240         }                                                                           \
241         if (!AreCallbackStateFlagsSet(__dwExpectedCallbackState))                   \
242         {                                                                           \
243             LOG((LF_CORPROF,                                                        \
244                  LL_ERROR,                                                          \
245                  "**PROF: ERROR: Returning CORPROF_E_UNSUPPORTED_CALL_SEQUENCE "    \
246                  "due to illegal asynchronous profiler call\n"));                   \
247             return CORPROF_E_UNSUPPORTED_CALL_SEQUENCE;                             \
248         }                                                                           \
249     } while(0)
250
251 // INIT_ONLY entrypoints must ensure we're executing inside the profiler's
252 // Initialize() implementation on startup (attach init doesn't count!).
253 #define PROFILER_TO_CLR_ENTRYPOINT_CALLABLE_ON_INIT_ONLY(logParams)                             \
254     do                                                                                          \
255     {                                                                                           \
256         PROFILER_TO_CLR_ENTRYPOINT_ASYNC(logParams);                                            \
257         if (g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForStartupLoad &&  \
258             g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForAttachLoad)     \
259         {                                                                                       \
260             return CORPROF_E_CALL_ONLY_FROM_INIT;                                               \
261         }                                                                                       \
262     } while(0)
263
264 // This macro is used to ensure that the current thread is not in a forbid
265 // suspend region.   Some methods are allowed to be called asynchronously,
266 // but some of them call JIT functions that take a reader lock.  So we need to ensure
267 // the current thread hasn't been hijacked by a profiler while it was holding the writer lock.
268 // Checking the ForbidSuspendThread region is a sufficient test for this
269 #define FAIL_IF_IN_FORBID_SUSPEND_REGION()                                  \
270     do                                                                      \
271     {                                                                       \
272         Thread * __pThread = GetThreadNULLOk();                             \
273         if ((__pThread != NULL) && (__pThread->IsInForbidSuspendRegion()))  \
274         {                                                                   \
275         return CORPROF_E_ASYNCHRONOUS_UNSAFE;                               \
276         }                                                                   \
277     } while(0)
278     
279 //
280 // This type is an overlay onto the exported type COR_PRF_FRAME_INFO.
281 // The first four fields *must* line up with the same fields in the
282 // exported type.  After that, we can add to the end as we wish.
283 //
284 typedef struct _COR_PRF_FRAME_INFO_INTERNAL {
285     USHORT size;
286     USHORT version;
287     FunctionID funcID;
288     UINT_PTR IP;
289     void *extraArg;
290     LPVOID thisArg;
291 } COR_PRF_FRAME_INFO_INTERNAL, *PCOR_PRF_FRAME_INFO_INTERNAL;
292
293 //
294 // After we ship a product with a certain struct type for COR_PRF_FRAME_INFO_INTERNAL
295 // we have that as a version.  If we change that in a later product, we can increment
296 // the counter below and then we can properly do versioning.
297 //
298 #define COR_PRF_FRAME_INFO_INTERNAL_CURRENT_VERSION 1
299
300
301 //---------------------------------------------------------------------------------------
302 //
303 // Converts TypeHandle to a ClassID
304 //
305 // Arguments:
306 //      th - TypeHandle to convert
307 //
308 // Return Value:
309 //      Requested ClassID.
310 //
311
312 ClassID TypeHandleToClassID(TypeHandle th)
313 {
314     WRAPPER_NO_CONTRACT;
315     return reinterpret_cast<ClassID> (th.AsPtr());
316 }
317
318 //---------------------------------------------------------------------------------------
319 //
320 // Converts TypeHandle for a non-generic type to a ClassID
321 //
322 // Arguments:
323 //      th - TypeHandle to convert
324 //
325 // Return Value:
326 //      Requested ClassID.  NULL if th represents a generic type
327 //
328 #ifdef PROFILING_SUPPORTED
329
330 static ClassID NonGenericTypeHandleToClassID(TypeHandle th)
331 {
332     CONTRACTL
333     {
334         SO_NOT_MAINLINE;
335         NOTHROW;
336         GC_NOTRIGGER;
337         MODE_ANY;
338     } CONTRACTL_END;
339     
340     if ((!th.IsNull()) && (th.HasInstantiation()))
341 {
342         return NULL;
343 }
344
345     return TypeHandleToClassID(th);
346 }
347
348 //---------------------------------------------------------------------------------------
349 //
350 // Converts MethodDesc * to FunctionID
351 //
352 // Arguments:
353 //      pMD - MethodDesc * to convert
354 //
355 // Return Value:
356 //      Requested FunctionID
357 //
358
359 static FunctionID MethodDescToFunctionID(MethodDesc * pMD)
360 {
361     LIMITED_METHOD_CONTRACT;
362     return reinterpret_cast< FunctionID > (pMD);
363 }
364
365 #endif
366
367 //---------------------------------------------------------------------------------------
368 //
369 // Converts FunctionID to MethodDesc *
370 //
371 // Arguments:
372 //      functionID - FunctionID to convert
373 //
374 // Return Value:
375 //      MethodDesc * requested
376 //
377
378 MethodDesc *FunctionIdToMethodDesc(FunctionID functionID)
379 {
380     LIMITED_METHOD_CONTRACT;
381     
382     MethodDesc *pMethodDesc;
383
384     pMethodDesc = reinterpret_cast< MethodDesc* >(functionID);
385
386     _ASSERTE(pMethodDesc != NULL);
387     return pMethodDesc;
388 }
389
390 // (See comments for ArrayKindFromTypeHandle below.)
391 typedef enum
392 {
393     ARRAY_KIND_TYPEDESC,        // Normal, garden-variety typedesc array
394     ARRAY_KIND_METHODTABLE,  // Weirdo array with its own unshared methodtable (e.g., System.Object[])
395     ARRAY_KIND_NOTARRAY,       // Not an array
396 } ARRAY_KIND;
397
398 //---------------------------------------------------------------------------------------
399 //
400 // A couple Info calls need to understand what constitutes an "array", and what
401 // kinds of arrays there are.  ArrayKindFromTypeHandle tries to put some of this
402 // knowledge in a single place
403 //
404 // Arguments:
405 //      th - TypeHandle to inspect
406 //
407 // Return Value:
408 //      ARRAY_KIND describing th
409 //
410
411 inline ARRAY_KIND ArrayKindFromTypeHandle(TypeHandle th)
412 {
413     LIMITED_METHOD_CONTRACT;
414
415     if (th.IsArray())
416     {
417         return ARRAY_KIND_TYPEDESC;
418     }
419
420     if (!th.IsTypeDesc() && th.GetMethodTable()->IsArray())
421     {
422         return ARRAY_KIND_METHODTABLE;
423     }
424
425     return ARRAY_KIND_NOTARRAY;
426 }
427
428 #ifdef PROFILING_SUPPORTED
429
430 //---------------------------------------------------------------------------------------
431 // ModuleILHeap IUnknown implementation
432 //
433 // Function headers unnecessary, as MSDN adequately documents IUnknown
434 //
435
436 ULONG ModuleILHeap::AddRef()
437 {
438     // Lifetime of this object is controlled entirely by the CLR.  This
439     // is created on first request, and is automatically destroyed when
440     // the profiler is detached.
441     return 1;
442 }
443
444
445 ULONG ModuleILHeap::Release()
446 {
447     // Lifetime of this object is controlled entirely by the CLR.  This
448     // is created on first request, and is automatically destroyed when
449     // the profiler is detached.
450     return 1;
451 }
452
453
454 HRESULT ModuleILHeap::QueryInterface(REFIID riid, void ** pp)
455 {
456     HRESULT     hr = S_OK;
457
458     if (pp == NULL)
459     {
460         return E_POINTER;
461     }
462
463     *pp = 0;
464     if (riid == IID_IUnknown)
465     {
466         *pp = static_cast<IUnknown *>(this);
467     }
468     else if (riid == IID_IMethodMalloc)
469     {
470         *pp = static_cast<IMethodMalloc *>(this);
471     }
472     else
473     {
474         hr = E_NOINTERFACE;
475     }
476
477     if (hr == S_OK)
478     {
479         // CLR manages lifetime of this object, but in case that changes (or
480         // this code gets copied/pasted elsewhere), we'll still AddRef here so
481         // QI remains a good citizen either way.
482         AddRef();
483     }
484     return hr;
485 }
486
487 //---------------------------------------------------------------------------------------
488 // Profiler entrypoint to allocate space from this module's heap.
489 //
490 // Arguments
491 //      cb - size in bytes of allocation request
492 //
493 // Return value
494 //      pointer to allocated memory, or NULL if there was an error
495
496 void * STDMETHODCALLTYPE ModuleILHeap::Alloc(ULONG cb)
497 {
498     CONTRACTL
499     {
500         // Yay!
501         NOTHROW;
502     
503         // (see GC_TRIGGERS comment below)
504         CAN_TAKE_LOCK;
505
506         // Allocations using loader heaps below enter a critsec, which switches
507         // to preemptive, which is effectively a GC trigger
508         GC_TRIGGERS;
509
510         // Yay!
511         MODE_ANY;
512
513         SO_NOT_MAINLINE;
514     } 
515     CONTRACTL_END;
516
517     LOG((LF_CORPROF, LL_INFO1000, "**PROF: ModuleILHeap::Alloc 0x%08xp.\n", cb));
518
519     if (cb == 0)
520     {
521         return NULL;
522     }
523
524     return new (nothrow) BYTE[cb];
525 }
526
527 //---------------------------------------------------------------------------------------
528 // The one and only instance of the IL heap
529
530 ModuleILHeap ModuleILHeap::s_Heap;
531
532 //---------------------------------------------------------------------------------------
533 // Implementation of ProfToEEInterfaceImpl's IUnknown
534
535 //
536 // The VM controls the lifetime of ProfToEEInterfaceImpl, not the
537 // profiler.  We'll automatically take care of cleanup when profilers
538 // unload and detach.
539 //
540
541 ULONG STDMETHODCALLTYPE ProfToEEInterfaceImpl::AddRef()
542     {
543     LIMITED_METHOD_CONTRACT;
544     return 1; 
545 }
546
547 ULONG STDMETHODCALLTYPE ProfToEEInterfaceImpl::Release()
548 {
549     LIMITED_METHOD_CONTRACT;
550     return 1; 
551 }
552
553 COM_METHOD ProfToEEInterfaceImpl::QueryInterface(REFIID id, void ** pInterface)
554 {
555     if (pInterface == NULL)
556     {
557         return E_POINTER;
558     }
559
560     if (id == IID_ICorProfilerInfo)
561     {
562         *pInterface = static_cast<ICorProfilerInfo *>(this);
563     }
564     else if (id == IID_ICorProfilerInfo2)
565     {
566         *pInterface = static_cast<ICorProfilerInfo2 *>(this);
567     }
568     else if (id == IID_ICorProfilerInfo3)
569     {
570         *pInterface = static_cast<ICorProfilerInfo3 *>(this);
571     }
572     else if (id == IID_ICorProfilerInfo4)
573     {
574         *pInterface = static_cast<ICorProfilerInfo4 *>(this);
575     }
576     else if (id == IID_ICorProfilerInfo5)
577     {
578         *pInterface = static_cast<ICorProfilerInfo5 *>(this);
579     }
580     else if (id == IID_ICorProfilerInfo6)
581     {
582         *pInterface = static_cast<ICorProfilerInfo6 *>(this);
583     }
584     else if (id == IID_ICorProfilerInfo7)
585     {
586         *pInterface = static_cast<ICorProfilerInfo7 *>(this);
587     }
588     else if (id == IID_ICorProfilerInfo8)
589     {
590         *pInterface = static_cast<ICorProfilerInfo8 *>(this);
591     }
592     else if (id == IID_IUnknown)
593     {
594         *pInterface = static_cast<IUnknown *>(static_cast<ICorProfilerInfo *>(this));
595     }
596     else
597     {
598         *pInterface = NULL;
599         return E_NOINTERFACE;
600     }
601
602     // CLR manages lifetime of this object, but in case that changes (or
603     // this code gets copied/pasted elsewhere), we'll still AddRef here so
604     // QI remains a good citizen either way.
605     AddRef();
606
607     return S_OK;
608 }
609 #endif // PROFILING_SUPPORTED
610
611 //---------------------------------------------------------------------------------------
612 //
613 // GC-related helpers.  These are called from elsewhere in the EE to determine profiler
614 // state, and to update the profiling API with info from the GC.
615 //
616
617 //---------------------------------------------------------------------------------------
618 //
619 // ProfilerObjectAllocatedCallback is called if a profiler is attached, requesting
620 // ObjectAllocated callbacks.
621 //
622 // Arguments:
623 //      objref - Reference to newly-allocated object
624 //      classId - ClassID of newly-allocated object
625 //
626
627 void __stdcall ProfilerObjectAllocatedCallback(OBJECTREF objref, ClassID classId)
628 {
629     CONTRACTL 
630 {
631         THROWS;
632         GC_TRIGGERS;
633         MODE_COOPERATIVE;
634     } 
635     CONTRACTL_END;
636     
637     TypeHandle th = OBJECTREFToObject(objref)->GetTypeHandle();
638
639     // WARNING: objref can move as a result of the ObjectAllocated() call below if
640     // the profiler causes a GC, so any operations on the objref should occur above
641     // this comment (unless you're prepared to add a GCPROTECT around the objref).  
642
643 #ifdef PROFILING_SUPPORTED
644     // Notify the profiler of the allocation
645
646     {
647         BEGIN_PIN_PROFILER(CORProfilerTrackAllocations());
648         // Note that for generic code we always return uninstantiated ClassIDs and FunctionIDs.
649         // Thus we strip any instantiations of the ClassID (which is really a type handle) here.
650         g_profControlBlock.pProfInterface->ObjectAllocated(
651                 (ObjectID) OBJECTREFToObject(objref), 
652                 classId);
653         END_PIN_PROFILER();
654     }
655 #endif // PROFILING_SUPPORTED
656 }
657
658 //---------------------------------------------------------------------------------------
659 //
660 // Wrapper around the GC Started callback
661 //
662 // Arguments:
663 //      generation - Generation being collected
664 //      induced - Was this GC induced by GC.Collect?
665 //
666
667 void __stdcall GarbageCollectionStartedCallback(int generation, BOOL induced)
668 {
669     CONTRACTL 
670     {
671         NOTHROW;
672         GC_NOTRIGGER;
673         MODE_ANY; // can be called even on GC threads
674     } 
675     CONTRACTL_END;
676
677 #ifdef PROFILING_SUPPORTED
678     //
679     // Mark that we are starting a GC.  This will allow profilers to do limited object inspection
680     // during callbacks that occur while a GC is happening.
681     //
682     g_profControlBlock.fGCInProgress = TRUE;
683
684     // Notify the profiler of start of the collection
685     {
686         BEGIN_PIN_PROFILER(CORProfilerTrackGC());
687         BOOL generationCollected[COR_PRF_GC_LARGE_OBJECT_HEAP+1];
688         if (generation == COR_PRF_GC_GEN_2)
689             generation = COR_PRF_GC_LARGE_OBJECT_HEAP;
690         for (int gen = 0; gen <= COR_PRF_GC_LARGE_OBJECT_HEAP; gen++)
691             generationCollected[gen] = gen <= generation;
692
693         g_profControlBlock.pProfInterface->GarbageCollectionStarted(
694             COR_PRF_GC_LARGE_OBJECT_HEAP+1, 
695             generationCollected, 
696             induced ? COR_PRF_GC_INDUCED : COR_PRF_GC_OTHER);
697         END_PIN_PROFILER();
698     }
699 #endif // PROFILING_SUPPORTED
700 }
701
702 //---------------------------------------------------------------------------------------
703 //
704 // Wrapper around the GC Finished callback
705 //
706
707 void __stdcall GarbageCollectionFinishedCallback()
708 {
709     CONTRACTL 
710     {
711         NOTHROW;
712         GC_NOTRIGGER;
713         MODE_ANY; // can be called even on GC threads        
714     } 
715     CONTRACTL_END;
716
717 #ifdef PROFILING_SUPPORTED
718     // Notify the profiler of end of the collection
719     {
720         BEGIN_PIN_PROFILER(CORProfilerTrackGC());
721         g_profControlBlock.pProfInterface->GarbageCollectionFinished();
722         END_PIN_PROFILER();
723     }
724
725     // Mark that GC is finished.
726     g_profControlBlock.fGCInProgress = FALSE;
727 #endif // PROFILING_SUPPORTED
728 }
729
730 #ifdef PROFILING_SUPPORTED
731 //---------------------------------------------------------------------------------------
732 //
733 // Describes a GC generation by number and address range
734 //
735
736 struct GenerationDesc
737 {
738     int generation;
739     BYTE *rangeStart;
740     BYTE *rangeEnd;
741     BYTE *rangeEndReserved;
742 };
743
744 struct GenerationTable
745 {
746     ULONG count;
747     ULONG capacity;
748     static const ULONG defaultCapacity = 4; // that's the minimum for 3 generation plus the large object heap
749     GenerationTable *prev;
750     GenerationDesc *genDescTable;
751 #ifdef  _DEBUG
752     ULONG magic;
753 #define GENERATION_TABLE_MAGIC 0x34781256
754 #define GENERATION_TABLE_BAD_MAGIC 0x55aa55aa
755 #endif
756 };
757
758
759 //---------------------------------------------------------------------------------------
760 //
761 // This is a callback used by the GC when we call GCHeapUtilities::DiagDescrGenerations
762 // (from UpdateGenerationBounds() below).  The GC gives us generation information through
763 // this callback, which we use to update the GenerationDesc in the corresponding
764 // GenerationTable
765 //
766 // Arguments:
767 //      context - The containing GenerationTable
768 //      generation - Generation number
769 //      rangeStart - Address where generation starts
770 //      rangeEnd - Address where generation ends
771 //      rangeEndReserved - Address where generation reserved space ends
772 //
773
774 // static
775 static void GenWalkFunc(void * context,
776                         int generation, 
777                         BYTE * rangeStart, 
778                         BYTE * rangeEnd,
779                         BYTE * rangeEndReserved)
780 {
781     CONTRACT_VOID
782     {
783         NOTHROW;
784         GC_NOTRIGGER;
785         MODE_ANY; // can be called even on GC threads        
786         PRECONDITION(CheckPointer(context));
787         PRECONDITION(0 <= generation && generation <= 3);
788         PRECONDITION(CheckPointer(rangeStart));
789         PRECONDITION(CheckPointer(rangeEnd));
790         PRECONDITION(CheckPointer(rangeEndReserved));
791     } CONTRACT_END;
792
793     GenerationTable *generationTable = (GenerationTable *)context;
794
795     _ASSERTE(generationTable->magic == GENERATION_TABLE_MAGIC);
796
797     ULONG count = generationTable->count;
798     if (count >= generationTable->capacity)
799     {
800         ULONG newCapacity = generationTable->capacity == 0 ? GenerationTable::defaultCapacity : generationTable->capacity * 2;
801         GenerationDesc *newGenDescTable = new (nothrow) GenerationDesc[newCapacity];
802         if (newGenDescTable == NULL)
803         {
804             // if we can't allocate a bigger table, we'll have to ignore this call
805             RETURN;
806         }
807         memcpy(newGenDescTable, generationTable->genDescTable, sizeof(generationTable->genDescTable[0]) * generationTable->count);
808         delete[] generationTable->genDescTable;
809         generationTable->genDescTable = newGenDescTable;
810         generationTable->capacity = newCapacity;
811     }
812     _ASSERTE(count < generationTable->capacity);
813
814     GenerationDesc *genDescTable = generationTable->genDescTable;
815
816     genDescTable[count].generation = generation;
817     genDescTable[count].rangeStart = rangeStart;
818     genDescTable[count].rangeEnd = rangeEnd;
819     genDescTable[count].rangeEndReserved = rangeEndReserved;
820
821     generationTable->count = count + 1;
822 }
823
824 // This is the table of generation bounds updated by the gc 
825 // and read by the profiler. So this is a single writer,
826 // multiple readers scenario.
827 static GenerationTable *s_currentGenerationTable;
828
829 // The generation table is updated atomically by replacing the
830 // pointer to it. The only tricky part is knowing when
831 // the old table can be deleted.
832 static Volatile<LONG> s_generationTableLock;
833
834 // This is just so we can assert there's a single writer
835 #ifdef  ENABLE_CONTRACTS
836 static Volatile<LONG> s_generationTableWriterCount;
837 #endif
838 #endif // PROFILING_SUPPORTED
839
840 //---------------------------------------------------------------------------------------
841 //
842 // This is called from the gc to push a new set of generation bounds
843 //
844
845 void __stdcall UpdateGenerationBounds()
846 {
847     CONTRACT_VOID
848     {
849         NOTHROW;
850         GC_NOTRIGGER;
851         MODE_ANY; // can be called even on GC threads        
852 #ifdef PROFILING_SUPPORTED
853         PRECONDITION(FastInterlockIncrement(&s_generationTableWriterCount) == 1);
854         POSTCONDITION(FastInterlockDecrement(&s_generationTableWriterCount) == 0);
855 #endif // PROFILING_SUPPORTED
856     } CONTRACT_END;
857
858 #ifdef PROFILING_SUPPORTED
859     // Notify the profiler of start of the collection
860     if (CORProfilerTrackGC())
861     {
862         // generate a new generation table
863         GenerationTable *newGenerationTable = new (nothrow) GenerationTable();
864         if (newGenerationTable == NULL)
865             RETURN;
866         newGenerationTable->count = 0;
867         newGenerationTable->capacity = GenerationTable::defaultCapacity;
868         // if there is already a current table, use its count as a guess for the capacity
869         if (s_currentGenerationTable != NULL)
870             newGenerationTable->capacity = s_currentGenerationTable->count;
871         newGenerationTable->prev = NULL;
872         newGenerationTable->genDescTable = new (nothrow) GenerationDesc[newGenerationTable->capacity];
873         if (newGenerationTable->genDescTable == NULL)
874             newGenerationTable->capacity = 0;
875
876 #ifdef  _DEBUG
877         newGenerationTable->magic = GENERATION_TABLE_MAGIC;
878 #endif
879         // fill in the values by calling back into the gc, which will report
880         // the ranges by calling GenWalkFunc for each one
881         IGCHeap *hp = GCHeapUtilities::GetGCHeap();
882         hp->DiagDescrGenerations(GenWalkFunc, newGenerationTable);
883
884         // remember the old table and plug in the new one
885         GenerationTable *oldGenerationTable = s_currentGenerationTable;
886         s_currentGenerationTable = newGenerationTable;
887
888         // WARNING: tricky code!
889         //
890         // We sample the generation table lock *after* plugging in the new table
891         // We do so using an interlocked operation so the cpu can't reorder
892         // the write to the s_currentGenerationTable with the increment.
893         // If the interlocked increment returns 1, we know nobody can be using
894         // the old table (readers increment the lock before using the table,
895         // and decrement it afterwards). Any new readers coming in
896         // will use the new table. So it's safe to delete the old
897         // table.
898         // On the other hand, if the interlocked increment returns
899         // something other than one, we put the old table on a list
900         // dangling off of the new one. Next time around, we'll try again
901         // deleting any old tables.
902         if (FastInterlockIncrement(&s_generationTableLock) == 1)
903         {
904             // We know nobody can be using any of the old tables
905             while (oldGenerationTable != NULL)
906             {
907                 _ASSERTE(oldGenerationTable->magic == GENERATION_TABLE_MAGIC);
908 #ifdef  _DEBUG
909                 oldGenerationTable->magic = GENERATION_TABLE_BAD_MAGIC;
910 #endif
911                 GenerationTable *temp = oldGenerationTable;
912                 oldGenerationTable = oldGenerationTable->prev;
913                 delete[] temp->genDescTable;
914                 delete temp;
915             }
916         }
917         else
918         {
919             // put the old table on a list
920             newGenerationTable->prev = oldGenerationTable;
921         }
922         FastInterlockDecrement(&s_generationTableLock);
923     }
924 #endif // PROFILING_SUPPORTED
925     RETURN;
926 }
927
928 #ifdef PROFILING_SUPPORTED
929
930 //---------------------------------------------------------------------------------------
931 //
932 // Determines whether we are in a window to allow object inspection.
933 //
934 // Return Value:
935 //      Returns S_OK if we can determine that we are in a window to allow object
936 //      inspection.  Otherwise a failure HRESULT is returned
937 //
938
939 HRESULT AllowObjectInspection()
940 {
941     CONTRACTL
942     {
943         NOTHROW;
944         GC_NOTRIGGER;
945         MODE_ANY; // tests for preemptive mode dynamically as its main function so contract enforcement is not appropriate
946     } 
947     CONTRACTL_END;
948
949     //
950     // Check first to see if we are in the process of doing a GC and presume that the profiler
951     // is making this object inspection from the same thread that notified of a valid ObjectID.
952     //
953     if (g_profControlBlock.fGCInProgress)
954     {
955         return S_OK;
956     }
957
958     //
959     // Thus we must have a managed thread, and it must be in coop mode.
960     // (That will also guarantee we're in a callback).
961     //
962     Thread * pThread = GetThreadNULLOk();
963
964     if (pThread == NULL)
965     {
966         return CORPROF_E_NOT_MANAGED_THREAD;
967     }
968
969     // Note this is why we don't enforce the contract of being in cooperative mode the whole point
970     // is that clients of this fellow want to return a robust error if not cooperative
971     // so technically they are mode_any although the only true preemptive support they offer
972     // is graceful failure in that case
973     if (!pThread->PreemptiveGCDisabled())
974     {
975         return CORPROF_E_UNSUPPORTED_CALL_SEQUENCE;
976     }
977
978     return S_OK;
979 }
980
981 //---------------------------------------------------------------------------------------
982 //
983 // helper functions for the GC events
984 //
985
986
987 #endif // PROFILING_SUPPORTED
988
989 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
990
991 //---------------------------------------------------------------------------------------
992 //
993 // It's generally unsafe for profiling API code to call Get(GCSafe)TypeHandle() on
994 // objects, since we can encounter objects on the heap whose types belong to unloading
995 // AppDomains. In such cases, getting the type handle of the object could AV.  Use this
996 // function instead, which will return NULL for potentially unloaded types.
997 // 
998 // Arguments:
999 //      pObj - Object * whose ClassID is desired
1000 //
1001 // Return Value:
1002 //      ClassID of the object, if it's safe to look it up. Else NULL.
1003 //
1004
1005 ClassID SafeGetClassIDFromObject(Object * pObj)
1006 {
1007     CONTRACTL
1008     {
1009         NOTHROW;
1010         GC_NOTRIGGER;
1011     } 
1012     CONTRACTL_END;
1013
1014     TypeHandle th = pObj->GetGCSafeTypeHandleIfPossible();
1015     if(th == NULL)
1016     {
1017         return NULL;
1018     }
1019
1020     return TypeHandleToClassID(th);
1021 }
1022
1023 //---------------------------------------------------------------------------------------
1024 //
1025 // Callback of type walk_fn used by GCHeapUtilities::DiagWalkObject.  Keeps a count of each
1026 // object reference found.
1027 //
1028 // Arguments:
1029 //      pBO - Object reference encountered in walk
1030 //      context - running count of object references encountered
1031 //
1032 // Return Value:
1033 //      Always returns TRUE to object walker so it walks the entire object
1034 //
1035
1036 BOOL CountContainedObjectRef(Object * pBO, void * context)
1037 {
1038     LIMITED_METHOD_CONTRACT;
1039     // Increase the count
1040     (*((size_t *)context))++;
1041
1042     return TRUE;
1043 }
1044
1045 //---------------------------------------------------------------------------------------
1046 //
1047 // Callback of type walk_fn used by GCHeapUtilities::DiagWalkObject.  Stores each object reference
1048 // encountered into an array.
1049 //
1050 // Arguments:
1051 //      pBO - Object reference encountered in walk
1052 //      context - Array of locations within the walked object that point to other
1053 //                objects.  On entry, (*context) points to the next unfilled array
1054 //                entry.  On exit, that location is filled, and (*context) is incremented
1055 //                to point to the next entry.
1056 //
1057 // Return Value:
1058 //      Always returns TRUE to object walker so it walks the entire object
1059 //
1060
1061 BOOL SaveContainedObjectRef(Object * pBO, void * context)
1062 {
1063     LIMITED_METHOD_CONTRACT;
1064     // Assign the value
1065     **((Object ***)context) = pBO;
1066
1067     // Now increment the array pointer
1068     //
1069     // Note that HeapWalkHelper has already walked the references once to count them up,
1070     // and then allocated an array big enough to hold those references.  First time this
1071     // callback is called for a given object, (*context) points to the first entry in the
1072     // array.  So "blindly" incrementing (*context) here and using it next time around
1073     // for the next reference, over and over again, should be safe.
1074     (*((Object ***)context))++;
1075
1076     return TRUE;
1077 }
1078
1079 //---------------------------------------------------------------------------------------
1080 //
1081 // Callback of type walk_fn used by the GC when walking the heap, to help profapi and ETW
1082 // track objects.  This guy orchestrates the use of the above callbacks which dig
1083 // into object references contained each object encountered by this callback.
1084 // This method is defined when either GC_PROFILING is defined or FEATURE_EVENT_TRACING
1085 // is defined and can operate fully when only one of the two is defined.
1086 //
1087 // Arguments:
1088 //      pBO - Object reference encountered on the heap
1089 //      pvContext - Pointer to ProfilerWalkHeapContext, containing ETW context built up
1090 //       during this GC, and which remembers if profapi-profiler is supposed to be called.
1091 //
1092 // Return Value:
1093 //      BOOL indicating whether the heap walk should continue.
1094 //      TRUE=continue
1095 //      FALSE=stop
1096 //
1097 extern bool s_forcedGCInProgress;
1098
1099 BOOL HeapWalkHelper(Object * pBO, void * pvContext)
1100 {
1101     CONTRACTL
1102     {
1103         NOTHROW;
1104         GC_NOTRIGGER;
1105         SO_INTOLERANT;
1106         MODE_ANY;
1107     }
1108     CONTRACTL_END;
1109
1110     OBJECTREF *   arrObjRef      = NULL;
1111     size_t        cNumRefs       = 0;
1112     bool          bOnStack       = false;
1113     MethodTable * pMT            = pBO->GetMethodTable();
1114
1115     ProfilerWalkHeapContext * pProfilerWalkHeapContext = (ProfilerWalkHeapContext *) pvContext;
1116
1117     if (pMT->ContainsPointersOrCollectible())
1118     {
1119         // First round through calculates the number of object refs for this class
1120         GCHeapUtilities::GetGCHeap()->DiagWalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs);
1121
1122         if (cNumRefs > 0)
1123         {
1124             // Create an array to contain all of the refs for this object
1125             bOnStack = cNumRefs <= 32 ? true : false;
1126
1127             if (bOnStack)
1128             {
1129                 // It's small enough, so just allocate on the stack
1130                 arrObjRef = (OBJECTREF *)_alloca(cNumRefs * sizeof(OBJECTREF));
1131             }
1132             else
1133             {
1134                 // Otherwise, allocate from the heap
1135                 arrObjRef = new (nothrow) OBJECTREF[cNumRefs];
1136
1137                 if (!arrObjRef)
1138                 {
1139                     return FALSE;
1140                 }
1141             }
1142
1143             // Second round saves off all of the ref values
1144             OBJECTREF * pCurObjRef = arrObjRef;
1145             GCHeapUtilities::GetGCHeap()->DiagWalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef);
1146         }
1147     }
1148
1149     HRESULT hr = E_FAIL;
1150
1151 #if defined(GC_PROFILING)
1152     if (pProfilerWalkHeapContext->fProfilerPinned)
1153     {
1154         // It is not safe and could be overflowed to downcast size_t to ULONG on WIN64.
1155         // However, we have to do this dangerous downcast here to comply with the existing Profiling COM interface.
1156         // We are currently evaluating ways to fix this potential overflow issue.
1157         hr = g_profControlBlock.pProfInterface->ObjectReference(
1158             (ObjectID) pBO, 
1159             SafeGetClassIDFromObject(pBO),
1160             (ULONG) cNumRefs, 
1161             (ObjectID *) arrObjRef);
1162     }
1163 #endif
1164
1165 #ifdef FEATURE_EVENT_TRACE
1166     if (s_forcedGCInProgress &&
1167         ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, 
1168                                      TRACE_LEVEL_INFORMATION, 
1169                                      CLR_GCHEAPDUMP_KEYWORD))
1170     {
1171         ETW::GCLog::ObjectReference(
1172             pProfilerWalkHeapContext,
1173             pBO,
1174             (ULONGLONG) SafeGetClassIDFromObject(pBO),
1175             cNumRefs,
1176             (Object **) arrObjRef);
1177
1178     }
1179 #endif // FEATURE_EVENT_TRACE
1180
1181     // If the data was not allocated on the stack, need to clean it up.
1182     if ((arrObjRef != NULL) && !bOnStack)
1183     {
1184         delete [] arrObjRef;
1185     }
1186
1187     // Return TRUE iff we want to the heap walk to continue. The only way we'd abort the
1188     // heap walk is if we're issuing profapi callbacks, and the profapi profiler
1189     // intentionally returned a failed HR (as its request that we stop the walk). There's
1190     // a potential conflict here. If a profapi profiler and an ETW profiler are both
1191     // monitoring the heap dump, and the profapi profiler requests to abort the walk (but
1192     // the ETW profiler may not want to abort the walk), then what do we do? The profapi
1193     // profiler gets precedence. We don't want to accidentally send more callbacks to a
1194     // profapi profiler that explicitly requested an abort. The ETW profiler will just
1195     // have to deal. In theory, I could make the code more complex by remembering that a
1196     // profapi profiler requested to abort the dump but an ETW profiler is still
1197     // attached, and then intentionally inhibit the remainder of the profapi callbacks
1198     // for this GC. But that's unnecessary complexity. In practice, it should be
1199     // extremely rare that a profapi profiler is monitoring heap dumps AND an ETW
1200     // profiler is also monitoring heap dumps.
1201     return (pProfilerWalkHeapContext->fProfilerPinned) ? SUCCEEDED(hr) : TRUE;
1202 }
1203
1204 #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACING)
1205
1206 #ifdef PROFILING_SUPPORTED
1207 //---------------------------------------------------------------------------------------
1208 //
1209 // Callback of type walk_fn used by the GC when walking the heap, to help profapi
1210 // track objects.  This is really just a wrapper around
1211 // EEToProfInterfaceImpl::AllocByClass, which does the real work
1212 //
1213 // Arguments:
1214 //      pBO - Object reference encountered on the heap
1215 //      pv - Structure used by EEToProfInterfaceImpl::AllocByClass to do its work.
1216 //
1217 // Return Value:
1218 //      BOOL indicating whether the heap walk should continue.
1219 //      TRUE=continue
1220 //      FALSE=stop
1221 //      Currently always returns TRUE
1222 //
1223
1224 BOOL AllocByClassHelper(Object * pBO, void * pv)
1225 {
1226     CONTRACTL
1227     {
1228         NOTHROW;
1229         GC_NOTRIGGER;
1230         MODE_ANY;
1231     }
1232     CONTRACTL_END;
1233     _ASSERTE(pv != NULL);
1234
1235     {
1236         BEGIN_PIN_PROFILER(CORProfilerPresent());
1237         // Pass along the call
1238         g_profControlBlock.pProfInterface->AllocByClass(
1239             (ObjectID) pBO, 
1240             SafeGetClassIDFromObject(pBO), 
1241             pv);
1242         END_PIN_PROFILER();
1243     }
1244
1245     return TRUE;
1246 }
1247
1248 #endif // PROFILING_SUPPORTED
1249 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
1250
1251 //---------------------------------------------------------------------------------------
1252 //
1253 // Callback of type promote_func called by GC while scanning roots (in GCProfileWalkHeap,
1254 // called after the collection).  Wrapper around EEToProfInterfaceImpl::RootReference2,
1255 // which does the real work.
1256 //
1257 // Arguments:
1258 //      pObj - Object reference encountered
1259 ///     ppRoot - Address that references ppObject (can be interior pointer)
1260 //      pSC - ProfilingScanContext * containing the root kind and GCReferencesData used
1261 //            by RootReference2 
1262 //      dwFlags - Properties of the root as GC_CALL* constants (this function converts
1263 //                to COR_PRF_GC_ROOT_FLAGS.
1264 //
1265
1266 void ScanRootsHelper(Object* pObj, Object ** ppRoot, ScanContext *pSC, uint32_t dwFlags)
1267 {
1268     CONTRACTL
1269     {
1270         NOTHROW;
1271         GC_NOTRIGGER;
1272         SO_INTOLERANT;
1273         MODE_ANY;
1274     }
1275     CONTRACTL_END;
1276
1277     // RootReference2 can return E_OUTOFMEMORY, and we're swallowing that.
1278     // Furthermore, we can't really handle it because we're callable during GC promotion.
1279     // On the other hand, this only means profiling information will be incomplete,
1280     // so it's ok to swallow E_OUTOFMEMORY.
1281     //
1282     FAULT_NOT_FATAL();
1283
1284     ProfilingScanContext *pPSC = (ProfilingScanContext *)pSC;
1285
1286     DWORD dwEtwRootFlags = 0;
1287     if (dwFlags & GC_CALL_INTERIOR)
1288         dwEtwRootFlags |= kEtwGCRootFlagsInterior;
1289     if (dwFlags & GC_CALL_PINNED)
1290         dwEtwRootFlags |= kEtwGCRootFlagsPinning;
1291
1292 #if defined(GC_PROFILING)
1293     void *rootID = NULL;
1294     switch (pPSC->dwEtwRootKind)
1295     {
1296     case    kEtwGCRootKindStack:
1297         rootID = pPSC->pMD;
1298         break;
1299
1300     case    kEtwGCRootKindHandle:
1301         _ASSERT(!"Shouldn't see handle here");
1302
1303     case    kEtwGCRootKindFinalizer:
1304     default:
1305         break;
1306     }
1307
1308     // Notify profiling API of the root
1309     if (pPSC->fProfilerPinned)
1310     {
1311         // Let the profiling code know about this root reference
1312         g_profControlBlock.pProfInterface->
1313             RootReference2((BYTE *)pObj, pPSC->dwEtwRootKind, (EtwGCRootFlags)dwEtwRootFlags, (BYTE *)rootID, &((pPSC)->pHeapId));
1314     }
1315 #endif
1316
1317 #ifdef FEATURE_EVENT_TRACE
1318     // Notify ETW of the root
1319     if (s_forcedGCInProgress &&
1320         ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, 
1321                                      TRACE_LEVEL_INFORMATION, 
1322                                      CLR_GCHEAPDUMP_KEYWORD))
1323     {
1324         ETW::GCLog::RootReference(
1325             NULL,           // handle is NULL, cuz this is a non-HANDLE root
1326             pObj,           // object being rooted
1327             NULL,           // pSecondaryNodeForDependentHandle is NULL, cuz this isn't a dependent handle
1328             FALSE,          // is dependent handle
1329             pPSC,
1330             dwFlags,        // dwGCFlags
1331             dwEtwRootFlags);
1332     }
1333 #endif // FEATURE_EVENT_TRACE
1334 }
1335
1336 #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
1337 #ifdef PROFILING_SUPPORTED
1338
1339 //---------------------------------------------------------------------------------------
1340 //
1341 // Private ProfToEEInterfaceImpl maintenance functions
1342 //
1343
1344
1345 //---------------------------------------------------------------------------------------
1346 //
1347 // Initialize ProfToEEInterfaceImpl (including ModuleILHeap statics)
1348 //
1349 // Return Value:
1350 //      HRESULT indicating success
1351 //
1352
1353 HRESULT ProfToEEInterfaceImpl::Init()
1354 {
1355     CONTRACTL
1356     {
1357         NOTHROW;
1358         CANNOT_TAKE_LOCK;
1359         GC_NOTRIGGER;
1360         MODE_ANY;
1361     } 
1362     CONTRACTL_END;
1363
1364     LOG((LF_CORPROF, LL_INFO1000, "**PROF: Init.\n"));
1365
1366 #ifdef _DEBUG
1367     if (ProfilingAPIUtility::ShouldInjectProfAPIFault(kProfAPIFault_StartupInternal))
1368     {
1369         return E_OUTOFMEMORY;
1370     }
1371 #endif //_DEBUG
1372     
1373     return S_OK;
1374 }
1375
1376
1377 //---------------------------------------------------------------------------------------
1378 //
1379 // Destroy ProfToEEInterfaceImpl (including ModuleILHeap statics)
1380 //
1381     
1382 ProfToEEInterfaceImpl::~ProfToEEInterfaceImpl()
1383 {
1384     CONTRACTL
1385     {
1386         NOTHROW;
1387         GC_NOTRIGGER;
1388         MODE_ANY;
1389     }
1390     CONTRACTL_END;
1391
1392     LOG((LF_CORPROF, LL_INFO1000, "**PROF: Terminate.\n"));
1393 }
1394
1395 //---------------------------------------------------------------------------------------
1396 //
1397 // Obsolete info functions
1398 //
1399
1400 HRESULT ProfToEEInterfaceImpl::GetInprocInspectionInterface(IUnknown **)
1401 {
1402     LIMITED_METHOD_CONTRACT;
1403     return E_NOTIMPL; 
1404 }
1405
1406 HRESULT ProfToEEInterfaceImpl::GetInprocInspectionIThisThread(IUnknown **)
1407 {
1408     LIMITED_METHOD_CONTRACT;
1409     return E_NOTIMPL; 
1410 }
1411
1412 HRESULT ProfToEEInterfaceImpl::BeginInprocDebugging(BOOL, DWORD *)
1413 {
1414     LIMITED_METHOD_CONTRACT;
1415     return E_NOTIMPL; 
1416 }
1417
1418 HRESULT ProfToEEInterfaceImpl::EndInprocDebugging(DWORD)
1419 {
1420     LIMITED_METHOD_CONTRACT;
1421     return E_NOTIMPL; 
1422 }
1423
1424 HRESULT ProfToEEInterfaceImpl::SetFunctionReJIT(FunctionID)
1425 {
1426     LIMITED_METHOD_CONTRACT;
1427     return E_NOTIMPL; 
1428 }
1429
1430
1431
1432
1433 //---------------------------------------------------------------------------------------
1434 //
1435 // *******************************
1436 // Public Profiler->EE entrypoints
1437 // *******************************
1438 //
1439 // ProfToEEInterfaceImpl implementation of public ICorProfilerInfo* methods
1440 //
1441 // NOTE: All ICorProfilerInfo* method implementations must follow the rules stated
1442 // at the top of this file!
1443 //
1444
1445 // See corprof.idl / MSDN for detailed comments about each of these public
1446 // functions, their parameters, return values, etc.
1447
1448 HRESULT ProfToEEInterfaceImpl::SetEventMask(DWORD dwEventMask)
1449 {
1450     CONTRACTL
1451     {
1452         // Yay!
1453         NOTHROW;
1454
1455         // Yay!
1456         GC_NOTRIGGER;
1457
1458         // Yay!
1459         MODE_ANY;
1460
1461         // Yay!
1462         EE_THREAD_NOT_REQUIRED;
1463
1464         CANNOT_TAKE_LOCK;
1465
1466         SO_NOT_MAINLINE;
1467     }
1468     CONTRACTL_END;
1469
1470     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
1471         (LF_CORPROF, 
1472         LL_INFO1000, 
1473         "**PROF: SetEventMask 0x%08x.\n",
1474         dwEventMask));
1475
1476     _ASSERTE(CORProfilerPresentOrInitializing());
1477
1478     return g_profControlBlock.pProfInterface->SetEventMask(dwEventMask, 0 /* No high bits */);
1479 }
1480
1481 HRESULT ProfToEEInterfaceImpl::SetEventMask2(DWORD dwEventsLow, DWORD dwEventsHigh)
1482 {
1483     CONTRACTL
1484     {
1485         // Yay!
1486         NOTHROW;
1487
1488         // Yay!
1489         GC_NOTRIGGER;
1490
1491         // Yay!
1492         MODE_ANY;
1493
1494         // Yay!
1495         EE_THREAD_NOT_REQUIRED;
1496
1497         CANNOT_TAKE_LOCK;
1498
1499         SO_NOT_MAINLINE;
1500     }
1501     CONTRACTL_END;
1502
1503     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
1504         (LF_CORPROF, 
1505         LL_INFO1000, 
1506         "**PROF: SetEventMask2 0x%08x, 0x%08x.\n",
1507         dwEventsLow, dwEventsHigh));
1508
1509     _ASSERTE(CORProfilerPresentOrInitializing());
1510  
1511     return g_profControlBlock.pProfInterface->SetEventMask(dwEventsLow, dwEventsHigh);
1512 }
1513
1514
1515 HRESULT ProfToEEInterfaceImpl::GetHandleFromThread(ThreadID threadId, HANDLE *phThread)
1516 {
1517     CONTRACTL
1518 {
1519         // Yay!
1520         NOTHROW;
1521
1522         // Yay!
1523         GC_NOTRIGGER;
1524     
1525         // Yay!
1526         MODE_ANY;
1527
1528         // Yay!
1529         EE_THREAD_NOT_REQUIRED;
1530
1531         // Yay!
1532         CANNOT_TAKE_LOCK;
1533     
1534         SO_NOT_MAINLINE;
1535     }
1536     CONTRACTL_END;
1537
1538     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
1539         (LF_CORPROF, 
1540         LL_INFO1000, 
1541         "**PROF: GetHandleFromThread 0x%p.\n", 
1542         threadId));
1543
1544     if (!IsManagedThread(threadId))
1545     {
1546         return E_INVALIDARG;
1547     }
1548
1549     HRESULT hr = S_OK;
1550
1551     HANDLE hThread = ((Thread *)threadId)->GetThreadHandle();
1552
1553     if (hThread == INVALID_HANDLE_VALUE)
1554         hr = E_INVALIDARG;
1555
1556     else if (phThread)
1557         *phThread = hThread;
1558
1559     return (hr);
1560 }
1561
1562 HRESULT ProfToEEInterfaceImpl::GetObjectSize(ObjectID objectId, ULONG *pcSize)
1563 {
1564     CONTRACTL
1565     {
1566         // Yay!
1567         NOTHROW;
1568
1569         // Yay!
1570         GC_NOTRIGGER;
1571
1572         // Yay!  Fail at runtime if in preemptive mode via AllowObjectInspection()
1573         MODE_ANY;
1574
1575         // Yay!
1576         EE_THREAD_NOT_REQUIRED;
1577
1578         // Yay!
1579         CANNOT_TAKE_LOCK;
1580
1581         SO_NOT_MAINLINE;
1582     }
1583     CONTRACTL_END;
1584
1585     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
1586         (LF_CORPROF, 
1587          LL_INFO1000, 
1588          "**PROF: GetObjectSize 0x%p.\n", 
1589          objectId));
1590     
1591     if (objectId == NULL)
1592     {
1593         return E_INVALIDARG;
1594     }
1595
1596     HRESULT hr = AllowObjectInspection();
1597     if (FAILED(hr))
1598     {
1599         return hr;
1600     }
1601     
1602     // Get the object pointer
1603     Object *pObj = reinterpret_cast<Object *>(objectId);
1604
1605     // Get the size
1606     if (pcSize)
1607     {
1608         SIZE_T size = pObj->GetSize();
1609
1610         if(size < MIN_OBJECT_SIZE)
1611         {
1612             size = PtrAlign(size);
1613         }
1614
1615         if (size > ULONG_MAX)
1616         {
1617             *pcSize = ULONG_MAX;
1618             return COR_E_OVERFLOW;
1619         }
1620         *pcSize = (ULONG)size; 
1621     }
1622
1623     // Indicate success
1624     return (S_OK);
1625 }
1626
1627 HRESULT ProfToEEInterfaceImpl::GetObjectSize2(ObjectID objectId, SIZE_T *pcSize)
1628 {
1629     CONTRACTL
1630     {
1631         // Yay!
1632         NOTHROW;
1633
1634         // Yay!
1635         GC_NOTRIGGER;
1636
1637         // Yay!  Fail at runtime if in preemptive mode via AllowObjectInspection()
1638         MODE_ANY;
1639
1640         // Yay!
1641         EE_THREAD_NOT_REQUIRED;
1642
1643         // Yay!
1644         CANNOT_TAKE_LOCK;
1645
1646         SO_NOT_MAINLINE;
1647     }
1648     CONTRACTL_END;
1649
1650     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
1651         (LF_CORPROF, 
1652          LL_INFO1000, 
1653          "**PROF: GetObjectSize2 0x%p.\n", 
1654          objectId));
1655     
1656     if (objectId == NULL)
1657     {
1658         return E_INVALIDARG;
1659     }
1660
1661     HRESULT hr = AllowObjectInspection();
1662     if (FAILED(hr))
1663     {
1664         return hr;
1665     }
1666     
1667     // Get the object pointer
1668     Object *pObj = reinterpret_cast<Object *>(objectId);
1669
1670     // Get the size
1671     if (pcSize)
1672     {
1673         SIZE_T size = pObj->GetSize();
1674
1675         if(size < MIN_OBJECT_SIZE)
1676         {
1677             size = PtrAlign(size);
1678         }
1679
1680         *pcSize = size; 
1681     }
1682
1683     // Indicate success
1684     return (S_OK);
1685 }
1686
1687
1688 HRESULT ProfToEEInterfaceImpl::IsArrayClass(
1689     /* [in] */  ClassID classId,
1690     /* [out] */ CorElementType *pBaseElemType,
1691     /* [out] */ ClassID *pBaseClassId,
1692     /* [out] */ ULONG   *pcRank)
1693 {
1694     CONTRACTL
1695     {
1696         NOTHROW;
1697
1698         GC_NOTRIGGER;
1699         
1700         // Yay!
1701         MODE_ANY;
1702
1703         // Yay!
1704         EE_THREAD_NOT_REQUIRED;
1705
1706         // Yay!
1707         CANNOT_TAKE_LOCK;
1708
1709         SO_NOT_MAINLINE;
1710     }
1711     CONTRACTL_END;
1712
1713     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
1714         (LF_CORPROF, 
1715          LL_INFO1000, 
1716          "**PROF: IsArrayClass 0x%p.\n",
1717          classId));
1718
1719     HRESULT hr;
1720     
1721     if (classId == NULL)
1722     {
1723         return E_INVALIDARG;
1724     }
1725
1726     TypeHandle th = TypeHandle::FromPtr((void *)classId);
1727
1728     ARRAY_KIND arrayKind = ArrayKindFromTypeHandle(th);
1729         
1730     // If this is indeed an array class, get some info about it
1731     switch (arrayKind)
1732     {
1733         default:
1734         {
1735             _ASSERTE(!"Unexpected return from ArrayKindFromTypeHandle()");
1736             hr = E_UNEXPECTED;
1737             break;
1738         }
1739             
1740         case ARRAY_KIND_TYPEDESC:
1741         {
1742             // This is actually an array, so cast it up
1743             ArrayTypeDesc *pArr = th.AsArray();
1744
1745             // Fill in the type if they want it
1746             if (pBaseElemType != NULL)
1747             {
1748                 *pBaseElemType = pArr->GetArrayElementTypeHandle().GetVerifierCorElementType();
1749             }
1750
1751             // If this is an array of classes and they wish to have the base type
1752             // If there is no associated class with this type, then there's no problem
1753             // because GetClass returns NULL which is the default we want to return in
1754             // this case.
1755             // Note that for generic code we always return uninstantiated ClassIDs and FunctionIDs
1756             if (pBaseClassId != NULL)
1757             {
1758                 *pBaseClassId = TypeHandleToClassID(pArr->GetTypeParam());
1759             }
1760
1761             // If they want the number of dimensions of the array
1762             if (pcRank != NULL)
1763             {
1764                 *pcRank = (ULONG) pArr->GetRank();
1765             }
1766
1767             // S_OK indicates that this was indeed an array
1768             hr = S_OK;
1769             break;
1770         }
1771         case ARRAY_KIND_METHODTABLE:
1772         {
1773             MethodTable *pArrMT = th.GetMethodTable();
1774
1775             // Fill in the type if they want it
1776             if (pBaseElemType != NULL)
1777             {
1778                 *pBaseElemType = pArrMT->GetArrayElementType();
1779             }
1780
1781             // If this is an array of classes and they wish to have the base type.
1782             if (pBaseClassId != NULL)
1783             {
1784                 *pBaseClassId = TypeHandleToClassID(pArrMT->GetApproxArrayElementTypeHandle());
1785             }
1786
1787             // If they want the number of dimensions of the array
1788             if (pcRank != NULL)
1789             {
1790                 *pcRank = (ULONG) pArrMT->GetRank();
1791             }
1792
1793             // S_OK indicates that this was indeed an array
1794             hr = S_OK;
1795             break;
1796         }
1797         case ARRAY_KIND_NOTARRAY:
1798         {
1799             if (pBaseClassId != NULL)
1800             {
1801                 *pBaseClassId = NULL;
1802             }
1803             
1804             // This is not an array, S_FALSE indicates so.
1805             hr = S_FALSE;
1806             break;
1807         }
1808     }
1809
1810     return hr;
1811 }
1812     
1813 HRESULT ProfToEEInterfaceImpl::GetThreadInfo(ThreadID threadId, DWORD *pdwWin32ThreadId)
1814 {
1815     CONTRACTL
1816     {
1817         // Yay!
1818         NOTHROW;
1819
1820         // Yay!
1821         GC_NOTRIGGER;
1822
1823         // Yay!
1824         MODE_ANY;
1825
1826         // Yay!
1827         EE_THREAD_NOT_REQUIRED;
1828
1829         // Yay!
1830         CANNOT_TAKE_LOCK;
1831
1832         SO_NOT_MAINLINE;
1833     }
1834     CONTRACTL_END;
1835
1836     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
1837         (LF_CORPROF, 
1838          LL_INFO1000, 
1839          "**PROF: GetThreadInfo 0x%p.\n", 
1840          threadId));  
1841     
1842     if (!IsManagedThread(threadId))
1843     {
1844         return E_INVALIDARG;
1845     }
1846     
1847     if (pdwWin32ThreadId)
1848     {
1849         *pdwWin32ThreadId = ((Thread *)threadId)->GetOSThreadId();
1850     }
1851
1852     return S_OK;
1853 }
1854
1855 HRESULT ProfToEEInterfaceImpl::GetCurrentThreadID(ThreadID *pThreadId)
1856 {
1857     CONTRACTL
1858     {
1859         // Yay!
1860         NOTHROW;
1861
1862         // Yay!
1863         GC_NOTRIGGER;
1864
1865         // Yay!
1866         MODE_ANY;
1867
1868         // Yay!
1869         EE_THREAD_NOT_REQUIRED;
1870
1871         // Yay!
1872         CANNOT_TAKE_LOCK;
1873
1874         SO_NOT_MAINLINE;
1875     }
1876     CONTRACTL_END;
1877
1878     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
1879         (LF_CORPROF, 
1880         LL_INFO1000, 
1881         "**PROF: GetCurrentThreadID.\n"));    
1882
1883     HRESULT hr = S_OK;
1884
1885     // No longer assert that GetThread doesn't return NULL, since callbacks
1886     // can now occur on non-managed threads (such as the GC helper threads)
1887     Thread * pThread = GetThreadNULLOk();
1888
1889     // If pThread is null, then the thread has never run managed code and
1890     // so has no ThreadID
1891     if (!IsManagedThread(pThread))
1892         hr = CORPROF_E_NOT_MANAGED_THREAD;
1893
1894     // Only provide value if they want it
1895     else if (pThreadId)
1896         *pThreadId = (ThreadID) pThread;
1897
1898     return (hr);
1899 }
1900
1901 //---------------------------------------------------------------------------------------
1902 //
1903 // Internal helper function to wrap a call into the JIT manager to get information about
1904 // a managed function based on IP
1905 //
1906 // Arguments:
1907 //      ip - IP address inside managed function of interest
1908 //      ppCodeInfo - [out] information about the managed function based on IP
1909 //
1910 // Return Value:
1911 //     HRESULT indicating success or failure.
1912 //
1913 //
1914
1915 HRESULT GetFunctionInfoInternal(LPCBYTE ip, EECodeInfo * pCodeInfo)
1916 {
1917     CONTRACTL
1918     {
1919         NOTHROW;
1920
1921         GC_NOTRIGGER;
1922         EE_THREAD_NOT_REQUIRED;
1923         CAN_TAKE_LOCK;
1924         CANNOT_RETAKE_LOCK;
1925
1926         SO_NOT_MAINLINE;
1927
1928         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
1929         // host (SQL).  Corners will be cut to ensure this is the case
1930         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
1931     }
1932     CONTRACTL_END;
1933
1934     // Before calling into the code manager, ensure the GC heap has been
1935     // initialized--else the code manager will assert trying to get info from the heap.
1936     if (!IsGarbageCollectorFullyInitialized())
1937     {
1938         return CORPROF_E_NOT_YET_AVAILABLE;
1939     }
1940
1941     if (ShouldAvoidHostCalls())
1942     {
1943         ExecutionManager::ReaderLockHolder rlh(NoHostCalls);
1944         if (!rlh.Acquired())
1945         {
1946             // Couldn't get the info.  Try again later
1947             return CORPROF_E_ASYNCHRONOUS_UNSAFE;
1948         }
1949
1950         pCodeInfo->Init((PCODE)ip, ExecutionManager::ScanNoReaderLock);
1951     }
1952     else
1953     {
1954         pCodeInfo->Init((PCODE)ip);
1955     }
1956
1957     if (!pCodeInfo->IsValid())
1958     {
1959         return E_FAIL;
1960     }
1961
1962     return S_OK;
1963 }
1964
1965
1966 HRESULT GetFunctionFromIPInternal(LPCBYTE ip, EECodeInfo * pCodeInfo, BOOL failOnNoMetadata)
1967 {
1968     CONTRACTL
1969     {
1970         NOTHROW;
1971         GC_NOTRIGGER;
1972         MODE_ANY;
1973         EE_THREAD_NOT_REQUIRED;
1974         CAN_TAKE_LOCK;
1975         SO_NOT_MAINLINE;
1976     }
1977     CONTRACTL_END;
1978
1979     _ASSERTE (pCodeInfo != NULL);
1980
1981     HRESULT hr = GetFunctionInfoInternal(ip, pCodeInfo);
1982     if (FAILED(hr))
1983     {
1984         return hr;
1985     }
1986
1987     if (failOnNoMetadata)
1988     {
1989         // never return a method that the user of the profiler API cannot use
1990         if (pCodeInfo->GetMethodDesc()->IsNoMetadata())
1991         {
1992             return E_FAIL;
1993         }
1994     }
1995
1996     return S_OK;
1997 }
1998
1999
2000 HRESULT ProfToEEInterfaceImpl::GetFunctionFromIP(LPCBYTE ip, FunctionID * pFunctionId)
2001 {
2002     CONTRACTL
2003     {
2004         // Yay!
2005         NOTHROW;
2006
2007         // Yay!
2008         GC_NOTRIGGER;
2009
2010         // Yay!
2011         MODE_ANY;
2012
2013         // Yay!
2014         EE_THREAD_NOT_REQUIRED;
2015
2016         // Querying the code manager requires a reader lock.  However, see
2017         // code:#DisableLockOnAsyncCalls
2018         DISABLED(CAN_TAKE_LOCK);
2019
2020         // Asynchronous functions can be called at arbitrary times when runtime 
2021         // is holding locks that cannot be reentered without causing deadlock.
2022         // This contract detects any attempts to reenter locks held at the time 
2023         // this function was called.  
2024         CANNOT_RETAKE_LOCK;
2025
2026         SO_NOT_MAINLINE;
2027
2028         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
2029         // host (SQL).  Corners will be cut to ensure this is the case
2030         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
2031     }
2032     CONTRACTL_END;
2033
2034     // See code:#DisableLockOnAsyncCalls
2035     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
2036
2037     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
2038         (LF_CORPROF, 
2039         LL_INFO1000, 
2040         "**PROF: GetFunctionFromIP 0x%p.\n", 
2041         ip));  
2042
2043     // This call is allowed asynchronously, but the JIT functions take a reader lock.  
2044     // So we need to ensure the current thread hasn't been hijacked by a profiler while
2045     // it was holding the writer lock.  Checking the ForbidSuspendThread region is a
2046     // sufficient test for this
2047     FAIL_IF_IN_FORBID_SUSPEND_REGION();
2048
2049     HRESULT hr = S_OK;
2050
2051     EECodeInfo codeInfo;
2052
2053     hr = GetFunctionFromIPInternal(ip, &codeInfo, /* failOnNoMetadata */ TRUE);
2054     if (FAILED(hr))
2055     {
2056         return hr;
2057     }
2058
2059     if (pFunctionId)
2060     {
2061         *pFunctionId = MethodDescToFunctionID(codeInfo.GetMethodDesc());
2062     }
2063
2064     return S_OK;
2065 }
2066
2067
2068 HRESULT ProfToEEInterfaceImpl::GetFunctionFromIP2(LPCBYTE ip, FunctionID * pFunctionId, ReJITID * pReJitId)
2069 {
2070     CONTRACTL
2071     {
2072         // Yay!
2073         NOTHROW;
2074
2075         // Grabbing the rejitid requires entering the rejit manager's hash table & lock,
2076         // which can switch us to preemptive mode and trigger GCs
2077         GC_TRIGGERS;
2078
2079         // Yay!
2080         MODE_ANY;
2081     
2082         // Yay!
2083         EE_THREAD_NOT_REQUIRED;
2084
2085         // Grabbing the rejitid requires entering the rejit manager's hash table & lock,
2086         CAN_TAKE_LOCK;
2087
2088         SO_NOT_MAINLINE;
2089     }
2090     CONTRACTL_END;
2091
2092     // See code:#DisableLockOnAsyncCalls
2093     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
2094
2095     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
2096         kP2EEAllowableAfterAttach | kP2EETriggers,
2097         (LF_CORPROF, 
2098         LL_INFO1000, 
2099         "**PROF: GetFunctionFromIP2 0x%p.\n", 
2100         ip));  
2101
2102     HRESULT hr = S_OK;
2103
2104     EECodeInfo codeInfo;
2105
2106     hr = GetFunctionFromIPInternal(ip, &codeInfo, /* failOnNoMetadata */ TRUE);
2107     if (FAILED(hr))
2108     {
2109         return hr;
2110     }
2111
2112     if (pFunctionId)
2113     {
2114         *pFunctionId = MethodDescToFunctionID(codeInfo.GetMethodDesc());
2115     }
2116
2117     if (pReJitId != NULL)
2118     {
2119         MethodDesc * pMD = codeInfo.GetMethodDesc();
2120         *pReJitId = pMD->GetReJitManager()->GetReJitId(pMD, codeInfo.GetStartAddress());
2121     }
2122
2123     return S_OK;
2124 }
2125
2126 //*****************************************************************************
2127 // Given a function id, retrieve the metadata token and a reader api that
2128 // can be used against the token.
2129 //*****************************************************************************
2130 HRESULT ProfToEEInterfaceImpl::GetTokenAndMetaDataFromFunction(
2131     FunctionID  functionId,
2132     REFIID      riid,
2133     IUnknown    **ppOut,
2134     mdToken     *pToken)
2135 {
2136     CONTRACTL
2137     {
2138         // Yay!
2139         NOTHROW;
2140
2141         // Yay!
2142         GC_NOTRIGGER;
2143
2144         // Yay!
2145         MODE_ANY;
2146
2147         // Yay!
2148         EE_THREAD_NOT_REQUIRED;
2149
2150         // PEFile::GetRWImporter and GetReadablePublicMetaDataInterface take locks
2151         CAN_TAKE_LOCK;
2152
2153         SO_NOT_MAINLINE;
2154     }
2155     CONTRACTL_END;
2156
2157     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
2158         (LF_CORPROF, 
2159          LL_INFO1000, 
2160          "**PROF: GetTokenAndMetaDataFromFunction 0x%p.\n", 
2161          functionId));  
2162     
2163     if (functionId == NULL)
2164     {
2165         return E_INVALIDARG;
2166     }
2167     
2168     HRESULT     hr = S_OK;
2169
2170     MethodDesc *pMD = FunctionIdToMethodDesc(functionId);
2171
2172     // it's not safe to examine a methoddesc that has not been restored so do not do so
2173     if (!pMD->IsRestored())
2174         return CORPROF_E_DATAINCOMPLETE;
2175     
2176     if (pToken)
2177     {
2178         *pToken = pMD->GetMemberDef();
2179     }
2180
2181     // don't bother with any of this module fetching if the metadata access isn't requested
2182     if (ppOut)
2183     {
2184         Module * pMod = pMD->GetModule();
2185         hr = pMod->GetReadablePublicMetaDataInterface(ofRead, riid, (LPVOID *) ppOut);
2186     }
2187
2188     return hr;
2189 }
2190
2191 //---------------------------------------------------------------------------------------
2192 // What follows are the GetCodeInfo* APIs and their helpers.  The two helpers factor out
2193 // some of the common code to validate parameters and then determine the code info from
2194 // the start of the code.  Each individual GetCodeInfo* API differs in how it uses these
2195 // helpers, particuarly in how it determines the start of the code (GetCodeInfo3 needs
2196 // to use the rejit manager to determine the code start, whereas the others do not). 
2197 // Factoring out like this allows us to have statically determined contracts that differ
2198 // based on whether we need to use the rejit manager, which requires locking and
2199 // may trigger GCs.
2200 //---------------------------------------------------------------------------------------
2201
2202
2203 HRESULT ValidateParametersForGetCodeInfo(
2204     MethodDesc * pMethodDesc,
2205     ULONG32  cCodeInfos,
2206     COR_PRF_CODE_INFO codeInfos[])
2207 {
2208     LIMITED_METHOD_CONTRACT;
2209
2210     if (pMethodDesc == NULL)
2211     {
2212         return E_INVALIDARG;
2213     }
2214
2215     if ((cCodeInfos != 0) && (codeInfos == NULL))
2216     {
2217         return E_INVALIDARG;
2218     }
2219
2220     // it's not safe to examine a methoddesc that has not been restored so do not do so
2221     if (!pMethodDesc->IsRestored())
2222         return CORPROF_E_DATAINCOMPLETE;
2223
2224     if (pMethodDesc->HasClassOrMethodInstantiation() && pMethodDesc->IsTypicalMethodDefinition())
2225     {
2226         // In this case, we used to replace pMethodDesc with its canonical instantiation
2227         // (FindOrCreateTypicalSharedInstantiation).  However, a profiler should never be able
2228         // to get to this point anyway, since any MethodDesc a profiler gets from us
2229         // cannot be typical (i.e., cannot be a generic with types still left uninstantiated).
2230         // We assert here just in case a test proves me wrong, but generally we will
2231         // disallow this code path.
2232         _ASSERTE(!"Profiler passed a typical method desc (a generic with types still left uninstantiated) to GetCodeInfo2");
2233         return E_INVALIDARG;
2234     }
2235
2236     return S_OK;
2237 }
2238
2239 HRESULT GetCodeInfoFromCodeStart(
2240     PCODE start,
2241     ULONG32  cCodeInfos,
2242     ULONG32 * pcCodeInfos,
2243     COR_PRF_CODE_INFO codeInfos[])
2244 {
2245     CONTRACTL
2246     {
2247         NOTHROW;
2248         GC_NOTRIGGER;
2249         MODE_ANY;
2250
2251         // We need to take the ExecutionManager reader lock to find the
2252         // appropriate jit manager.
2253         CAN_TAKE_LOCK;
2254
2255         SO_NOT_MAINLINE;
2256
2257         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
2258         // host (SQL).  Corners will be cut to ensure this is the case
2259         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
2260     }
2261     CONTRACTL_END;
2262
2263     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
2264
2265     ///////////////////////////////////
2266     // Get the code region info for this function. This is a multi step process.
2267     //
2268     // MethodDesc ==> Code Address ==> JitMananger ==>
2269     // MethodToken ==> MethodRegionInfo
2270     // 
2271     // (Our caller handled the first step: MethodDesc ==> Code Address.)
2272     //
2273     // <WIN64-ONLY>
2274     //
2275     // On WIN64 we have a choice of where to go to find out the function address range size:
2276     // GC info (which is what we're doing below on all architectures) or the OS unwind
2277     // info, stored in the RUNTIME_FUNCTION structure.  The latter produces
2278     // a SMALLER size than the former, because the latter excludes some data from
2279     // the set we report to the OS for unwind info.  For example, switch tables can be
2280     // separated out from the regular code and not be reported as OS unwind info, and thus
2281     // those addresses will not appear in the range reported by the RUNTIME_FUNCTION gotten via:
2282     //
2283     //      IJitManager* pJitMan = ExecutionManager::FindJitMan((PBYTE)codeInfos[0].startAddress);
2284     //      PRUNTIME_FUNCTION pfe = pJitMan->GetUnwindInfo((PBYTE)codeInfos[0].startAddress);
2285     //      *pcCodeInfos = (ULONG) (pfe->EndAddress - pfe->BeginAddress);
2286     //
2287     // (Note that GCInfo & OS unwind info report the same start address--it's the size that's
2288     // different.)
2289     //
2290     // The advantage of using the GC info is that it's available on all architectures,
2291     // and it gives you a more complete picture of the addresses belonging to the function.
2292     //
2293     // A disadvantage of using GC info is we'll report those extra addresses (like switch
2294     // tables) that a profiler might turn back around and use in a call to
2295     // GetFunctionFromIP.  A profiler may expect we'd be able to map back any address
2296     // in the function's GetCodeInfo ranges back to that function's FunctionID (methoddesc).  But
2297     // querying these extra addresses will cause GetFunctionFromIP to fail, as they're not
2298     // actually valid instruction addresses that the IP register can be set to.
2299     // 
2300     // The advantage wins out, so we're going with GC info everywhere.
2301     //
2302     // </WIN64-ONLY>
2303
2304     HRESULT hr;
2305
2306     if (start == NULL)
2307     {
2308         return CORPROF_E_FUNCTION_NOT_COMPILED;
2309     }
2310
2311     EECodeInfo codeInfo;
2312     hr = GetFunctionInfoInternal(
2313         (LPCBYTE) start,
2314         &codeInfo);
2315     if (hr == CORPROF_E_ASYNCHRONOUS_UNSAFE)
2316     {
2317         _ASSERTE(ShouldAvoidHostCalls());
2318         return hr;
2319     }
2320     if (FAILED(hr))
2321     {
2322         return CORPROF_E_FUNCTION_NOT_COMPILED;
2323     }
2324
2325     IJitManager::MethodRegionInfo methodRegionInfo;
2326     codeInfo.GetMethodRegionInfo(&methodRegionInfo);
2327
2328     //
2329     // Fill out the codeInfo structures with valuse from the
2330     // methodRegion
2331     //
2332     // Note that we're assuming that a method will never be split into
2333     // more than two regions ... this is unlikely to change any time in
2334     // the near future.
2335     //
2336     if (NULL != codeInfos)
2337     {
2338         if (cCodeInfos > 0)
2339         {
2340             //
2341             // We have to return the two regions in the order that they would appear
2342             // if straight-line compiled
2343             //
2344             if (PCODEToPINSTR(start) == methodRegionInfo.hotStartAddress)
2345             {
2346                 codeInfos[0].startAddress =
2347                     (UINT_PTR)methodRegionInfo.hotStartAddress;
2348                 codeInfos[0].size = methodRegionInfo.hotSize;
2349             }
2350             else
2351             {
2352                 _ASSERTE(methodRegionInfo.coldStartAddress != NULL);
2353                 codeInfos[0].startAddress =
2354                     (UINT_PTR)methodRegionInfo.coldStartAddress;
2355                 codeInfos[0].size = methodRegionInfo.coldSize;
2356             }
2357
2358             if (NULL != methodRegionInfo.coldStartAddress)
2359             {
2360                 if (cCodeInfos > 1)
2361                 {
2362                     if (PCODEToPINSTR(start) == methodRegionInfo.hotStartAddress)
2363                     {
2364                         codeInfos[1].startAddress =
2365                             (UINT_PTR)methodRegionInfo.coldStartAddress;
2366                         codeInfos[1].size = methodRegionInfo.coldSize;
2367                     }
2368                     else
2369                     {
2370                         codeInfos[1].startAddress =
2371                             (UINT_PTR)methodRegionInfo.hotStartAddress;
2372                         codeInfos[1].size = methodRegionInfo.hotSize;
2373                     }
2374                 }
2375             }
2376         }
2377     }
2378
2379     if (NULL != pcCodeInfos)
2380     {
2381         *pcCodeInfos = (NULL != methodRegionInfo.coldStartAddress) ? 2 : 1;
2382     }
2383
2384
2385     return S_OK;
2386 }
2387
2388 //*****************************************************************************
2389 // Gets the location and size of a jitted function
2390 //*****************************************************************************
2391
2392 HRESULT ProfToEEInterfaceImpl::GetCodeInfo(FunctionID functionId, LPCBYTE * pStart, ULONG * pcSize)
2393 {
2394     CONTRACTL
2395     {
2396         // Yay!
2397         NOTHROW;
2398
2399         // Yay!
2400         GC_NOTRIGGER;
2401
2402         // Yay!
2403         MODE_ANY;
2404
2405         // Yay!
2406         EE_THREAD_NOT_REQUIRED;
2407
2408         // (See locking contract comment in GetCodeInfoHelper.)
2409         DISABLED(CAN_TAKE_LOCK);
2410         
2411         // (See locking contract comment in GetCodeInfoHelper.)
2412         CANNOT_RETAKE_LOCK;
2413
2414         SO_NOT_MAINLINE;
2415
2416         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
2417         // host (SQL).  Corners will be cut to ensure this is the case
2418         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
2419     }
2420     CONTRACTL_END;
2421
2422     // See code:#DisableLockOnAsyncCalls
2423     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
2424
2425     // This is called asynchronously, but GetCodeInfoHelper() will
2426     // ensure we're not called at a dangerous time
2427     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
2428         (LF_CORPROF, 
2429         LL_INFO1000, 
2430         "**PROF: GetCodeInfo 0x%p.\n", 
2431         functionId));
2432
2433     // GetCodeInfo may be called asynchronously, and the JIT functions take a reader
2434     // lock.  So we need to ensure the current thread hasn't been hijacked by a profiler while
2435     // it was holding the writer lock.  Checking the ForbidSuspendThread region is a sufficient test for this
2436     FAIL_IF_IN_FORBID_SUSPEND_REGION();
2437     
2438     if (functionId == 0)
2439     {
2440         return E_INVALIDARG;
2441     }
2442
2443     MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
2444
2445     COR_PRF_CODE_INFO codeInfos[2];
2446     ULONG32 cCodeInfos;
2447
2448     HRESULT hr = GetCodeInfoFromCodeStart(
2449         pMethodDesc->GetNativeCode(),
2450         _countof(codeInfos),
2451         &cCodeInfos, 
2452         codeInfos);
2453
2454     if ((FAILED(hr)) || (0 == cCodeInfos))
2455     {
2456         return hr;
2457     }
2458
2459     if (NULL != pStart)
2460     {
2461         *pStart = reinterpret_cast< LPCBYTE >(codeInfos[0].startAddress);
2462     }
2463
2464     if (NULL != pcSize)
2465     {
2466         if (!FitsIn<ULONG>(codeInfos[0].size))
2467         {
2468             return E_UNEXPECTED;
2469         }
2470         *pcSize = static_cast<ULONG>(codeInfos[0].size);
2471     }
2472
2473     return hr;
2474 }
2475
2476 HRESULT ProfToEEInterfaceImpl::GetCodeInfo2(FunctionID functionId,
2477                                             ULONG32  cCodeInfos,
2478                                             ULONG32 * pcCodeInfos,
2479                                             COR_PRF_CODE_INFO codeInfos[])
2480 {
2481     CONTRACTL
2482     {
2483         // Yay!
2484         NOTHROW;
2485
2486         // Yay!
2487         GC_NOTRIGGER;
2488
2489         // Yay!
2490         MODE_ANY;
2491
2492         // Yay!
2493         EE_THREAD_NOT_REQUIRED;
2494
2495         // (See locking contract comment in GetCodeInfoHelper.)
2496         DISABLED(CAN_TAKE_LOCK);
2497
2498         // (See locking contract comment in GetCodeInfoHelper.)
2499         CANNOT_RETAKE_LOCK;
2500
2501         SO_NOT_MAINLINE;
2502         
2503         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
2504         // host (SQL).  Corners will be cut to ensure this is the case
2505         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
2506
2507         PRECONDITION(CheckPointer(pcCodeInfos, NULL_OK));
2508         PRECONDITION(CheckPointer(codeInfos, NULL_OK));
2509     }
2510     CONTRACTL_END;
2511
2512     // See code:#DisableLockOnAsyncCalls
2513     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
2514
2515     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
2516         (LF_CORPROF, 
2517         LL_INFO1000, 
2518         "**PROF: GetCodeInfo2 0x%p.\n", 
2519         functionId));         
2520
2521     HRESULT hr = S_OK; 
2522
2523     EX_TRY
2524     {
2525         MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
2526
2527         hr = ValidateParametersForGetCodeInfo(pMethodDesc, cCodeInfos, codeInfos);
2528         if (SUCCEEDED(hr))
2529         {
2530             hr = GetCodeInfoFromCodeStart(
2531                 pMethodDesc->GetNativeCode(),
2532                 cCodeInfos,
2533                 pcCodeInfos,
2534                 codeInfos);
2535         }
2536     }
2537     EX_CATCH_HRESULT(hr);
2538
2539     return hr;
2540 }
2541
2542
2543 HRESULT ProfToEEInterfaceImpl::GetCodeInfo3(FunctionID functionId,
2544                                             ReJITID  reJitId,
2545                                             ULONG32  cCodeInfos,
2546                                             ULONG32* pcCodeInfos,
2547                                             COR_PRF_CODE_INFO codeInfos[])
2548
2549
2550 {
2551     CONTRACTL
2552     {
2553         // Yay!
2554         NOTHROW;
2555
2556         // We need to access the rejitmanager, which means taking locks, which means we
2557         // may trigger a GC
2558         GC_TRIGGERS;
2559
2560         // Yay!
2561         MODE_ANY;
2562
2563         // Yay!
2564         EE_THREAD_NOT_REQUIRED;
2565
2566         // We need to access the rejitmanager, which means taking locks
2567         CAN_TAKE_LOCK;
2568         
2569         SO_NOT_MAINLINE;
2570
2571         PRECONDITION(CheckPointer(pcCodeInfos, NULL_OK));
2572         PRECONDITION(CheckPointer(codeInfos, NULL_OK));
2573     }
2574     CONTRACTL_END;
2575
2576     // See code:#DisableLockOnAsyncCalls
2577     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
2578
2579     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
2580         kP2EEAllowableAfterAttach | kP2EETriggers,
2581         (LF_CORPROF, 
2582         LL_INFO1000, 
2583         "**PROF: GetCodeInfo3 0x%p 0x%p.\n", 
2584         functionId, reJitId));         
2585
2586     HRESULT hr = S_OK; 
2587
2588     EX_TRY
2589     {
2590         MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
2591
2592         hr = ValidateParametersForGetCodeInfo(pMethodDesc, cCodeInfos, codeInfos);
2593         if (SUCCEEDED(hr))
2594         {
2595             hr = GetCodeInfoFromCodeStart(
2596                 // Note here that we must consult the rejit manager to determine the code
2597                 // start address
2598                 pMethodDesc->GetReJitManager()->GetCodeStart(pMethodDesc, reJitId),
2599                 cCodeInfos,
2600                 pcCodeInfos,
2601                 codeInfos);
2602         }
2603     }
2604     EX_CATCH_HRESULT(hr);
2605
2606     return hr;
2607 }
2608
2609
2610 HRESULT ProfToEEInterfaceImpl::GetEventMask(DWORD * pdwEvents)
2611 {
2612     CONTRACTL
2613     {
2614         // Yay!
2615         NOTHROW;
2616
2617         // Yay!
2618         GC_NOTRIGGER;
2619
2620         // Yay!
2621         MODE_ANY;
2622
2623         // Yay!
2624         EE_THREAD_NOT_REQUIRED;
2625
2626         // Yay!
2627         CANNOT_TAKE_LOCK;
2628
2629         SO_NOT_MAINLINE;
2630     }
2631     CONTRACTL_END;
2632
2633
2634     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach, 
2635         (LF_CORPROF, 
2636         LL_INFO10, 
2637         "**PROF: GetEventMask.\n"));
2638     
2639     if (pdwEvents == NULL)
2640     {
2641         return E_INVALIDARG;
2642     }
2643
2644     *pdwEvents = g_profControlBlock.dwEventMask;
2645     return S_OK;
2646 }
2647
2648 HRESULT ProfToEEInterfaceImpl::GetEventMask2(DWORD *pdwEventsLow, DWORD *pdwEventsHigh)
2649 {
2650     CONTRACTL
2651     {
2652         // Yay!
2653         NOTHROW;
2654
2655         // Yay!
2656         GC_NOTRIGGER;
2657
2658         // Yay!
2659         MODE_ANY;
2660
2661         // Yay!
2662         EE_THREAD_NOT_REQUIRED;
2663
2664         // Yay!
2665         CANNOT_TAKE_LOCK;
2666
2667         SO_NOT_MAINLINE;
2668     }
2669     CONTRACTL_END;
2670
2671
2672     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach, 
2673         (LF_CORPROF, 
2674         LL_INFO10, 
2675         "**PROF: GetEventMask2.\n"));
2676     
2677     if ((pdwEventsLow == NULL) || (pdwEventsHigh == NULL))
2678     {
2679         return E_INVALIDARG;
2680     }
2681
2682     *pdwEventsLow = g_profControlBlock.dwEventMask;
2683     *pdwEventsHigh = g_profControlBlock.dwEventMaskHigh;
2684     return S_OK;
2685 }
2686
2687 // static
2688 void ProfToEEInterfaceImpl::MethodTableCallback(void* context, void* objectUNSAFE)
2689 {
2690     CONTRACTL
2691     {
2692         NOTHROW;
2693         GC_NOTRIGGER;
2694         SO_NOT_MAINLINE;
2695         MODE_ANY;
2696     } 
2697     CONTRACTL_END;
2698
2699     // each callback identifies the address of a method table within the frozen object segment
2700     // that pointer is an object ID by definition -- object references point to the method table
2701     CDynArray< ObjectID >* objects = reinterpret_cast< CDynArray< ObjectID >* >(context);
2702
2703     *objects->Append() = reinterpret_cast< ObjectID >(objectUNSAFE);
2704 }
2705
2706 // static
2707 void ProfToEEInterfaceImpl::ObjectRefCallback(void* context, void* objectUNSAFE)
2708 {
2709     // we don't care about embedded object references, ignore them
2710 }
2711
2712
2713 HRESULT ProfToEEInterfaceImpl::EnumModuleFrozenObjects(ModuleID moduleID,
2714                                                        ICorProfilerObjectEnum** ppEnum)
2715 {
2716     CONTRACTL
2717     {
2718         // Yay!
2719         NOTHROW;
2720
2721         // Yay!
2722         GC_NOTRIGGER;
2723
2724         // Yay!
2725         MODE_ANY;
2726
2727         // Yay!
2728         EE_THREAD_NOT_REQUIRED;
2729
2730         // Yay!
2731         CANNOT_TAKE_LOCK;
2732
2733         SO_NOT_MAINLINE;
2734     }
2735     CONTRACTL_END;
2736
2737     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
2738         (LF_CORPROF, 
2739          LL_INFO1000, 
2740          "**PROF: EnumModuleFrozenObjects 0x%p.\n", 
2741          moduleID));             
2742     
2743     if (NULL == ppEnum)
2744     {
2745         return E_INVALIDARG;
2746     }
2747
2748     Module* pModule = reinterpret_cast< Module* >(moduleID);
2749     if (pModule == NULL || pModule->IsBeingUnloaded())
2750     {
2751         return CORPROF_E_DATAINCOMPLETE;
2752     }
2753     
2754     HRESULT hr = S_OK;
2755
2756     EX_TRY
2757     {
2758         // If we don't support frozen objects at all, then just return empty
2759         // enumerator.
2760         *ppEnum = new ProfilerObjectEnum();
2761     }
2762     EX_CATCH_HRESULT(hr);
2763
2764     return hr;
2765 }
2766
2767
2768
2769 /*
2770  * GetArrayObjectInfo
2771  *
2772  * This function returns informatin about array objects.  In particular, the dimensions
2773  * and where the data buffer is stored.
2774  *
2775  */
2776 HRESULT ProfToEEInterfaceImpl::GetArrayObjectInfo(ObjectID objectId,
2777                     ULONG32 cDimensionSizes,
2778                     ULONG32 pDimensionSizes[],
2779                     int pDimensionLowerBounds[],
2780                     BYTE    **ppData)
2781 {
2782     CONTRACTL
2783     {
2784         // Yay!
2785         NOTHROW;
2786
2787         // Yay!
2788         GC_NOTRIGGER;
2789
2790         // Yay!  Fail at runtime if in preemptive mode via AllowObjectInspection()
2791         MODE_ANY;
2792
2793         // Yay!
2794         CANNOT_TAKE_LOCK;
2795
2796         SO_NOT_MAINLINE;
2797     }
2798     CONTRACTL_END;
2799
2800     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
2801         (LF_CORPROF, 
2802          LL_INFO1000, 
2803          "**PROF: GetArrayObjectInfo 0x%p.\n", 
2804          objectId));
2805     
2806     if (objectId == NULL)
2807     {
2808         return E_INVALIDARG;
2809     }
2810
2811     if ((pDimensionSizes == NULL) ||
2812         (pDimensionLowerBounds == NULL) ||
2813         (ppData == NULL))
2814     {
2815         return E_INVALIDARG;
2816     }
2817
2818     HRESULT hr = AllowObjectInspection();
2819     if (FAILED(hr))
2820     {
2821         return hr;
2822     }
2823
2824     Object * pObj = reinterpret_cast<Object *>(objectId);
2825
2826     // GC callbacks may come from a non-EE thread, which is considered permanently preemptive.
2827     // We are about calling some object inspection functions, which require to be in co-op mode.
2828     // Given that none managed objects can be changed by managed code until GC resumes the 
2829     // runtime, it is safe to violate the mode contract and to inspect managed objects from a 
2830     // non-EE thread when GetArrayObjectInfo is called within GC callbacks.
2831     if (NativeThreadInGC())
2832     {
2833         CONTRACT_VIOLATION(ModeViolation);
2834         return GetArrayObjectInfoHelper(pObj, cDimensionSizes, pDimensionSizes, pDimensionLowerBounds, ppData);
2835     }
2836
2837     return GetArrayObjectInfoHelper(pObj, cDimensionSizes, pDimensionSizes, pDimensionLowerBounds, ppData);
2838 }
2839
2840 HRESULT ProfToEEInterfaceImpl::GetArrayObjectInfoHelper(Object * pObj,
2841                     ULONG32 cDimensionSizes,
2842                     __out_ecount(cDimensionSizes) ULONG32 pDimensionSizes[],
2843                     __out_ecount(cDimensionSizes) int pDimensionLowerBounds[],
2844                     BYTE    **ppData)
2845 {
2846     CONTRACTL
2847     {
2848         // Yay!
2849         NOTHROW;
2850
2851         // Yay!
2852         GC_NOTRIGGER;
2853
2854         // Because of the object pointer parameter, we must be either in CO-OP mode, 
2855         // or on a non-EE thread in the process of doing a GC .
2856         if (!NativeThreadInGC()) { MODE_COOPERATIVE; }
2857
2858         // Yay!
2859         CANNOT_TAKE_LOCK;
2860
2861         SO_NOT_MAINLINE;
2862     }
2863     CONTRACTL_END;
2864
2865     // Must have an array.
2866     MethodTable * pMT = pObj->GetTrueMethodTable();
2867     if (!pMT->IsArray())
2868     {
2869         return E_INVALIDARG;
2870     }
2871
2872     ArrayBase * pArray = static_cast<ArrayBase*> (pObj);
2873
2874     unsigned rank = pArray->GetRank();
2875
2876     if (cDimensionSizes < rank)
2877     {
2878         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
2879     }
2880
2881     // Copy range for each dimension (rank)
2882     int * pBounds      = pArray->GetBoundsPtr();
2883     int * pLowerBounds = pArray->GetLowerBoundsPtr();
2884
2885     unsigned i;
2886     for(i = 0; i < rank; i++)
2887     {
2888         pDimensionSizes[i]       = pBounds[i];
2889         pDimensionLowerBounds[i] = pLowerBounds[i];
2890     }
2891
2892     // Pointer to data.
2893     *ppData = pArray->GetDataPtr();
2894
2895     return S_OK;
2896 }
2897
2898 /*
2899  * GetBoxClassLayout
2900  *
2901  * Returns information about how a particular value type is laid out.
2902  *
2903  */
2904 HRESULT ProfToEEInterfaceImpl::GetBoxClassLayout(ClassID classId,
2905                                                 ULONG32 *pBufferOffset)
2906 {
2907     CONTRACTL
2908     {
2909         // Yay!
2910         NOTHROW;
2911
2912         // Yay!
2913         GC_NOTRIGGER;
2914
2915         // Yay!
2916         MODE_ANY;
2917
2918         // Yay!
2919         EE_THREAD_NOT_REQUIRED;
2920
2921         // Yay!
2922         CANNOT_TAKE_LOCK;
2923
2924         SO_NOT_MAINLINE;
2925     }
2926     CONTRACTL_END;
2927
2928     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
2929         (LF_CORPROF, 
2930          LL_INFO1000, 
2931          "**PROF: GetBoxClassLayout 0x%p.\n", 
2932          classId));             
2933     
2934     if (pBufferOffset == NULL)
2935     {
2936         return E_INVALIDARG;
2937     }
2938
2939     if (classId == NULL)
2940     {
2941         return E_INVALIDARG;
2942     }
2943
2944     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
2945
2946     //
2947     // This is the incorrect API for arrays.  Use GetArrayInfo and GetArrayLayout.
2948     //
2949     if (!typeHandle.IsValueType())
2950     {
2951         return E_INVALIDARG;
2952     }
2953
2954     *pBufferOffset = Object::GetOffsetOfFirstField();
2955
2956     return S_OK;
2957 }
2958
2959 /*
2960  * GetThreadAppDomain
2961  *
2962  * Returns the app domain currently associated with the given thread.
2963  *
2964  */
2965 HRESULT ProfToEEInterfaceImpl::GetThreadAppDomain(ThreadID threadId,
2966                                                   AppDomainID *pAppDomainId)
2967
2968 {
2969     CONTRACTL
2970     {
2971         // Yay!
2972         NOTHROW;
2973
2974         // Yay!
2975         GC_NOTRIGGER;
2976
2977         // Yay!
2978         MODE_ANY;
2979
2980         // Yay!
2981         EE_THREAD_NOT_REQUIRED;
2982
2983         // Yay!
2984         CANNOT_TAKE_LOCK;
2985
2986         SO_NOT_MAINLINE;
2987     }
2988     CONTRACTL_END;
2989
2990     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
2991         (LF_CORPROF,
2992          LL_INFO1000, 
2993          "**PROF: GetThreadAppDomain 0x%p.\n", 
2994          threadId));
2995
2996     if (pAppDomainId == NULL)
2997     {
2998         return E_INVALIDARG;
2999     }
3000
3001     Thread *pThread;
3002
3003     if (threadId == NULL)
3004     {
3005         pThread = GetThreadNULLOk();
3006     }
3007     else
3008     {
3009         pThread = (Thread *)threadId;
3010     }
3011
3012     //
3013     // If pThread is null, then the thread has never run managed code and
3014     // so has no ThreadID.
3015     //
3016     if (!IsManagedThread(pThread))
3017     {
3018         return CORPROF_E_NOT_MANAGED_THREAD;
3019     }
3020
3021     *pAppDomainId = (AppDomainID)pThread->GetDomain();
3022
3023     return S_OK;
3024 }
3025
3026
3027 /*
3028  * GetRVAStaticAddress
3029  *
3030  * This function returns the absolute address of the given field in the given
3031  * class.  The field must be an RVA Static token.
3032  *
3033  * Parameters:
3034  *    classId - the containing class.
3035  *    fieldToken - the field we are querying.
3036  *    pAddress - location for storing the resulting address location.
3037  *
3038  * Returns:
3039  *    S_OK on success,
3040  *    E_INVALIDARG if not an RVA static,
3041  *    CORPROF_E_DATAINCOMPLETE if not yet initialized.
3042  *
3043  */
3044 HRESULT ProfToEEInterfaceImpl::GetRVAStaticAddress(ClassID classId,
3045                                                    mdFieldDef fieldToken,
3046                                                    void **ppAddress)
3047 {
3048     CONTRACTL
3049     {
3050         // Yay!
3051         NOTHROW;
3052
3053         // Yay!
3054         GC_NOTRIGGER;
3055
3056         // Yay!
3057         MODE_ANY;
3058
3059         // FieldDesc::GetStaticAddress takes a lock
3060         CAN_TAKE_LOCK;
3061
3062         SO_NOT_MAINLINE;
3063     }
3064     CONTRACTL_END;
3065
3066     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
3067         (LF_CORPROF, 
3068          LL_INFO1000, 
3069          "**PROF: GetRVAStaticAddress 0x%p, 0x%08x.\n", 
3070          classId, 
3071          fieldToken));
3072     
3073     //
3074     // Check for NULL parameters
3075     //
3076     if ((classId == NULL) || (ppAddress == NULL))
3077     {
3078         return E_INVALIDARG;
3079     }
3080
3081     if (GetThread() == NULL)
3082     {
3083         return CORPROF_E_NOT_MANAGED_THREAD;
3084     }
3085
3086     if (GetAppDomain() == NULL)
3087     {
3088         return E_FAIL;
3089     }
3090
3091     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
3092
3093     //
3094     // If this class is not fully restored, that is all the information we can get at this time.
3095     //
3096     if (!typeHandle.IsRestored())
3097     {
3098         return CORPROF_E_DATAINCOMPLETE;
3099     }
3100
3101     //
3102     // Get the field descriptor object
3103     //
3104     FieldDesc *pFieldDesc = typeHandle.GetModule()->LookupFieldDef(fieldToken);
3105
3106     if (pFieldDesc == NULL)
3107     {
3108         return E_INVALIDARG;
3109     }
3110
3111     //
3112     // Verify this field is of the right type
3113     //
3114     if(!pFieldDesc->IsStatic() ||
3115        !pFieldDesc->IsRVA() ||
3116        pFieldDesc->IsThreadStatic() || 
3117        pFieldDesc->IsContextStatic())
3118     {
3119         return E_INVALIDARG;
3120     }
3121
3122     // It may seem redundant to try to retrieve the same method table from GetEnclosingMethodTable, but classId 
3123     // leads to the instantiated method table while GetEnclosingMethodTable returns the uninstantiated one.
3124     MethodTable *pMethodTable = pFieldDesc->GetEnclosingMethodTable();
3125
3126     //
3127     // Check that the data is available
3128     //
3129     if (!IsClassOfMethodTableInited(pMethodTable, GetAppDomain()))
3130     {
3131         return CORPROF_E_DATAINCOMPLETE;
3132     }
3133
3134     //
3135     // Store the result and return
3136     //
3137     PTR_VOID pAddress = pFieldDesc->GetStaticAddress(NULL);
3138     if (pAddress == NULL)
3139     {
3140         return CORPROF_E_DATAINCOMPLETE;
3141     }
3142
3143     *ppAddress = pAddress;
3144
3145     return S_OK;
3146 }
3147
3148
3149 /*
3150  * GetAppDomainStaticAddress
3151  *
3152  * This function returns the absolute address of the given field in the given
3153  * class in the given app domain.  The field must be an App Domain Static token.
3154  *
3155  * Parameters:
3156  *    classId - the containing class.
3157  *    fieldToken - the field we are querying.
3158  *    appDomainId - the app domain container.
3159  *    pAddress - location for storing the resulting address location.
3160  *
3161  * Returns:
3162  *    S_OK on success,
3163  *    E_INVALIDARG if not an app domain static,
3164  *    CORPROF_E_DATAINCOMPLETE if not yet initialized.
3165  *
3166  */
3167 HRESULT ProfToEEInterfaceImpl::GetAppDomainStaticAddress(ClassID classId,
3168                                                          mdFieldDef fieldToken,
3169                                                          AppDomainID appDomainId,
3170                                                          void **ppAddress)
3171 {
3172     CONTRACTL
3173     {
3174         // Yay!
3175         NOTHROW;
3176
3177         // Yay!
3178         GC_NOTRIGGER;
3179
3180         // Yay!
3181         MODE_ANY;
3182
3183         // Yay!
3184         EE_THREAD_NOT_REQUIRED;
3185
3186         // FieldDesc::GetStaticAddress & FieldDesc::GetBaseInDomain take locks
3187         CAN_TAKE_LOCK;
3188
3189         SO_NOT_MAINLINE;
3190     }
3191     CONTRACTL_END;
3192
3193     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
3194         (LF_CORPROF, 
3195          LL_INFO1000, 
3196          "**PROF: GetAppDomainStaticAddress 0x%p, 0x%08x, 0x%p.\n",
3197          classId, 
3198          fieldToken, 
3199          appDomainId));
3200     
3201     //
3202     // Check for NULL parameters
3203     //
3204     if ((classId == NULL) || (appDomainId == NULL) || (ppAddress == NULL))
3205     {
3206         return E_INVALIDARG;
3207     }
3208
3209     // Some domains, like the system domain, aren't APP domains, and thus don't contain any
3210     // statics.  See if the profiler is trying to be naughty.
3211     if (!((BaseDomain*) appDomainId)->IsAppDomain())
3212     {
3213         return E_INVALIDARG;
3214     }
3215
3216     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
3217
3218     //
3219     // If this class is not fully restored, that is all the information we can get at this time.
3220     //
3221     if (!typeHandle.IsRestored())
3222     {
3223         return CORPROF_E_DATAINCOMPLETE;
3224     }
3225
3226     //
3227     // Get the field descriptor object
3228     //
3229     FieldDesc *pFieldDesc = typeHandle.GetModule()->LookupFieldDef(fieldToken);
3230
3231     if (pFieldDesc == NULL)
3232     {
3233         //
3234         // Give specific error code for literals.
3235         //
3236         DWORD dwFieldAttrs;
3237         if (FAILED(typeHandle.GetModule()->GetMDImport()->GetFieldDefProps(fieldToken, &dwFieldAttrs)))
3238         {
3239             return E_INVALIDARG;
3240         }
3241         
3242         if (IsFdLiteral(dwFieldAttrs))
3243         {
3244             return CORPROF_E_LITERALS_HAVE_NO_ADDRESS;
3245         }
3246
3247         return E_INVALIDARG;
3248     }
3249
3250     //
3251     // Verify this field is of the right type
3252     //
3253     if(!pFieldDesc->IsStatic() ||
3254        pFieldDesc->IsRVA() ||
3255        pFieldDesc->IsThreadStatic() ||
3256        pFieldDesc->IsContextStatic())
3257     {
3258         return E_INVALIDARG;
3259     }
3260
3261     // It may seem redundant to try to retrieve the same method table from GetEnclosingMethodTable, but classId 
3262     // leads to the instantiated method table while GetEnclosingMethodTable returns the uninstantiated one.
3263     MethodTable *pMethodTable = pFieldDesc->GetEnclosingMethodTable();
3264     AppDomain * pAppDomain = (AppDomain *)appDomainId;
3265
3266     //
3267     // Check that the data is available
3268     //
3269     if (!IsClassOfMethodTableInited(pMethodTable, pAppDomain))
3270     {
3271         return CORPROF_E_DATAINCOMPLETE;
3272     }
3273
3274     //
3275     // Get the address
3276     //
3277     void *base = (void*)pFieldDesc->GetBaseInDomain(pAppDomain);
3278
3279     if (base == NULL)
3280     {
3281         return CORPROF_E_DATAINCOMPLETE;
3282     }
3283
3284     //
3285     // Store the result and return
3286     //
3287     PTR_VOID pAddress = pFieldDesc->GetStaticAddress(base);
3288     if (pAddress == NULL)
3289     {
3290         return E_INVALIDARG;
3291     }
3292
3293     *ppAddress = pAddress;
3294
3295     return S_OK;
3296 }
3297
3298 /*
3299  * GetThreadStaticAddress
3300  *
3301  * This function returns the absolute address of the given field in the given
3302  * class on the given thread.  The field must be an Thread Static token. threadId 
3303  * must be the current thread ID or NULL, which means using curernt thread ID.
3304  *
3305  * Parameters:
3306  *    classId - the containing class.
3307  *    fieldToken - the field we are querying.
3308  *    threadId - the thread container, which has to be the current managed thread or 
3309  *               NULL, which means to use the current managed thread.
3310  *    pAddress - location for storing the resulting address location.
3311  *
3312  * Returns:
3313  *    S_OK on success,
3314  *    E_INVALIDARG if not a thread static,
3315  *    CORPROF_E_DATAINCOMPLETE if not yet initialized.
3316  *
3317  */
3318 HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress(ClassID classId,
3319                                                       mdFieldDef fieldToken,
3320                                                       ThreadID threadId,
3321                                                       void **ppAddress)
3322 {
3323     CONTRACTL
3324     {
3325         // Yay!
3326         NOTHROW;
3327
3328         // Yay!
3329         GC_NOTRIGGER;
3330
3331         // Yay!
3332         MODE_ANY;
3333
3334         // Yay!
3335         CANNOT_TAKE_LOCK;
3336
3337         SO_NOT_MAINLINE;
3338     }
3339     CONTRACTL_END;
3340
3341     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
3342         (LF_CORPROF, 
3343          LL_INFO1000, 
3344          "**PROF: GetThreadStaticAddress 0x%p, 0x%08x, 0x%p.\n",
3345          classId, 
3346          fieldToken, 
3347          threadId));
3348
3349     //
3350     // Verify the value of threadId, which must be the current thread ID or NULL, which means using curernt thread ID.
3351     //
3352     if ((threadId != NULL) && (threadId != ((ThreadID)GetThread())))
3353     {
3354         return E_INVALIDARG;
3355     }
3356
3357     threadId = reinterpret_cast<ThreadID>(GetThread());
3358     AppDomainID appDomainId = reinterpret_cast<AppDomainID>(GetAppDomain());
3359
3360     //
3361     // Check for NULL parameters
3362     //
3363     if ((classId == NULL) || (ppAddress == NULL) || !IsManagedThread(threadId) || (appDomainId == NULL))
3364     {
3365         return E_INVALIDARG;
3366     }
3367
3368     return GetThreadStaticAddress2(classId,
3369                                    fieldToken,
3370                                    appDomainId,
3371                                    threadId,
3372                                    ppAddress);
3373 }
3374
3375 /*
3376  * GetThreadStaticAddress2
3377  *
3378  * This function returns the absolute address of the given field in the given
3379  * class on the given thread.  The field must be an Thread Static token.
3380  *
3381  * Parameters:
3382  *    classId - the containing class.
3383  *    fieldToken - the field we are querying.
3384  *    appDomainId - the AppDomain container.
3385  *    threadId - the thread container.
3386  *    pAddress - location for storing the resulting address location.
3387  *
3388  * Returns:
3389  *    S_OK on success,
3390  *    E_INVALIDARG if not a thread static,
3391  *    CORPROF_E_DATAINCOMPLETE if not yet initialized.
3392  *
3393  */
3394 HRESULT ProfToEEInterfaceImpl::GetThreadStaticAddress2(ClassID classId,
3395                                                        mdFieldDef fieldToken,
3396                                                        AppDomainID appDomainId,
3397                                                        ThreadID threadId,
3398                                                        void **ppAddress)
3399 {
3400     CONTRACTL
3401     {
3402         // Yay!
3403         NOTHROW;
3404
3405         // Yay!
3406         GC_NOTRIGGER;
3407
3408         // Yay!
3409         MODE_ANY;
3410
3411         // Yay!
3412         CANNOT_TAKE_LOCK;
3413
3414         SO_NOT_MAINLINE;
3415     }
3416     CONTRACTL_END;
3417
3418     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
3419         (LF_CORPROF, 
3420          LL_INFO1000, 
3421          "**PROF: GetThreadStaticAddress2 0x%p, 0x%08x, 0x%p, 0x%p.\n",
3422          classId,
3423          fieldToken,
3424          appDomainId,
3425          threadId));
3426
3427
3428     if (threadId == NULL)
3429     {
3430         if (GetThread() == NULL)
3431         {
3432             return CORPROF_E_NOT_MANAGED_THREAD;
3433         }
3434
3435         threadId = reinterpret_cast<ThreadID>(GetThread());
3436     }
3437
3438     //
3439     // Check for NULL parameters
3440     //
3441     if ((classId == NULL) || (ppAddress == NULL) || !IsManagedThread(threadId) || (appDomainId == NULL))
3442     {
3443         return E_INVALIDARG;
3444     }
3445
3446     // Some domains, like the system domain, aren't APP domains, and thus don't contain any
3447     // statics.  See if the profiler is trying to be naughty.
3448     if (!((BaseDomain*) appDomainId)->IsAppDomain())
3449     {
3450         return E_INVALIDARG;
3451     }
3452
3453     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
3454
3455     //
3456     // If this class is not fully restored, that is all the information we can get at this time.
3457     //
3458     if (!typeHandle.IsRestored())
3459     {
3460         return CORPROF_E_DATAINCOMPLETE;
3461     }
3462
3463     //
3464     // Get the field descriptor object
3465     //
3466     FieldDesc *pFieldDesc = typeHandle.GetModule()->LookupFieldDef(fieldToken);
3467
3468     if (pFieldDesc == NULL)
3469     {
3470         return E_INVALIDARG;
3471     }
3472
3473     //
3474     // Verify this field is of the right type
3475     //
3476     if(!pFieldDesc->IsStatic() ||
3477        !pFieldDesc->IsThreadStatic() ||
3478        pFieldDesc->IsRVA() ||
3479        pFieldDesc->IsContextStatic())
3480     {
3481         return E_INVALIDARG;
3482     }
3483
3484     // It may seem redundant to try to retrieve the same method table from GetEnclosingMethodTable, but classId 
3485     // leads to the instantiated method table while GetEnclosingMethodTable returns the uninstantiated one.
3486     MethodTable *pMethodTable = pFieldDesc->GetEnclosingMethodTable();
3487     AppDomain * pAppDomain = (AppDomain *)appDomainId;
3488
3489     //
3490     // Check that the data is available
3491     //
3492     if (!IsClassOfMethodTableInited(pMethodTable, pAppDomain))
3493     {
3494         return CORPROF_E_DATAINCOMPLETE;
3495     }
3496
3497     //
3498     // Store the result and return
3499     //
3500     PTR_VOID pAddress = (void *)(((Thread *)threadId)->GetStaticFieldAddrNoCreate(pFieldDesc, pAppDomain));
3501     if (pAddress == NULL)
3502     {
3503         return E_INVALIDARG;
3504     }
3505
3506     *ppAddress = pAddress;
3507
3508     return S_OK;
3509 }
3510
3511 /*
3512  * GetContextStaticAddress
3513  *
3514  * This function returns the absolute address of the given field in the given
3515  * class in the given context.  The field must be an Context Static token.
3516  *
3517  * Parameters:
3518  *    classId - the containing class.
3519  *    fieldToken - the field we are querying.
3520  *    contextId - the context container.
3521  *    pAddress - location for storing the resulting address location.
3522  *
3523  * Returns:
3524  *    S_OK on success,
3525  *    E_INVALIDARG if not a context static,
3526  *    CORPROF_E_DATAINCOMPLETE if not yet initialized.
3527  *
3528  */
3529 HRESULT ProfToEEInterfaceImpl::GetContextStaticAddress(ClassID classId,
3530                                                        mdFieldDef fieldToken,
3531                                                        ContextID contextId,
3532                                                        void **ppAddress)
3533 {
3534     CONTRACTL
3535     {
3536         // Yay!
3537         NOTHROW;
3538
3539         // Yay!
3540         GC_NOTRIGGER;
3541
3542         // Yay!
3543         MODE_ANY;
3544
3545         // Yay!
3546         CANNOT_TAKE_LOCK;
3547
3548         SO_NOT_MAINLINE;
3549     }
3550     CONTRACTL_END;
3551
3552     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
3553         (LF_CORPROF, 
3554          LL_INFO1000, 
3555          "**PROF: GetContextStaticAddress 0x%p, 0x%08x, 0x%p.\n", 
3556          classId, 
3557          fieldToken, 
3558          contextId));
3559     
3560 #ifdef FEATURE_REMOTING
3561
3562     //
3563     // Check for NULL parameters
3564     //
3565     if ((classId == NULL) || (contextId == NULL) || (ppAddress == NULL))
3566     {
3567         return E_INVALIDARG;
3568     }
3569
3570     if (GetThread() == NULL)
3571     {
3572         return CORPROF_E_NOT_MANAGED_THREAD;
3573     }
3574
3575     if (GetAppDomain() == NULL)
3576     {
3577         return E_FAIL;
3578     }
3579
3580     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
3581
3582     //
3583     // If this class is not fully restored, that is all the information we can get at this time.
3584     //
3585     if (!typeHandle.IsRestored())
3586     {
3587         return CORPROF_E_DATAINCOMPLETE;
3588     }
3589
3590     //
3591     // Get the field descriptor object
3592     //
3593     FieldDesc *pFieldDesc = typeHandle.GetModule()->LookupFieldDef(fieldToken);
3594
3595     if (pFieldDesc == NULL)
3596     {
3597         return E_INVALIDARG;
3598     }
3599
3600     //
3601     // Verify this field is of the right type
3602     //
3603     if(!pFieldDesc->IsStatic() ||
3604        !pFieldDesc->IsContextStatic() ||
3605        pFieldDesc->IsRVA() ||
3606        pFieldDesc->IsThreadStatic())
3607     {
3608         return E_INVALIDARG;
3609     }
3610
3611     // It may seem redundant to try to retrieve the same method table from GetEnclosingMethodTable, but classId 
3612     // leads to the instantiated method table while GetEnclosingMethodTable returns the uninstantiated one.
3613     MethodTable *pMethodTable = pFieldDesc->GetEnclosingMethodTable();
3614
3615     //
3616     // Check that the data is available
3617     //
3618     if (!IsClassOfMethodTableInited(pMethodTable, GetAppDomain()))
3619     {
3620         return CORPROF_E_DATAINCOMPLETE;
3621     }
3622
3623     //
3624     // Get the context
3625     //
3626     Context *pContext = reinterpret_cast<Context *>(contextId);
3627
3628     //
3629     // Store the result and return
3630     //
3631     PTR_VOID pAddress = pContext->GetStaticFieldAddrNoCreate(pFieldDesc);
3632     if (pAddress == NULL)
3633     {
3634         return E_INVALIDARG;
3635     }
3636
3637     *ppAddress = pAddress;
3638
3639     return S_OK;
3640
3641 #else // FEATURE_REMOTING
3642     return E_NOTIMPL;
3643 #endif // FEATURE_REMOTING
3644 }
3645
3646 /*
3647  * GetAppDomainsContainingModule
3648  *
3649  * This function returns the AppDomains in which the given module has been loaded    
3650  *
3651  * Parameters:
3652  *    moduleId - the module with static variables.
3653  *    cAppDomainIds - the input size of appDomainIds array.
3654  *    pcAppDomainIds - the output size of appDomainIds array.
3655  *    appDomainIds - the array to be filled up with AppDomainIDs containing initialized 
3656  *                   static variables from the moduleId's moudle.
3657  *
3658  * Returns:
3659  *    S_OK on success,
3660  *    E_INVALIDARG for invalid parameters,
3661  *    CORPROF_E_DATAINCOMPLETE if moduleId's module is not yet initialized.
3662  *
3663  */
3664 HRESULT ProfToEEInterfaceImpl::GetAppDomainsContainingModule(ModuleID moduleId,
3665                                                              ULONG32 cAppDomainIds,
3666                                                              ULONG32 * pcAppDomainIds, 
3667                                                              AppDomainID appDomainIds[])
3668 {
3669     CONTRACTL
3670     {
3671         // Yay!
3672         NOTHROW;
3673
3674         // This method iterates over AppDomains, which adds, then releases, a reference on 
3675         // each AppDomain iterated.  This causes locking, and can cause triggering if the 
3676         // AppDomain gets destroyed as a result of the release. (See code:AppDomainIterator::Next 
3677         // and its call to code:AppDomain::Release.)
3678         GC_TRIGGERS;
3679
3680         // Yay!
3681         MODE_ANY;
3682
3683         // (See comment above GC_TRIGGERS.)
3684         CAN_TAKE_LOCK;
3685
3686         SO_NOT_MAINLINE;
3687     }
3688     CONTRACTL_END;
3689
3690     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
3691         kP2EEAllowableAfterAttach | kP2EETriggers,
3692         (LF_CORPROF, 
3693          LL_INFO1000, 
3694          "**PROF: GetAppDomainsContainingModule 0x%p, 0x%08x, 0x%p, 0x%p.\n",
3695          moduleId,
3696          cAppDomainIds,
3697          pcAppDomainIds,
3698          appDomainIds));
3699
3700
3701     //
3702     // Check for NULL parameters
3703     //
3704     if ((moduleId == NULL) || ((appDomainIds == NULL) && (cAppDomainIds != 0)) || (pcAppDomainIds == NULL))
3705     {
3706         return E_INVALIDARG;
3707     }
3708    
3709     Module* pModule = reinterpret_cast< Module* >(moduleId);
3710     if (pModule->IsBeingUnloaded())
3711     {
3712         return CORPROF_E_DATAINCOMPLETE;
3713     }
3714
3715     // IterateAppDomainContainingModule uses AppDomainIterator, which cannot be called while the current thread
3716     // is holding the ThreadStore lock.
3717     if (ThreadStore::HoldingThreadStore())
3718     {
3719         return CORPROF_E_UNSUPPORTED_CALL_SEQUENCE;
3720     }
3721
3722     IterateAppDomainContainingModule iterateAppDomainContainingModule(pModule, cAppDomainIds, pcAppDomainIds, appDomainIds);
3723
3724     return iterateAppDomainContainingModule.PopulateArray();
3725 }
3726
3727
3728
3729 /*
3730  * GetStaticFieldInfo
3731  *
3732  * This function returns a bit mask of the type of statics the
3733  * given field is.
3734  *
3735  * Parameters:
3736  *    classId - the containing class.
3737  *    fieldToken - the field we are querying.
3738  *    pFieldInfo - location for storing the resulting bit mask.
3739  *
3740  * Returns:
3741  *    S_OK on success,
3742  *    E_INVALIDARG if pFieldInfo is NULL
3743  *
3744  */
3745 HRESULT ProfToEEInterfaceImpl::GetStaticFieldInfo(ClassID classId,
3746                                                   mdFieldDef fieldToken,
3747                                                   COR_PRF_STATIC_TYPE *pFieldInfo)
3748 {
3749     CONTRACTL
3750     {
3751         // Yay!
3752         NOTHROW;
3753
3754         // Yay!
3755         GC_NOTRIGGER;
3756
3757         // Yay!
3758         MODE_ANY;
3759
3760         // Yay!
3761         EE_THREAD_NOT_REQUIRED;
3762
3763         // Yay!
3764         CANNOT_TAKE_LOCK;
3765
3766         SO_NOT_MAINLINE;
3767     }
3768     CONTRACTL_END;
3769
3770     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
3771         (LF_CORPROF, 
3772          LL_INFO1000, 
3773          "**PROF: GetStaticFieldInfo 0x%p, 0x%08x.\n", 
3774          classId, 
3775          fieldToken));
3776     
3777     //
3778     // Check for NULL parameters
3779     //
3780     if ((classId == NULL) || (pFieldInfo == NULL))
3781     {
3782         return E_INVALIDARG;
3783     }
3784
3785     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
3786
3787     //
3788     // If this class is not fully restored, that is all the information we can get at this time.
3789     //
3790     if (!typeHandle.IsRestored())
3791     {
3792         return CORPROF_E_DATAINCOMPLETE;
3793     }
3794
3795     //
3796     // Get the field descriptor object
3797     //
3798     FieldDesc *pFieldDesc = typeHandle.GetModule()->LookupFieldDef(fieldToken);
3799
3800     if (pFieldDesc == NULL)
3801     {
3802         return E_INVALIDARG;
3803     }
3804
3805     *pFieldInfo = COR_PRF_FIELD_NOT_A_STATIC;
3806
3807     if (pFieldDesc->IsContextStatic())
3808     {
3809         *pFieldInfo = (COR_PRF_STATIC_TYPE)(*pFieldInfo | COR_PRF_FIELD_CONTEXT_STATIC);
3810     }
3811
3812     if (pFieldDesc->IsRVA())
3813     {
3814         *pFieldInfo = (COR_PRF_STATIC_TYPE)(*pFieldInfo | COR_PRF_FIELD_RVA_STATIC);
3815     }
3816
3817     if (pFieldDesc->IsThreadStatic())
3818     {
3819         *pFieldInfo = (COR_PRF_STATIC_TYPE)(*pFieldInfo | COR_PRF_FIELD_THREAD_STATIC);
3820     }
3821
3822     if ((*pFieldInfo == COR_PRF_FIELD_NOT_A_STATIC) && pFieldDesc->IsStatic())
3823     {
3824         *pFieldInfo = (COR_PRF_STATIC_TYPE)(*pFieldInfo | COR_PRF_FIELD_APP_DOMAIN_STATIC);
3825     }
3826
3827     return S_OK;
3828 }
3829
3830
3831
3832 /*
3833  * GetClassIDInfo2
3834  *
3835  * This function generalizes GetClassIDInfo for all types, both generic and non-generic.  It returns
3836  * the module, type token, and an array of instantiation classIDs that were used to instantiate the
3837  * given classId.
3838  *
3839  * Parameters:
3840  *   classId - The classId (TypeHandle) to query information about.
3841  *   pParentClassId - The ClassID (TypeHandle) of the parent class.
3842  *   pModuleId - An optional parameter for returning the module of the class.
3843  *   pTypeDefToken - An optional parameter for returning the metadata token of the class.
3844  *   cNumTypeArgs - The count of the size of the array typeArgs
3845  *   pcNumTypeArgs - Returns the number of elements of typeArgs filled in, or if typeArgs is NULL
3846  *         the number that would be needed.
3847  *   typeArgs - An array to store generic type parameters for the class.
3848  *
3849  * Returns:
3850  *   S_OK if successful.
3851  */
3852 HRESULT ProfToEEInterfaceImpl::GetClassIDInfo2(ClassID classId,
3853                                             ModuleID *pModuleId,
3854                                             mdTypeDef *pTypeDefToken,
3855                                             ClassID *pParentClassId,
3856                                             ULONG32 cNumTypeArgs,
3857                                             ULONG32 *pcNumTypeArgs,
3858                                             ClassID typeArgs[])
3859 {
3860
3861     CONTRACTL
3862     {
3863         // Yay!
3864         NOTHROW;
3865
3866         // Yay!
3867         GC_NOTRIGGER;
3868
3869         // Yay!
3870         MODE_ANY;
3871
3872         // Yay!
3873         EE_THREAD_NOT_REQUIRED;
3874
3875         // Yay!
3876         CANNOT_TAKE_LOCK;
3877
3878         SO_NOT_MAINLINE;
3879
3880         PRECONDITION(CheckPointer(pParentClassId, NULL_OK));
3881         PRECONDITION(CheckPointer(pModuleId, NULL_OK));
3882         PRECONDITION(CheckPointer(pTypeDefToken,  NULL_OK));
3883         PRECONDITION(CheckPointer(pcNumTypeArgs, NULL_OK));
3884         PRECONDITION(CheckPointer(typeArgs, NULL_OK));
3885     }
3886     CONTRACTL_END;
3887
3888     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
3889         (LF_CORPROF, 
3890         LL_INFO1000, 
3891         "**PROF: GetClassIDInfo2 0x%p.\n", 
3892         classId));
3893     
3894     //
3895     // Verify parameters.
3896     //
3897     if (classId == NULL)
3898     {
3899         return E_INVALIDARG;
3900     }
3901
3902     if ((cNumTypeArgs != 0) && (typeArgs == NULL))
3903     {
3904         return E_INVALIDARG;
3905     }
3906
3907     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
3908
3909     //
3910     // If this class is not fully restored, that is all the information we can get at this time.
3911     //
3912     if (!typeHandle.IsRestored())
3913     {
3914         return CORPROF_E_DATAINCOMPLETE;
3915     }
3916
3917     //
3918     // Handle globals which don't have the instances.
3919     //
3920     if (classId == PROFILER_GLOBAL_CLASS)
3921     {
3922         if (pParentClassId != NULL)
3923         {
3924             *pParentClassId = NULL;
3925         }
3926
3927         if (pModuleId != NULL)
3928         {
3929             *pModuleId = PROFILER_GLOBAL_MODULE;
3930         }
3931
3932         if (pTypeDefToken != NULL)
3933         {
3934             *pTypeDefToken = mdTokenNil;
3935         }
3936
3937         return S_OK;
3938     }
3939
3940     //
3941     // Do not do arrays via this API
3942     //
3943     ARRAY_KIND arrayKind = ArrayKindFromTypeHandle(typeHandle); 
3944     if (arrayKind == ARRAY_KIND_TYPEDESC || arrayKind == ARRAY_KIND_METHODTABLE)
3945     {
3946         return CORPROF_E_CLASSID_IS_ARRAY;
3947     }
3948
3949     _ASSERTE (arrayKind == ARRAY_KIND_NOTARRAY);
3950     
3951     if (typeHandle.IsTypeDesc())
3952     {
3953         // Not an array, but still a typedesc?  We don't know how to
3954         // deal with those.
3955         return CORPROF_E_CLASSID_IS_COMPOSITE;
3956     }
3957
3958     //
3959     // Fill in the basic information
3960     //
3961     if (pParentClassId != NULL)
3962     {
3963         TypeHandle parentTypeHandle = typeHandle.GetParent();
3964         if (!parentTypeHandle.IsNull())
3965         {
3966             *pParentClassId = TypeHandleToClassID(parentTypeHandle);
3967         }
3968         else
3969         {
3970             *pParentClassId = NULL;
3971         }
3972     }
3973
3974     if (pModuleId != NULL)
3975     {
3976         *pModuleId = (ModuleID) typeHandle.GetModule();
3977         _ASSERTE(*pModuleId != NULL);
3978     }
3979
3980     if (pTypeDefToken != NULL)
3981     {
3982         *pTypeDefToken = typeHandle.GetCl();
3983         _ASSERTE(*pTypeDefToken != NULL);
3984     }
3985
3986     //
3987     // See if they are just looking to get the buffer size.
3988     //
3989     if (cNumTypeArgs == 0)
3990     {
3991         if (pcNumTypeArgs != NULL)
3992         {
3993             *pcNumTypeArgs = typeHandle.GetMethodTable()->GetNumGenericArgs();
3994         }
3995         return S_OK;
3996     }
3997
3998     //
3999     // Adjust the count for the size of the given array.
4000     //
4001     if (cNumTypeArgs > typeHandle.GetMethodTable()->GetNumGenericArgs())
4002     {
4003         cNumTypeArgs = typeHandle.GetMethodTable()->GetNumGenericArgs();
4004     }
4005
4006     if (pcNumTypeArgs != NULL)
4007     {
4008         *pcNumTypeArgs = cNumTypeArgs;
4009     }
4010
4011     //
4012     // Copy over the instantiating types.
4013     //
4014     ULONG32 count;
4015     Instantiation inst = typeHandle.GetMethodTable()->GetInstantiation();
4016
4017     for (count = 0; count < cNumTypeArgs; count ++)
4018     {
4019         typeArgs[count] = TypeHandleToClassID(inst[count]);
4020     }
4021
4022     return S_OK;
4023 }
4024
4025 HRESULT ProfToEEInterfaceImpl::GetModuleInfo(ModuleID     moduleId,
4026     LPCBYTE *    ppBaseLoadAddress,
4027     ULONG        cchName,
4028     ULONG *      pcchName,
4029     __out_ecount_part_opt(cchName, *pcchName) WCHAR wszName[],
4030     AssemblyID * pAssemblyId)
4031 {
4032     CONTRACTL
4033     {
4034         // Yay!
4035         NOTHROW;
4036         
4037         // Yay!
4038         GC_NOTRIGGER; 
4039
4040         // See comment in code:ProfToEEInterfaceImpl::GetModuleInfo2
4041         CAN_TAKE_LOCK;
4042
4043         // Yay!
4044         MODE_ANY;
4045
4046         // Yay!
4047         EE_THREAD_NOT_REQUIRED;
4048
4049         SO_NOT_MAINLINE;
4050
4051         PRECONDITION(CheckPointer((Module *)moduleId, NULL_OK));
4052         PRECONDITION(CheckPointer(ppBaseLoadAddress,  NULL_OK));
4053         PRECONDITION(CheckPointer(pcchName, NULL_OK));
4054         PRECONDITION(CheckPointer(wszName, NULL_OK));
4055         PRECONDITION(CheckPointer(pAssemblyId, NULL_OK));
4056     }
4057     CONTRACTL_END;
4058
4059     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
4060         (LF_CORPROF, 
4061         LL_INFO1000, 
4062         "**PROF: GetModuleInfo 0x%p.\n", 
4063         moduleId));    
4064
4065     // Paramter validation is taken care of in GetModuleInfo2.
4066
4067     return GetModuleInfo2(
4068         moduleId,
4069         ppBaseLoadAddress,
4070         cchName,
4071         pcchName,
4072         wszName,
4073         pAssemblyId,
4074         NULL);          // Don't need module type
4075 }
4076
4077 //---------------------------------------------------------------------------------------
4078 //
4079 // Helper used by GetModuleInfo2 to determine the bitmask of COR_PRF_MODULE_FLAGS for
4080 // the specified module. 
4081 //
4082 // Arguments:
4083 //      pModule - Module to get the flags for
4084 //
4085 // Return Value:
4086 //      Bitmask of COR_PRF_MODULE_FLAGS corresponding to pModule
4087 //
4088
4089 DWORD ProfToEEInterfaceImpl::GetModuleFlags(Module * pModule)
4090 {
4091     CONTRACTL
4092     {
4093         NOTHROW;
4094         GC_NOTRIGGER; 
4095         CAN_TAKE_LOCK;     // IsWindowsRuntimeModule accesses metadata directly, which takes locks
4096         MODE_ANY;
4097     }
4098     CONTRACTL_END;
4099
4100     PEFile * pPEFile = pModule->GetFile();
4101     if (pPEFile == NULL)
4102     {
4103         // Hopefully this should never happen; but just in case, don't try to determine the
4104         // flags without a PEFile.
4105         return 0;
4106     }
4107
4108     DWORD dwRet = 0;
4109
4110     // First, set the flags that are dependent on which PEImage / layout we look at
4111     // inside the Module (disk/ngen/flat)
4112     
4113     if (pModule->HasNativeImage())
4114     {
4115         // NGEN
4116         dwRet |= (COR_PRF_MODULE_DISK | COR_PRF_MODULE_NGEN);
4117
4118         // Intentionally not checking for flat, since NGEN PEImages never have flat
4119         // layouts.
4120     }
4121     else
4122     {
4123 #ifdef FEATURE_READYTORUN 
4124         // pModule->HasNativeImage() returns false for ReadyToRun images
4125         if (pModule->IsReadyToRun())
4126         {
4127             // Ready To Run
4128             dwRet |= (COR_PRF_MODULE_DISK | COR_PRF_MODULE_NGEN);
4129         }
4130 #endif
4131         // Not NGEN or ReadyToRun.
4132         if (pPEFile->HasOpenedILimage())
4133         {
4134             PEImage * pILImage = pPEFile->GetOpenedILimage();
4135             if (pILImage->IsFile())
4136             {
4137                 dwRet |= COR_PRF_MODULE_DISK;
4138             }           
4139             if (pPEFile->GetLoadedIL()->IsFlat())
4140             {
4141                 dwRet |= COR_PRF_MODULE_FLAT_LAYOUT;
4142             }
4143         }
4144     }
4145
4146     if (pModule->IsReflection())
4147     {
4148         dwRet |= COR_PRF_MODULE_DYNAMIC;
4149     }
4150
4151     if (pModule->IsCollectible())
4152     {
4153         dwRet |= COR_PRF_MODULE_COLLECTIBLE;
4154     }
4155
4156     if (pModule->IsResource())
4157     {
4158         dwRet |= COR_PRF_MODULE_RESOURCE;
4159     }
4160
4161     if (pModule->IsWindowsRuntimeModule())
4162     {
4163         dwRet |= COR_PRF_MODULE_WINDOWS_RUNTIME;
4164     }
4165     
4166     return dwRet;
4167 }
4168
4169 HRESULT ProfToEEInterfaceImpl::GetModuleInfo2(ModuleID     moduleId,
4170     LPCBYTE *    ppBaseLoadAddress,
4171     ULONG        cchName,
4172     ULONG *      pcchName,
4173     __out_ecount_part_opt(cchName, *pcchName) WCHAR wszName[],
4174     AssemblyID * pAssemblyId,
4175     DWORD *      pdwModuleFlags)
4176 {
4177     CONTRACTL
4178     {
4179         // Yay!
4180         NOTHROW;
4181         
4182         // Yay!
4183         GC_NOTRIGGER; 
4184
4185         // The pModule->GetScopeName() call below can result in locks getting taken to
4186         // access the metadata implementation.  However, these locks do not do a mode
4187         // change.
4188         CAN_TAKE_LOCK;
4189
4190         // Yay!
4191         MODE_ANY;
4192
4193         // Yay!
4194         EE_THREAD_NOT_REQUIRED;
4195
4196         SO_NOT_MAINLINE;
4197
4198         PRECONDITION(CheckPointer((Module *)moduleId, NULL_OK));
4199         PRECONDITION(CheckPointer(ppBaseLoadAddress,  NULL_OK));
4200         PRECONDITION(CheckPointer(pcchName, NULL_OK));
4201         PRECONDITION(CheckPointer(wszName, NULL_OK));
4202         PRECONDITION(CheckPointer(pAssemblyId, NULL_OK));
4203     }
4204     CONTRACTL_END;
4205
4206     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
4207         (LF_CORPROF, 
4208         LL_INFO1000, 
4209         "**PROF: GetModuleInfo2 0x%p.\n", 
4210         moduleId));    
4211
4212     if (moduleId == NULL)
4213     {
4214         return E_INVALIDARG;
4215     }
4216     
4217     Module * pModule = (Module *) moduleId;
4218     if (pModule->IsBeingUnloaded())
4219     {
4220         return CORPROF_E_DATAINCOMPLETE;
4221     }
4222     
4223     HRESULT     hr = S_OK;
4224
4225     EX_TRY
4226     {
4227         
4228         PEFile * pFile = pModule->GetFile();
4229
4230         // Pick some safe defaults to begin with.
4231         if (ppBaseLoadAddress != NULL)
4232             *ppBaseLoadAddress = 0;
4233         if (wszName != NULL)
4234             *wszName = 0;
4235         if (pcchName != NULL)
4236             *pcchName = 0;
4237         if (pAssemblyId != NULL)
4238             *pAssemblyId = PROFILER_PARENT_UNKNOWN;
4239
4240         // Module flags can be determined first without fear of error
4241         if (pdwModuleFlags != NULL)
4242             *pdwModuleFlags = GetModuleFlags(pModule);
4243
4244         // Get the module file name
4245         LPCWSTR wszFileName = pFile->GetPath();
4246         _ASSERTE(wszFileName != NULL);
4247         PREFIX_ASSUME(wszFileName != NULL);
4248
4249         // If there is no filename, which is the case for RefEmit modules and for SQL
4250         // modules, then rather than returning an empty string for the name, just use the
4251         // module name from metadata (a.k.a. Module.ScopeName). This is required to
4252         // support SQL F1 sampling profiling.
4253         StackSString strScopeName;
4254         LPCUTF8 szScopeName = NULL;
4255         if ((*wszFileName == W('\0')) && SUCCEEDED(pModule->GetScopeName(&szScopeName)))
4256         {
4257             strScopeName.SetUTF8(szScopeName);
4258             strScopeName.Normalize();
4259             wszFileName = strScopeName.GetUnicode();
4260         }
4261
4262         ULONG trueLen = (ULONG)(wcslen(wszFileName) + 1);
4263
4264         // Return name of module as required.
4265         if (wszName && cchName > 0)
4266         {
4267             if (cchName < trueLen)
4268             {
4269                 hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
4270             }
4271             else
4272             {
4273                 wcsncpy_s(wszName, cchName, wszFileName, trueLen);
4274             }
4275         }
4276
4277         // If they request the actual length of the name
4278         if (pcchName)
4279             *pcchName = trueLen;
4280
4281         if (ppBaseLoadAddress != NULL && !pFile->IsDynamic())
4282         {
4283             if (pModule->IsProfilerNotified())
4284             {
4285                 // Set the base load address -- this could be null in certain error conditions
4286                 *ppBaseLoadAddress = pModule->GetProfilerBase();
4287             }
4288             else
4289             {
4290                 *ppBaseLoadAddress = NULL;
4291             }
4292
4293             if (*ppBaseLoadAddress == NULL)
4294             {
4295                 hr = CORPROF_E_DATAINCOMPLETE;
4296             }
4297         }
4298
4299         // Return the parent assembly for this module if desired.
4300         if (pAssemblyId != NULL)
4301         {
4302             // Lie and say the assembly isn't avaialable until we are loaded (even though it is.)
4303             // This is for backward compatibilty - we may want to change it
4304             if (pModule->IsProfilerNotified())
4305             {
4306                 Assembly *pAssembly = pModule->GetAssembly();
4307                 _ASSERTE(pAssembly);
4308
4309                 *pAssemblyId = (AssemblyID) pAssembly;
4310             }
4311             else
4312             {
4313                 hr = CORPROF_E_DATAINCOMPLETE;
4314             }
4315         }
4316     }
4317     EX_CATCH_HRESULT(hr);
4318
4319     return (hr);
4320 }
4321
4322
4323 /*
4324  * Get a metadata interface instance which maps to the given module.
4325  * One may ask for the metadata to be opened in read+write mode, but
4326  * this will result in slower metadata execution of the program, because
4327  * changes made to the metadata cannot be optimized as they were from
4328  * the compiler.
4329  */
4330 HRESULT ProfToEEInterfaceImpl::GetModuleMetaData(ModuleID    moduleId,
4331     DWORD       dwOpenFlags,
4332     REFIID      riid,
4333     IUnknown    **ppOut)
4334 {
4335     CONTRACTL
4336     {
4337         // Yay!
4338         NOTHROW;
4339
4340         // Yay!
4341         GC_NOTRIGGER;
4342
4343         // Yay!
4344         MODE_ANY;
4345
4346         // Currently, this function is technically EE_THREAD_REQUIRED because
4347         // some functions in synch.cpp assert that there is a Thread object,
4348         // but we might be able to lift that restriction and make this be
4349         // EE_THREAD_NOT_REQUIRED.
4350
4351         // PEFile::GetRWImporter & PEFile::GetEmitter &
4352         // GetReadablePublicMetaDataInterface take locks
4353         CAN_TAKE_LOCK;
4354
4355         SO_NOT_MAINLINE;
4356     }
4357     CONTRACTL_END;
4358
4359     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
4360         (LF_CORPROF, 
4361         LL_INFO1000, 
4362         "**PROF: GetModuleMetaData 0x%p, 0x%08x.\n", 
4363         moduleId, 
4364         dwOpenFlags));
4365
4366     if (moduleId == NULL)
4367     {
4368         return E_INVALIDARG;
4369     }
4370
4371     // Check for unsupported bits, and return E_INVALIDARG if present
4372     if ((dwOpenFlags & ~(ofNoTransform | ofRead | ofWrite)) != 0)
4373     {
4374         return E_INVALIDARG;
4375     }
4376
4377     Module * pModule;
4378     HRESULT hr = S_OK;
4379
4380     pModule = (Module *) moduleId;
4381     _ASSERTE(pModule != NULL);
4382     if (pModule->IsBeingUnloaded())
4383     {
4384         return CORPROF_E_DATAINCOMPLETE;
4385     }
4386
4387     // Make sure we can get the importer first
4388     if (pModule->IsResource())
4389     {
4390         if (ppOut)
4391             *ppOut = NULL;
4392         return S_FALSE;
4393     }
4394
4395     // Decide which type of open mode we are in to see which you require.
4396     if ((dwOpenFlags & ofWrite) == 0)
4397     {
4398         // Readable interface
4399         return pModule->GetReadablePublicMetaDataInterface(dwOpenFlags, riid, (LPVOID *) ppOut);
4400     }
4401
4402     // Writeable interface
4403     IUnknown *pObj = NULL;
4404     EX_TRY
4405     {
4406         pObj = pModule->GetValidatedEmitter();
4407     }
4408     EX_CATCH_HRESULT_NO_ERRORINFO(hr);
4409
4410     // Ask for the interface the caller wanted, only if they provide a out param
4411     if (SUCCEEDED(hr) && ppOut)
4412         hr = pObj->QueryInterface(riid, (void **) ppOut);
4413
4414     return (hr);
4415 }
4416
4417
4418 /*
4419  * Retrieve a pointer to the body of a method starting at it's header.
4420  * A method is scoped by the module it lives in.  Because this function
4421  * is designed to give a tool access to IL before it has been loaded
4422  * by the Runtime, it uses the metadata token of the method to find
4423  * the instance desired.  Note that this function has no effect on
4424  * already compiled code.
4425  */
4426 HRESULT ProfToEEInterfaceImpl::GetILFunctionBody(ModuleID    moduleId,
4427     mdMethodDef methodId,
4428     LPCBYTE     *ppMethodHeader,
4429     ULONG       *pcbMethodSize)
4430 {
4431     CONTRACTL
4432     {
4433         // Yay!
4434         NOTHROW;
4435
4436         // Yay!
4437         GC_NOTRIGGER;
4438
4439         // Yay!
4440         MODE_ANY;
4441
4442         // PEFile::CheckLoaded & Module::GetDynamicIL both take a lock
4443         CAN_TAKE_LOCK;
4444
4445         SO_NOT_MAINLINE;
4446     }
4447     CONTRACTL_END;
4448
4449     PROFILER_TO_CLR_ENTRYPOINT_SYNC((LF_CORPROF, 
4450                                      LL_INFO1000, 
4451                                      "**PROF: GetILFunctionBody 0x%p, 0x%08x.\n",
4452                                      moduleId, 
4453                                      methodId));    
4454
4455     Module *    pModule;                // Working pointer for real class.
4456     ULONG       RVA;                    // Return RVA of the method body.
4457     DWORD       dwImplFlags;            // Flags for the item.
4458     
4459     if ((moduleId == NULL) ||
4460         (methodId == mdMethodDefNil) ||
4461         (methodId == 0) ||
4462         (TypeFromToken(methodId) != mdtMethodDef))
4463     {
4464         return E_INVALIDARG;
4465     }
4466     
4467     pModule = (Module *) moduleId;
4468     _ASSERTE(pModule != NULL && methodId != mdMethodDefNil);
4469     if (pModule->IsBeingUnloaded())
4470     {
4471         return CORPROF_E_DATAINCOMPLETE;
4472     }
4473
4474     // Find the method body based on metadata.
4475     IMDInternalImport *pImport = pModule->GetMDImport();
4476     _ASSERTE(pImport);
4477
4478     PEFile *pFile = pModule->GetFile();
4479
4480     if (!pFile->CheckLoaded())
4481         return (CORPROF_E_DATAINCOMPLETE);
4482
4483     LPCBYTE pbMethod = NULL;
4484
4485     // Don't return rewritten IL, use the new API to get that.
4486     pbMethod = (LPCBYTE) pModule->GetDynamicIL(methodId, FALSE);
4487
4488     // Method not overriden - get the original copy of the IL by going to metadata
4489     if (pbMethod == NULL)
4490     {
4491         HRESULT hr = S_OK;
4492         IfFailRet(pImport->GetMethodImplProps(methodId, &RVA, &dwImplFlags));
4493         
4494         // Check to see if the method has associated IL
4495         if ((RVA == 0 && !pFile->IsDynamic()) || !(IsMiIL(dwImplFlags) || IsMiOPTIL(dwImplFlags) || IsMiInternalCall(dwImplFlags)))
4496         {
4497             return (CORPROF_E_FUNCTION_NOT_IL);
4498         }
4499         
4500         EX_TRY
4501         {
4502             // Get the location of the IL
4503             pbMethod = (LPCBYTE) (pModule->GetIL(RVA));
4504         }
4505         EX_CATCH_HRESULT(hr);
4506         
4507         if (FAILED(hr))
4508         {
4509             return hr;
4510         }
4511     }
4512     
4513     // Fill out param if provided
4514     if (ppMethodHeader)
4515         *ppMethodHeader = pbMethod;
4516
4517     // Calculate the size of the method itself.
4518     if (pcbMethodSize)
4519     {
4520         if (!FitsIn<ULONG>(PEDecoder::ComputeILMethodSize((TADDR)pbMethod)))
4521         {
4522             return E_UNEXPECTED;
4523         }
4524         *pcbMethodSize = static_cast<ULONG>(PEDecoder::ComputeILMethodSize((TADDR)pbMethod));
4525     }
4526     return (S_OK);
4527 }
4528
4529 //---------------------------------------------------------------------------------------
4530 // Retrieves an IMethodMalloc pointer around a ModuleILHeap instance that will own
4531 // allocating heap space for this module (for IL rewriting).
4532 //
4533 // Arguments:
4534 //      moduleId - ModuleID this allocator shall allocate for
4535 //      ppMalloc - [out] IMethodMalloc pointer the profiler will use for allocation requests
4536 //                       against this module
4537 //
4538 // Return value
4539 //      HRESULT indicating success / failure
4540 //
4541 // Notes
4542 //        IL method bodies used to have the requirement that they must be referenced as
4543 //        RVA's to the loaded module, which means they come after the module within
4544 //        METHOD_MAX_RVA.  In order to make it easier for a tool to swap out the body of
4545 //        a method, this allocator will ensure memory allocated after that point.
4546 //
4547 //        Now that requirement is completely gone, so there's nothing terribly special
4548 //        about this allocator, we just keep it around for legacy purposes.
4549
4550 HRESULT ProfToEEInterfaceImpl::GetILFunctionBodyAllocator(ModuleID         moduleId,
4551                                                           IMethodMalloc ** ppMalloc)
4552 {
4553     CONTRACTL
4554     {
4555         // Yay!
4556         NOTHROW;
4557
4558         // ModuleILHeap::FindOrCreateHeap may take a Crst if it
4559         // needs to create a new allocator and add it to the list.  Taking a crst
4560         // switches to preemptive, which is effectively a GC trigger
4561         GC_TRIGGERS;
4562
4563         // Yay!
4564         MODE_ANY;
4565
4566         // Yay!
4567         EE_THREAD_NOT_REQUIRED;
4568
4569         // (see GC_TRIGGERS comment)
4570         CAN_TAKE_LOCK;
4571
4572         SO_NOT_MAINLINE;
4573     }
4574     CONTRACTL_END;
4575     
4576     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
4577         kP2EETriggers,
4578         (LF_CORPROF, 
4579         LL_INFO1000, 
4580         "**PROF: GetILFunctionBodyAllocator 0x%p.\n", 
4581         moduleId));
4582     
4583     if ((moduleId == NULL) || (ppMalloc == NULL))
4584     {
4585         return E_INVALIDARG;
4586     }
4587
4588     Module * pModule = (Module *) moduleId;
4589
4590     if (pModule->IsBeingUnloaded() ||
4591         !pModule->GetFile()->CheckLoaded())
4592     {
4593         return (CORPROF_E_DATAINCOMPLETE);
4594     }
4595
4596     *ppMalloc = &ModuleILHeap::s_Heap;
4597     return S_OK;
4598 }
4599
4600 /*
4601  * Replaces the method body for a function in a module.  This will replace
4602  * the RVA of the method in the metadata to point to this new method body,
4603  * and adjust any internal data structures as required.  This function can
4604  * only be called on those methods which have never been compiled by a JITTER.
4605  * Please use the GetILFunctionBodyAllocator to allocate space for the new method to
4606  * ensure the buffer is compatible.
4607  */
4608 HRESULT ProfToEEInterfaceImpl::SetILFunctionBody(ModuleID    moduleId,
4609     mdMethodDef methodId,
4610     LPCBYTE     pbNewILMethodHeader)
4611 {
4612     CONTRACTL
4613     {
4614         // PEFile::GetEmitter, Module::SetDynamicIL all throw
4615         THROWS;
4616         
4617         // Locks are taken (see CAN_TAKE_LOCK below), which may cause mode switch to
4618         // preemptive, which is triggers.
4619         GC_TRIGGERS;
4620
4621         // Yay!
4622         MODE_ANY;
4623
4624         // Module::SetDynamicIL & PEFile::CheckLoaded & PEFile::GetEmitter take locks
4625         CAN_TAKE_LOCK;
4626
4627         SO_NOT_MAINLINE;
4628     }
4629     CONTRACTL_END;
4630
4631     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
4632         kP2EETriggers,
4633         (LF_CORPROF, 
4634          LL_INFO1000, 
4635          "**PROF: SetILFunctionBody 0x%p, 0x%08x.\n",
4636          moduleId, 
4637          methodId));        
4638     
4639     if ((moduleId == NULL) ||
4640         (methodId == mdMethodDefNil) ||
4641         (TypeFromToken(methodId) != mdtMethodDef) ||
4642         (pbNewILMethodHeader == NULL))
4643     {
4644         return E_INVALIDARG;
4645     }
4646     
4647     Module      *pModule;               // Working pointer for real class.
4648     HRESULT     hr = S_OK;
4649
4650     // Cannot set the body for anything other than a method def
4651     if (TypeFromToken(methodId) != mdtMethodDef)
4652         return (E_INVALIDARG);
4653
4654     // Cast module to appropriate type
4655     pModule = (Module *) moduleId;
4656     _ASSERTE (pModule != NULL); // Enforced in CorProfInfo::SetILFunctionBody
4657     if (pModule->IsBeingUnloaded())
4658     {
4659         return CORPROF_E_DATAINCOMPLETE;
4660     }
4661
4662     // Remember the profiler is doing this, as that means we must never detach it!
4663     g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
4664
4665     // This action is not temporary!
4666     // If the profiler want to be able to revert, they need to use
4667     // the new ReJIT APIs.
4668     pModule->SetDynamicIL(methodId, (TADDR)pbNewILMethodHeader, FALSE);
4669
4670     return (hr);
4671 }
4672
4673 /*
4674  * Sets the codemap for the replaced IL function body
4675  */
4676 HRESULT ProfToEEInterfaceImpl::SetILInstrumentedCodeMap(FunctionID functionId,
4677         BOOL fStartJit,
4678         ULONG cILMapEntries,
4679         COR_IL_MAP rgILMapEntries[])
4680 {
4681     CONTRACTL
4682     {
4683         // Debugger::SetILInstrumentedCodeMap throws
4684         THROWS;
4685
4686         // Debugger::SetILInstrumentedCodeMap triggers
4687         GC_TRIGGERS;
4688
4689         // Yay!
4690         MODE_ANY;
4691
4692         // Yay!
4693         EE_THREAD_NOT_REQUIRED;
4694
4695         // Debugger::SetILInstrumentedCodeMap takes a lock when it calls Debugger::GetOrCreateMethodInfo
4696         CAN_TAKE_LOCK;
4697
4698         SO_NOT_MAINLINE;
4699     }
4700     CONTRACTL_END;
4701
4702     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
4703         kP2EETriggers,
4704         (LF_CORPROF, 
4705          LL_INFO1000, 
4706          "**PROF: SetILInstrumentedCodeMap 0x%p, %d.\n",
4707          functionId, 
4708          fStartJit));        
4709        
4710     if (functionId == NULL)
4711     {
4712         return E_INVALIDARG;
4713     }
4714
4715     if (cILMapEntries >= (MAXULONG / sizeof(COR_IL_MAP)))
4716     {
4717         // Too big!  The allocation below would overflow when calculating the size.
4718         return E_INVALIDARG;
4719     }
4720     
4721     
4722 #ifdef DEBUGGING_SUPPORTED
4723
4724     MethodDesc *pMethodDesc = FunctionIdToMethodDesc(functionId);
4725
4726     // it's not safe to examine a methoddesc that has not been restored so do not do so
4727     if (!pMethodDesc ->IsRestored())
4728         return CORPROF_E_DATAINCOMPLETE;
4729
4730     if (g_pDebugInterface == NULL)
4731     {
4732         return CORPROF_E_DEBUGGING_DISABLED;
4733     }
4734
4735     COR_IL_MAP * rgNewILMapEntries = new (nothrow) COR_IL_MAP[cILMapEntries];
4736
4737     if (rgNewILMapEntries == NULL)
4738         return E_OUTOFMEMORY;
4739
4740     memcpy_s(rgNewILMapEntries, sizeof(COR_IL_MAP) * cILMapEntries, rgILMapEntries, sizeof(COR_IL_MAP) * cILMapEntries);
4741
4742     return g_pDebugInterface->SetILInstrumentedCodeMap(pMethodDesc,
4743                                                        fStartJit,
4744                                                        cILMapEntries,
4745                                                        rgNewILMapEntries);
4746
4747 #else //DEBUGGING_SUPPORTED
4748     return E_NOTIMPL;
4749 #endif //DEBUGGING_SUPPORTED
4750 }
4751
4752 HRESULT ProfToEEInterfaceImpl::ForceGC()
4753 {
4754     CONTRACTL
4755     {
4756         // GC calls "new" which throws
4757         THROWS;
4758
4759         // Uh duh, look at the name of the function, dude
4760         GC_TRIGGERS;
4761
4762         // Yay!
4763         MODE_ANY;
4764
4765         // Yay!
4766         EE_THREAD_NOT_REQUIRED;
4767
4768         // Initiating a GC causes a runtime suspension which requires the
4769         // mother of all locks: the thread store lock.
4770         CAN_TAKE_LOCK;
4771
4772         SO_NOT_MAINLINE;
4773     }
4774     CONTRACTL_END;
4775
4776     ASSERT_NO_EE_LOCKS_HELD();
4777
4778     // We need to use IsGarbageCollectorFullyInitialized() instead of IsGCHeapInitialized() because
4779     // there are other GC initialization being done after IsGCHeapInitialized() becomes TRUE, 
4780     // and before IsGarbageCollectorFullyInitialized() becomes TRUE.
4781     if (!IsGarbageCollectorFullyInitialized())
4782     {
4783         return CORPROF_E_NOT_YET_AVAILABLE;
4784     }
4785
4786     // Disallow the cases where a profiler calls this off a hijacked CLR thread 
4787     // or inside a profiler callback.  (Allow cases where this is a native thread, or a
4788     // thread which previously successfully called ForceGC.)
4789     Thread * pThread = GetThreadNULLOk();
4790     if ((pThread != NULL) &&
4791             (!AreCallbackStateFlagsSet(COR_PRF_CALLBACKSTATE_FORCEGC_WAS_CALLED)) &&
4792             (pThread->GetFrame() != FRAME_TOP
4793             || AreCallbackStateFlagsSet(COR_PRF_CALLBACKSTATE_INCALLBACK)))
4794     {
4795         LOG((LF_CORPROF,
4796              LL_ERROR,
4797              "**PROF: ERROR: Returning CORPROF_E_UNSUPPORTED_CALL_SEQUENCE "
4798              "due to illegal hijacked profiler call or call from inside another callback\n"));
4799         return CORPROF_E_UNSUPPORTED_CALL_SEQUENCE;
4800     }
4801
4802     // NOTE: We cannot use the standard macro PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX
4803     // here because the macro ensures that either the current thread is not an 
4804     // EE thread, or, if it is, that the CALLBACK flag is set. In classic apps
4805     // a profiler-owned native thread will not get an EE thread associated with 
4806     // it, however, in AppX apps, during the first call into the GC on a
4807     // profiler-owned thread, the EE will associate an EE-thread with the profiler
4808     // thread. As a consequence the second call to ForceGC on the same thread
4809     // would fail, since this is now an EE thread and this API is not called from
4810     // a callback.
4811
4812     // First part of the PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX macro:
4813     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(
4814         kP2EEAllowableAfterAttach | kP2EETriggers,
4815         (LF_CORPROF, 
4816         LL_INFO1000, 
4817         "**PROF: ForceGC.\n"));        
4818
4819 #ifdef FEATURE_EVENT_TRACE
4820     // This helper, used by ETW and profAPI ensures a managed thread gets created for
4821     // this thread before forcing the GC (to work around Jupiter issues where it's
4822     // expected this thread is already managed before starting the GC).
4823     HRESULT hr = ETW::GCLog::ForceGCForDiagnostics();
4824 #else // !FEATURE_EVENT_TRACE
4825     HRESULT hr = E_FAIL;
4826 #endif // FEATURE_EVENT_TRACE
4827  
4828     // If a Thread object was just created for this thread, remember the fact that it
4829     // was a ForceGC() thread, so we can be more lenient when doing
4830     // COR_PRF_CALLBACKSTATE_INCALLBACK later on from other APIs
4831     pThread = GetThreadNULLOk();
4832     if (pThread != NULL)
4833     {
4834         pThread->SetProfilerCallbackStateFlags(COR_PRF_CALLBACKSTATE_FORCEGC_WAS_CALLED);
4835     }
4836
4837     return hr;
4838 }
4839
4840
4841 /*
4842  * Returns the ContextID for the current thread.
4843  */
4844 HRESULT ProfToEEInterfaceImpl::GetThreadContext(ThreadID threadId,
4845                                                 ContextID *pContextId)
4846 {
4847     CONTRACTL
4848     {
4849         // Yay!
4850         NOTHROW;
4851
4852         // Yay!
4853         GC_NOTRIGGER;
4854
4855         // Yay!
4856         MODE_ANY;
4857
4858         // Yay!
4859         EE_THREAD_NOT_REQUIRED;
4860
4861         // Yay!
4862         CANNOT_TAKE_LOCK;
4863
4864         SO_NOT_MAINLINE;
4865     }
4866     CONTRACTL_END;
4867
4868     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
4869         (LF_CORPROF, 
4870          LL_INFO1000, 
4871          "**PROF: GetThreadContext 0x%p.\n", 
4872          threadId));
4873     
4874     if (!IsManagedThread(threadId))
4875     {
4876         return E_INVALIDARG;
4877     }
4878
4879     // Cast to right type
4880     Thread *pThread = reinterpret_cast<Thread *>(threadId);
4881
4882     // Get the context for the Thread* provided
4883     Context *pContext = pThread->GetContext();
4884     _ASSERTE(pContext);
4885
4886     // If there's no current context, return incomplete info
4887     if (!pContext)
4888         return (CORPROF_E_DATAINCOMPLETE);
4889
4890     // Set the result and return
4891     if (pContextId)
4892         *pContextId = reinterpret_cast<ContextID>(pContext);
4893
4894     return (S_OK);
4895 }
4896
4897 HRESULT ProfToEEInterfaceImpl::GetClassIDInfo(ClassID classId,
4898     ModuleID *pModuleId,
4899     mdTypeDef *pTypeDefToken)
4900 {
4901     CONTRACTL
4902     {
4903         // Yay!
4904         NOTHROW;
4905
4906         // Yay!
4907         GC_NOTRIGGER;
4908
4909         // Yay!
4910         MODE_ANY;
4911
4912         // Yay!
4913         EE_THREAD_NOT_REQUIRED;
4914
4915         // Yay!
4916         CANNOT_TAKE_LOCK;
4917
4918         SO_NOT_MAINLINE;
4919     }
4920     CONTRACTL_END;
4921     
4922     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
4923         (LF_CORPROF, 
4924         LL_INFO1000, 
4925         "**PROF: GetClassIDInfo 0x%p.\n",
4926         classId));
4927
4928     if (classId == NULL)
4929     {
4930         return E_INVALIDARG;
4931     }
4932     
4933     if (pModuleId != NULL)
4934     {
4935         *pModuleId = NULL;
4936     }
4937
4938     if (pTypeDefToken != NULL)
4939     {
4940         *pTypeDefToken = NULL;
4941     }
4942
4943     // Handle globals which don't have the instances.
4944     if (classId == PROFILER_GLOBAL_CLASS)
4945     {
4946         if (pModuleId != NULL)
4947         {
4948             *pModuleId = PROFILER_GLOBAL_MODULE;
4949         }
4950
4951         if (pTypeDefToken != NULL)
4952         {
4953             *pTypeDefToken = mdTokenNil;
4954     }
4955     }
4956     else if (classId == NULL)
4957     {
4958         return E_INVALIDARG;
4959     }
4960     // Get specific data.
4961     else
4962     {
4963         TypeHandle th = TypeHandle::FromPtr((void *)classId);
4964
4965         if (!th.IsTypeDesc())
4966         {
4967             if (!th.IsArray())
4968             {
4969                 //
4970                 // If this class is not fully restored, that is all the information we can get at this time.
4971                 //
4972                 if (!th.IsRestored())
4973                 {
4974                     return CORPROF_E_DATAINCOMPLETE;
4975                 }
4976
4977                 if (pModuleId != NULL)
4978                 {
4979                     *pModuleId = (ModuleID) th.GetModule();
4980                     _ASSERTE(*pModuleId != NULL);
4981                 }
4982
4983                 if (pTypeDefToken != NULL)
4984                 {
4985                     *pTypeDefToken = th.GetCl();
4986                     _ASSERTE(*pTypeDefToken != NULL);
4987                 }
4988             }
4989         }
4990     }
4991
4992     return (S_OK);
4993 }
4994
4995
4996 HRESULT ProfToEEInterfaceImpl::GetFunctionInfo(FunctionID functionId,
4997     ClassID *pClassId,
4998     ModuleID *pModuleId,
4999     mdToken *pToken)
5000 {
5001     CONTRACTL
5002     {
5003         // Yay!
5004         NOTHROW;
5005
5006         // Yay!
5007         GC_NOTRIGGER;
5008
5009         // Yay!
5010         MODE_ANY;
5011
5012         // Yay!
5013         EE_THREAD_NOT_REQUIRED;
5014
5015         // Yay!
5016         CANNOT_TAKE_LOCK;
5017
5018         SO_NOT_MAINLINE;
5019     }
5020     CONTRACTL_END;
5021
5022     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
5023         (LF_CORPROF, 
5024         LL_INFO1000, 
5025         "**PROF: GetFunctionInfo 0x%p.\n",
5026         functionId));
5027     
5028     if (functionId == NULL)
5029     {
5030         return E_INVALIDARG;
5031     }
5032
5033     MethodDesc *pMDesc = (MethodDesc *) functionId;
5034     if (!pMDesc->IsRestored())
5035     {
5036         return CORPROF_E_DATAINCOMPLETE;
5037     }
5038
5039     MethodTable *pMT = pMDesc->GetMethodTable();
5040     if (!pMT->IsRestored())
5041     {
5042         return CORPROF_E_DATAINCOMPLETE;
5043     }
5044
5045     ClassID classId = PROFILER_GLOBAL_CLASS;
5046
5047     if (pMT != NULL)
5048     {
5049         classId = NonGenericTypeHandleToClassID(TypeHandle(pMT));
5050     }
5051
5052     if (pClassId != NULL)
5053     {
5054         *pClassId = classId;
5055     }
5056
5057     if (pModuleId != NULL)
5058     {
5059         *pModuleId = (ModuleID) pMDesc->GetModule();
5060     }
5061
5062     if (pToken != NULL)
5063     {
5064         *pToken = pMDesc->GetMemberDef();
5065     }
5066
5067     return (S_OK);
5068 }
5069
5070 /*
5071  * GetILToNativeMapping returns a map from IL offsets to native
5072  * offsets for this code. An array of COR_DEBUG_IL_TO_NATIVE_MAP
5073  * structs will be returned, and some of the ilOffsets in this array
5074  * may be the values specified in CorDebugIlToNativeMappingTypes.
5075  */
5076 HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping(FunctionID functionId,
5077                                                     ULONG32 cMap,
5078                                                     ULONG32 * pcMap,    // [out]
5079                                                     COR_DEBUG_IL_TO_NATIVE_MAP map[]) // [out]
5080 {
5081     CONTRACTL
5082     {
5083         // MethodDesc::FindOrCreateTypicalSharedInstantiation throws
5084         THROWS;
5085
5086         // MethodDesc::FindOrCreateTypicalSharedInstantiation triggers, but shouldn't trigger when
5087         // called from here.  Since the profiler has a valid functionId, the methoddesc for
5088         // this code will already have been created.  We should be able to enforce this by
5089         // passing allowCreate=FALSE  to FindOrCreateTypicalSharedInstantiation.
5090         DISABLED(GC_NOTRIGGER);
5091     
5092         // Yay!
5093         MODE_ANY;
5094     
5095         // The call to g_pDebugInterface->GetILToNativeMapping() below may call
5096         // Debugger::AcquireDebuggerLock
5097         CAN_TAKE_LOCK;
5098
5099         SO_NOT_MAINLINE;
5100     }
5101     CONTRACTL_END;
5102
5103     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
5104         (LF_CORPROF, 
5105         LL_INFO1000, 
5106         "**PROF: GetILToNativeMapping 0x%p.\n",
5107         functionId));
5108
5109     return GetILToNativeMapping2(functionId, 0, cMap, pcMap, map);
5110 }
5111
5112 HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping2(FunctionID functionId,
5113                                                     ReJITID reJitId,
5114                                                     ULONG32 cMap,
5115                                                     ULONG32 * pcMap,    // [out]
5116                                                     COR_DEBUG_IL_TO_NATIVE_MAP map[]) // [out]
5117     {
5118     CONTRACTL
5119     {
5120         // MethodDesc::FindOrCreateTypicalSharedInstantiation throws
5121         THROWS;
5122
5123         // MethodDesc::FindOrCreateTypicalSharedInstantiation triggers, but shouldn't trigger when
5124         // called from here.  Since the profiler has a valid functionId, the methoddesc for
5125         // this code will already have been created.  We should be able to enforce this by
5126         // passing allowCreate=FALSE  to FindOrCreateTypicalSharedInstantiation.
5127         DISABLED(GC_NOTRIGGER);
5128
5129         // Yay!
5130         MODE_ANY;
5131     
5132         // The call to g_pDebugInterface->GetILToNativeMapping() below may call
5133         // Debugger::AcquireDebuggerLock
5134         CAN_TAKE_LOCK;
5135
5136         SO_NOT_MAINLINE;
5137     }
5138     CONTRACTL_END;
5139
5140     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
5141         (LF_CORPROF, 
5142         LL_INFO1000, 
5143         "**PROF: GetILToNativeMapping2 0x%p 0x%p.\n",
5144         functionId, reJitId));
5145     
5146     if (functionId == NULL)
5147     {
5148         return E_INVALIDARG;
5149     }
5150
5151     if ((cMap > 0) && 
5152         ((pcMap == NULL) || (map == NULL)))
5153     {
5154         return E_INVALIDARG;
5155     }
5156
5157     if (reJitId != 0)
5158     {
5159         return E_NOTIMPL;
5160     }
5161
5162 #ifdef DEBUGGING_SUPPORTED
5163     // Cast to proper type
5164     MethodDesc * pMD = FunctionIdToMethodDesc(functionId);
5165
5166     if (pMD->HasClassOrMethodInstantiation() && pMD->IsTypicalMethodDefinition())
5167     {
5168         // In this case, we used to replace pMD with its canonical instantiation
5169         // (FindOrCreateTypicalSharedInstantiation).  However, a profiler should never be able
5170         // to get to this point anyway, since any MethodDesc a profiler gets from us
5171         // cannot be typical (i.e., cannot be a generic with types still left uninstantiated).
5172         // We assert here just in case a test proves me wrong, but generally we will
5173         // disallow this code path.
5174         _ASSERTE(!"Profiler passed a typical method desc (a generic with types still left uninstantiated) to GetILToNativeMapping2");
5175         return E_INVALIDARG;
5176     }
5177
5178     if (g_pDebugInterface == NULL)
5179     {
5180         return CORPROF_E_DEBUGGING_DISABLED;
5181     }
5182
5183     return (g_pDebugInterface->GetILToNativeMapping(pMD, cMap, pcMap, map));
5184 #else
5185     return E_NOTIMPL;
5186 #endif
5187 }
5188
5189
5190
5191 //*****************************************************************************
5192 // Given an ObjectID, go get the EE ClassID for it.
5193 //*****************************************************************************
5194 HRESULT ProfToEEInterfaceImpl::GetClassFromObject(ObjectID objectId,
5195                                                   ClassID * pClassId)
5196 {
5197     CONTRACTL
5198     {
5199         // Yay!
5200         NOTHROW;
5201
5202         // Yay!
5203         GC_NOTRIGGER;
5204
5205         // Yay!  Fail at runtime if in preemptive mode via AllowObjectInspection()
5206         MODE_ANY;
5207
5208         // Object::GetTypeHandle takes a lock
5209         CAN_TAKE_LOCK;
5210
5211         SO_NOT_MAINLINE;
5212     }
5213     CONTRACTL_END;
5214
5215     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
5216         (LF_CORPROF, 
5217          LL_INFO1000, 
5218          "**PROF: GetClassFromObject 0x%p.\n",
5219          objectId));    
5220     
5221     if (objectId == NULL)
5222     {
5223         return E_INVALIDARG;
5224     }
5225     
5226     HRESULT hr = AllowObjectInspection();
5227     if (FAILED(hr))
5228     {
5229         return hr;
5230     }
5231
5232     // Cast the ObjectID as a Object
5233     Object *pObj = reinterpret_cast<Object *>(objectId);
5234
5235     // Set the out param and indicate success
5236     // Note that for generic code we always return uninstantiated ClassIDs and FunctionIDs
5237     if (pClassId)
5238     {
5239         *pClassId = SafeGetClassIDFromObject(pObj);
5240     }
5241
5242     return S_OK;
5243 }
5244
5245 //*****************************************************************************
5246 // Given a module and a token for a class, go get the EE data structure for it.
5247 //*****************************************************************************
5248 HRESULT ProfToEEInterfaceImpl::GetClassFromToken(ModuleID    moduleId,
5249     mdTypeDef   typeDef,
5250     ClassID     *pClassId)
5251 {
5252     CONTRACTL
5253     {
5254         // Yay!
5255         NOTHROW;
5256
5257         // ClassLoader::LoadTypeDefOrRefThrowing triggers
5258         GC_TRIGGERS;
5259
5260         // Yay!
5261         MODE_ANY;
5262
5263         // ClassLoader::LoadTypeDefOrRefThrowing takes a lock
5264         CAN_TAKE_LOCK;
5265
5266         SO_NOT_MAINLINE;
5267     }
5268     CONTRACTL_END;
5269
5270     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
5271         kP2EEAllowableAfterAttach | kP2EETriggers,
5272         (LF_CORPROF, 
5273          LL_INFO1000, 
5274          "**PROF: GetClassFromToken 0x%p, 0x%08x.\n",
5275          moduleId, 
5276          typeDef));    
5277         
5278     if ((moduleId == NULL) || (typeDef == mdTypeDefNil) || (typeDef == NULL))
5279     {
5280         return E_INVALIDARG;
5281     }
5282     
5283     if (!g_profControlBlock.fBaseSystemClassesLoaded)
5284     {
5285         return CORPROF_E_RUNTIME_UNINITIALIZED;
5286     }
5287
5288     // Get the module
5289     Module *pModule = (Module *) moduleId;
5290
5291     // No module, or it's disassociated from metadata
5292     if ((pModule == NULL) || (pModule->IsBeingUnloaded()))
5293     {
5294         return CORPROF_E_DATAINCOMPLETE;
5295     }
5296
5297     // First, check the RID map. This is important since it
5298     // works during teardown (and the below doesn't)
5299     TypeHandle th;
5300     th = pModule->LookupTypeDef(typeDef);
5301     if (th.IsNull())
5302     {
5303         HRESULT hr = S_OK;
5304
5305         EX_TRY {
5306             th = ClassLoader::LoadTypeDefOrRefThrowing(pModule, typeDef,
5307                                                       ClassLoader::ThrowIfNotFound,
5308                                                       ClassLoader::PermitUninstDefOrRef);
5309         }
5310         EX_CATCH_HRESULT(hr);
5311
5312         if (FAILED(hr))
5313         {
5314             return hr;
5315         }
5316     }
5317
5318     if (!th.GetMethodTable())
5319     {
5320         return CORPROF_E_DATAINCOMPLETE;
5321     }
5322
5323     //
5324     // Check if it is generic
5325     //
5326     ClassID classId = NonGenericTypeHandleToClassID(th);
5327
5328     if (classId == NULL)
5329     {
5330         return CORPROF_E_TYPE_IS_PARAMETERIZED;
5331     }
5332
5333     // Return value if necessary
5334     if (pClassId)
5335     {
5336         *pClassId = classId;
5337     }
5338
5339     return S_OK;
5340 }
5341
5342
5343 HRESULT ProfToEEInterfaceImpl::GetClassFromTokenAndTypeArgs(ModuleID moduleID,
5344                                                             mdTypeDef typeDef,
5345                                                             ULONG32 cTypeArgs,
5346                                                             ClassID typeArgs[],
5347                                                             ClassID* pClassID)
5348 {
5349     CONTRACTL
5350     {
5351         // Yay!
5352         NOTHROW;
5353
5354         // LoadGenericInstantiationThrowing may load
5355         GC_TRIGGERS;
5356
5357         // Yay!
5358         MODE_ANY;
5359
5360         // ClassLoader::LoadGenericInstantiationThrowing takes a lock
5361         CAN_TAKE_LOCK;
5362
5363         SO_NOT_MAINLINE;
5364     }
5365     CONTRACTL_END;
5366         
5367     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
5368         kP2EEAllowableAfterAttach | kP2EETriggers,
5369         (LF_CORPROF, 
5370          LL_INFO1000, 
5371          "**PROF: GetClassFromTokenAndTypeArgs 0x%p, 0x%08x.\n",
5372          moduleID, 
5373          typeDef));    
5374     
5375     if (!g_profControlBlock.fBaseSystemClassesLoaded)
5376     {
5377         return CORPROF_E_RUNTIME_UNINITIALIZED;
5378     }
5379
5380     Module* pModule = reinterpret_cast< Module* >(moduleID);
5381
5382     if (pModule == NULL || pModule->IsBeingUnloaded())
5383     {
5384         return CORPROF_E_DATAINCOMPLETE;
5385     }
5386
5387     // This array needs to be accessible at least until the call to
5388     // ClassLoader::LoadGenericInstantiationThrowing
5389     TypeHandle* genericParameters = new (nothrow) TypeHandle[cTypeArgs];
5390     NewArrayHolder< TypeHandle > holder(genericParameters);
5391
5392     if (NULL == genericParameters)
5393     {
5394         return E_OUTOFMEMORY;
5395     }
5396
5397     for (ULONG32 i = 0; i < cTypeArgs; ++i)
5398     {
5399         genericParameters[i] = TypeHandle(reinterpret_cast< MethodTable* >(typeArgs[i]));
5400     }
5401
5402     //
5403     // nickbe 11/24/2003 10:12:56
5404     //
5405     // In RTM/Everett we decided to load the class if it hadn't been loaded yet
5406     // (see ProfToEEInterfaceImpl::GetClassFromToken). For compatibility we're
5407     // going to make the same decision here. It's potentially confusing to tell
5408     // someone a type doesn't exist at one point in time, but does exist later,
5409     // and there is no good way for us to determing that a class may eventually
5410     // be loaded without going ahead and loading it
5411     //
5412     TypeHandle th;
5413     HRESULT hr = S_OK;
5414
5415     EX_TRY
5416     {
5417         // Not sure if this is a valid override or not - making this a VIOLATION
5418         // until we're sure.
5419         CONTRACT_VIOLATION(LoadsTypeViolation);
5420     
5421         if (GetThreadNULLOk() == NULL)
5422         {
5423             // Type system will try to validate as part of its contract if the current 
5424             // AppDomain returned by GetAppDomain can load types in specified module's 
5425             // assembly.   On a non-EE thread it results in an AV in a check build 
5426             // since the type system tries to dereference NULL returned by GetAppDomain.  
5427             // More importantly, loading a type on a non-EE thread is not allowed.
5428             //
5429             // ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE() states that callers will not 
5430             // try to load a type, so that type system will not try to test type 
5431             // loadability in the current AppDomain.  However, 
5432             // ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE does not prevent callers from 
5433             // loading a type.   It is profiler's responsibility not to attempt to load
5434             // a type in unsupported ways (e.g. from a non-EE thread).  It doesn't 
5435             // impact retail builds, in which contracts are not available. 
5436             ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
5437
5438             // ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE also defines FAULT_FORBID, which 
5439             // causes Scanruntime to flag a fault violation in AssemblySpec::InitializeSpec,
5440             // which is defined as FAULTS.   It only happens in a type-loading path, which
5441             // is not supported on a non-EE thread.  Suppressing a contract violation in an
5442             // unsupported execution path is more preferable than causing AV when calling
5443             // GetClassFromTokenAndTypeArgs on a non-EE thread in a check build.  See Dev10 
5444             // 682526 for more details.
5445             FAULT_NOT_FATAL();
5446
5447             th = ClassLoader::LoadGenericInstantiationThrowing(pModule,
5448                                                                typeDef,
5449                                                                Instantiation(genericParameters, cTypeArgs),
5450                                                                ClassLoader::LoadTypes);
5451         }
5452         else
5453         {
5454             th = ClassLoader::LoadGenericInstantiationThrowing(pModule,
5455                                                                typeDef,
5456                                                                Instantiation(genericParameters, cTypeArgs),
5457                                                                ClassLoader::LoadTypes);
5458         }
5459     }
5460     EX_CATCH_HRESULT(hr);
5461
5462     if (FAILED(hr))
5463     {
5464         return hr;
5465     }
5466
5467     if (th.IsNull())
5468     {
5469         // Hmm, the type isn't loaded yet.
5470         return CORPROF_E_DATAINCOMPLETE;
5471     }
5472
5473     *pClassID = TypeHandleToClassID(th);
5474
5475     return S_OK;
5476 }
5477
5478 //*****************************************************************************
5479 // Given the token for a method, return the fucntion id.
5480 //*****************************************************************************
5481 HRESULT ProfToEEInterfaceImpl::GetFunctionFromToken(ModuleID moduleId,
5482     mdToken typeDef,
5483     FunctionID *pFunctionId)
5484 {
5485     CONTRACTL
5486     {
5487         // Yay!
5488         NOTHROW;
5489
5490         // Yay!
5491         GC_NOTRIGGER;
5492
5493         // Yay!
5494         MODE_ANY;
5495
5496         // Yay!
5497         EE_THREAD_NOT_REQUIRED;
5498
5499         // Yay!
5500         CANNOT_TAKE_LOCK;
5501
5502         SO_NOT_MAINLINE;
5503     }
5504     CONTRACTL_END;
5505
5506     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
5507         (LF_CORPROF, 
5508          LL_INFO1000, 
5509          "**PROF: GetFunctionFromToken 0x%p, 0x%08x.\n",
5510          moduleId, 
5511          typeDef));    
5512         
5513     if ((moduleId == NULL) || (typeDef == mdTokenNil))
5514     {
5515         return E_INVALIDARG;
5516     }
5517     
5518     if (!g_profControlBlock.fBaseSystemClassesLoaded)
5519     {
5520         return CORPROF_E_RUNTIME_UNINITIALIZED;
5521     }
5522
5523     // Default HRESULT
5524     HRESULT hr = S_OK;
5525
5526     // Get the module
5527     Module *pModule = (Module *) moduleId;
5528
5529     // No module, or disassociated from metadata
5530     if (pModule == NULL || pModule->IsBeingUnloaded())
5531     {
5532         return CORPROF_E_DATAINCOMPLETE;
5533     }
5534
5535     // Default return value of NULL
5536     MethodDesc *pDesc = NULL;
5537
5538     // Different lookup depending on whether it's a Def or Ref
5539     if (TypeFromToken(typeDef) == mdtMethodDef)
5540     {
5541         pDesc = pModule->LookupMethodDef(typeDef);
5542     }
5543     else if (TypeFromToken(typeDef) == mdtMemberRef)
5544     {
5545         pDesc = pModule->LookupMemberRefAsMethod(typeDef);
5546     }
5547     else
5548     {
5549         return E_INVALIDARG;
5550     }
5551
5552     if (NULL == pDesc)
5553     {
5554         return E_INVALIDARG;
5555     }
5556
5557     //
5558     // Check that this is a non-generic method
5559     //
5560     if (pDesc->HasClassOrMethodInstantiation())
5561     {
5562         return CORPROF_E_FUNCTION_IS_PARAMETERIZED;
5563     }
5564
5565     if (pFunctionId && SUCCEEDED(hr))
5566     {
5567         *pFunctionId = MethodDescToFunctionID(pDesc);
5568     }
5569
5570     return (hr);
5571 }
5572
5573 HRESULT ProfToEEInterfaceImpl::GetFunctionFromTokenAndTypeArgs(ModuleID moduleID,
5574                                                                mdMethodDef funcDef,
5575                                                                ClassID classId,
5576                                                                ULONG32 cTypeArgs,
5577                                                                ClassID typeArgs[],
5578                                                                FunctionID* pFunctionID)
5579 {
5580     CONTRACTL
5581     {
5582         // Yay!
5583         NOTHROW;
5584
5585         // It can trigger type loads
5586         GC_TRIGGERS;
5587
5588         // Yay!
5589         MODE_ANY;
5590
5591         // MethodDesc::FindOrCreateAssociatedMethodDesc enters a Crst
5592         CAN_TAKE_LOCK;
5593
5594         SO_NOT_MAINLINE;
5595     }
5596     CONTRACTL_END;
5597
5598     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
5599         kP2EEAllowableAfterAttach | kP2EETriggers,
5600         (LF_CORPROF, 
5601          LL_INFO1000, 
5602          "**PROF: GetFunctionFromTokenAndTypeArgs 0x%p, 0x%08x, 0x%p.\n",
5603          moduleID, 
5604          funcDef, 
5605          classId));        
5606     
5607     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classId);
5608     Module* pModule = reinterpret_cast< Module* >(moduleID);
5609
5610     if ((pModule == NULL) || typeHandle.IsNull())
5611     {
5612         return E_INVALIDARG;
5613     }
5614          
5615     if (!g_profControlBlock.fBaseSystemClassesLoaded)
5616     {
5617         return CORPROF_E_RUNTIME_UNINITIALIZED;
5618     }
5619
5620     if (pModule->IsBeingUnloaded())
5621     {
5622         return CORPROF_E_DATAINCOMPLETE;
5623     }
5624
5625     MethodDesc* pMethodDesc = NULL;
5626
5627     if (mdtMethodDef == TypeFromToken(funcDef))
5628     {
5629         pMethodDesc = pModule->LookupMethodDef(funcDef);
5630     }
5631     else if (mdtMemberRef == TypeFromToken(funcDef))
5632     {
5633         pMethodDesc = pModule->LookupMemberRefAsMethod(funcDef);
5634     }
5635     else
5636     {
5637         return E_INVALIDARG;
5638     }
5639
5640     MethodTable* pMethodTable = typeHandle.GetMethodTable();
5641
5642     if (pMethodTable == NULL || !pMethodTable->IsRestored() || 
5643         pMethodDesc == NULL || !pMethodDesc->IsRestored())
5644     {
5645         return CORPROF_E_DATAINCOMPLETE;
5646     }
5647
5648     // This array needs to be accessible at least until the call to
5649     // MethodDesc::FindOrCreateAssociatedMethodDesc
5650     TypeHandle* genericParameters = new (nothrow) TypeHandle[cTypeArgs];
5651     NewArrayHolder< TypeHandle > holder(genericParameters);
5652
5653     if (NULL == genericParameters)
5654     {
5655         return E_OUTOFMEMORY;
5656     }
5657
5658     for (ULONG32 i = 0; i < cTypeArgs; ++i)
5659     {
5660         genericParameters[i] = TypeHandle(reinterpret_cast< MethodTable* >(typeArgs[i]));
5661     }
5662
5663     MethodDesc* result = NULL;
5664     HRESULT hr = S_OK;
5665
5666     EX_TRY
5667     {
5668         result = MethodDesc::FindOrCreateAssociatedMethodDesc(pMethodDesc,
5669                                                               pMethodTable,
5670                                                               FALSE,
5671                                                               Instantiation(genericParameters, cTypeArgs),
5672                                                               TRUE);
5673     }
5674     EX_CATCH_HRESULT(hr);
5675
5676     if (NULL != result)
5677     {
5678         *pFunctionID = MethodDescToFunctionID(result);
5679     }
5680
5681     return hr;
5682 }
5683
5684 //*****************************************************************************
5685 // Retrieve information about a given application domain, which is like a
5686 // sub-process.
5687 //*****************************************************************************
5688 HRESULT ProfToEEInterfaceImpl::GetAppDomainInfo(AppDomainID appDomainId,
5689     ULONG       cchName,
5690     ULONG       *pcchName,
5691     __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[],
5692     ProcessID   *pProcessId)
5693 {
5694     CONTRACTL
5695     {
5696         // Yay!
5697         NOTHROW;
5698
5699         // AppDomain::GetFriendlyNameForDebugger triggers
5700         GC_TRIGGERS;
5701
5702         // Yay!
5703         MODE_ANY;
5704
5705         // AppDomain::GetFriendlyNameForDebugger takes a lock
5706         CAN_TAKE_LOCK;
5707
5708         SO_NOT_MAINLINE;
5709     }
5710     CONTRACTL_END;
5711
5712     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
5713         kP2EEAllowableAfterAttach | kP2EETriggers,
5714         (LF_CORPROF, 
5715          LL_INFO1000, 
5716          "**PROF: GetAppDomainInfo 0x%p.\n",
5717          appDomainId));
5718     
5719     if (appDomainId == NULL)
5720     {
5721         return E_INVALIDARG;
5722     }
5723     
5724     BaseDomain   *pDomain;            // Internal data structure.
5725     HRESULT     hr = S_OK;
5726
5727     // <TODO>@todo:
5728     // Right now, this ID is not a true AppDomain, since we use the old
5729     // AppDomain/SystemDomain model in the profiling API.  This means that
5730     // the profiler exposes the SharedDomain and the SystemDomain to the
5731     // outside world. It's not clear whether this is actually the right thing
5732     // to do or not. - seantrow
5733     //
5734     // Postponed to V2.
5735     // </TODO>
5736
5737     pDomain = (BaseDomain *) appDomainId;
5738
5739     // Make sure they've passed in a valid appDomainId
5740     if (pDomain == NULL)
5741         return (E_INVALIDARG);
5742
5743     // Pick sensible defaults.
5744     if (pcchName)
5745         *pcchName = 0;
5746     if (szName)
5747         *szName = 0;
5748     if (pProcessId)
5749         *pProcessId = 0;
5750
5751     LPCWSTR szFriendlyName;
5752     if (pDomain == SystemDomain::System())
5753         szFriendlyName = g_pwBaseLibrary;
5754     else if (pDomain == SharedDomain::GetDomain())
5755         szFriendlyName = W("EE Shared Assembly Repository");
5756     else
5757         szFriendlyName = ((AppDomain*)pDomain)->GetFriendlyNameForDebugger();
5758
5759     if (szFriendlyName != NULL)
5760     {
5761         // Get the module file name
5762         ULONG trueLen = (ULONG)(wcslen(szFriendlyName) + 1);
5763
5764         // Return name of module as required.
5765         if (szName && cchName > 0)
5766         {
5767             ULONG copyLen = trueLen;
5768
5769             if (copyLen >= cchName)
5770             {
5771                 copyLen = cchName - 1;
5772             }
5773
5774             wcsncpy_s(szName, cchName, szFriendlyName, copyLen);
5775         }
5776
5777         // If they request the actual length of the name
5778         if (pcchName)
5779             *pcchName = trueLen;
5780     }
5781
5782     // If we don't have a friendly name but the call was requesting it, then return incomplete data HR
5783     else
5784     {
5785         if ((szName != NULL && cchName > 0) || pcchName)
5786             hr = CORPROF_E_DATAINCOMPLETE;
5787     }
5788
5789     if (pProcessId)
5790         *pProcessId = (ProcessID) GetCurrentProcessId();
5791
5792     return (hr);
5793 }
5794
5795
5796 //*****************************************************************************
5797 // Retrieve information about an assembly, which is a collection of dll's.
5798 //*****************************************************************************
5799 HRESULT ProfToEEInterfaceImpl::GetAssemblyInfo(AssemblyID    assemblyId,
5800     ULONG       cchName,
5801     ULONG       *pcchName,
5802     __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[],
5803     AppDomainID *pAppDomainId,
5804     ModuleID    *pModuleId)
5805 {
5806     CONTRACTL
5807     {
5808         // SString::SString throws
5809         THROWS;
5810
5811         // Yay!
5812         GC_NOTRIGGER;
5813
5814         // Yay!
5815         MODE_ANY;
5816
5817         // Yay!
5818         EE_THREAD_NOT_REQUIRED;
5819
5820         // PEAssembly::GetSimpleName() enters a lock via use of the metadata interface
5821         CAN_TAKE_LOCK;
5822
5823         SO_NOT_MAINLINE;
5824     }
5825     CONTRACTL_END;
5826
5827     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
5828         (LF_CORPROF, 
5829          LL_INFO1000, 
5830          "**PROF: GetAssemblyInfo 0x%p.\n", 
5831          assemblyId));    
5832     
5833     if (assemblyId == NULL)
5834     {
5835         return E_INVALIDARG;
5836     }
5837     
5838     HRESULT hr = S_OK;
5839
5840     Assembly    *pAssembly;             // Internal data structure for assembly.
5841
5842     pAssembly = (Assembly *) assemblyId;
5843     _ASSERTE(pAssembly != NULL);
5844
5845     if (pcchName || szName)
5846     {
5847         // Get the friendly name of the assembly
5848         SString name(SString::Utf8, pAssembly->GetSimpleName());
5849
5850         const COUNT_T nameLength = name.GetCount() + 1;
5851
5852         if ((NULL != szName) && (cchName > 0))
5853         {
5854             wcsncpy_s(szName, cchName, name.GetUnicode(), min(nameLength, cchName - 1));
5855         }
5856
5857         if (NULL != pcchName)
5858         {
5859             *pcchName = nameLength;
5860         }
5861     }
5862
5863     // Get the parent application domain.
5864     if (pAppDomainId)
5865     {
5866         *pAppDomainId = (AppDomainID) pAssembly->GetDomain();
5867         _ASSERTE(*pAppDomainId != NULL);
5868     }
5869
5870     // Find the module the manifest lives in.
5871     if (pModuleId)
5872     {
5873         *pModuleId = (ModuleID) pAssembly->GetManifestModule();
5874
5875         // This is the case where the profiler has called GetAssemblyInfo
5876         // on an assembly that has been completely created yet.
5877         if (!*pModuleId)
5878             hr = CORPROF_E_DATAINCOMPLETE;
5879     }
5880
5881     return (hr);
5882 }
5883
5884 // Setting ELT hooks is only allowed from within Initialize().  However, test-only
5885 // profilers may need to set those hooks from an attaching profiling.  See
5886 // code:ProfControlBlock#TestOnlyELT
5887 #ifdef PROF_TEST_ONLY_FORCE_ELT
5888 #define PROFILER_TO_CLR_ENTRYPOINT_SET_ELT(logParams)                                   \
5889     do                                                                                  \
5890     {                                                                                   \
5891         if (g_profControlBlock.fTestOnlyForceEnterLeave)                                \
5892         {                                                                               \
5893             PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach, logParams);  \
5894         }                                                                               \
5895         else                                                                            \
5896         {                                                                               \
5897             PROFILER_TO_CLR_ENTRYPOINT_CALLABLE_ON_INIT_ONLY(logParams);                \
5898         }                                                                               \
5899     } while(0)
5900 #else //  PROF_TEST_ONLY_FORCE_ELT
5901 #define PROFILER_TO_CLR_ENTRYPOINT_SET_ELT                                              \
5902     PROFILER_TO_CLR_ENTRYPOINT_CALLABLE_ON_INIT_ONLY
5903 #endif //  PROF_TEST_ONLY_FORCE_ELT
5904
5905
5906 HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks(FunctionEnter * pFuncEnter,
5907                                                           FunctionLeave * pFuncLeave,
5908                                                           FunctionTailcall * pFuncTailcall)
5909 {
5910     CONTRACTL
5911     {
5912         // Yay!
5913         NOTHROW;
5914
5915         // Yay!
5916         GC_NOTRIGGER;
5917
5918         // Yay!
5919         MODE_ANY;
5920
5921         // Yay!
5922         EE_THREAD_NOT_REQUIRED;
5923
5924         CANNOT_TAKE_LOCK;
5925
5926         SO_NOT_MAINLINE;
5927     }
5928     CONTRACTL_END;
5929
5930     // The profiler must call SetEnterLeaveFunctionHooks during initialization, since
5931     // the enter/leave events are immutable and must also be set during initialization.
5932     PROFILER_TO_CLR_ENTRYPOINT_SET_ELT((LF_CORPROF, 
5933                                         LL_INFO10, 
5934                                         "**PROF: SetEnterLeaveFunctionHooks 0x%p, 0x%p, 0x%p.\n",
5935                                         pFuncEnter, 
5936                                         pFuncLeave, 
5937                                         pFuncTailcall));
5938
5939     return g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks(pFuncEnter, pFuncLeave, pFuncTailcall);
5940 }
5941
5942
5943 HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks2(FunctionEnter2 * pFuncEnter,
5944                                                            FunctionLeave2 * pFuncLeave,
5945                                                            FunctionTailcall2 * pFuncTailcall)
5946 {
5947     CONTRACTL
5948     {
5949         // Yay!
5950         NOTHROW;
5951
5952         // Yay!
5953         GC_NOTRIGGER;
5954
5955         // Yay!
5956         MODE_ANY;
5957
5958         // Yay!
5959         EE_THREAD_NOT_REQUIRED;
5960
5961         CANNOT_TAKE_LOCK;
5962
5963         SO_NOT_MAINLINE;
5964     }
5965     CONTRACTL_END;
5966
5967     // The profiler must call SetEnterLeaveFunctionHooks2 during initialization, since
5968     // the enter/leave events are immutable and must also be set during initialization.
5969     PROFILER_TO_CLR_ENTRYPOINT_SET_ELT((LF_CORPROF, 
5970                                         LL_INFO10, 
5971                                         "**PROF: SetEnterLeaveFunctionHooks2 0x%p, 0x%p, 0x%p.\n", 
5972                                         pFuncEnter, 
5973                                         pFuncLeave, 
5974                                         pFuncTailcall));    
5975
5976     return 
5977         g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks2(pFuncEnter, pFuncLeave, pFuncTailcall);
5978 }
5979
5980
5981 HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks3(FunctionEnter3 * pFuncEnter3,
5982                                                            FunctionLeave3 * pFuncLeave3,
5983                                                            FunctionTailcall3 * pFuncTailcall3)
5984 {
5985     CONTRACTL
5986     {
5987         // Yay!
5988         NOTHROW;
5989
5990         // Yay!
5991         GC_NOTRIGGER;
5992
5993         // Yay!
5994         MODE_ANY;
5995
5996         // Yay!
5997         EE_THREAD_NOT_REQUIRED;
5998
5999         CANNOT_TAKE_LOCK;
6000
6001         SO_NOT_MAINLINE;
6002     }
6003     CONTRACTL_END;
6004
6005     // The profiler must call SetEnterLeaveFunctionHooks3 during initialization, since
6006     // the enter/leave events are immutable and must also be set during initialization.
6007     PROFILER_TO_CLR_ENTRYPOINT_SET_ELT((LF_CORPROF, 
6008                                         LL_INFO10, 
6009                                         "**PROF: SetEnterLeaveFunctionHooks3 0x%p, 0x%p, 0x%p.\n", 
6010                                         pFuncEnter3, 
6011                                         pFuncLeave3, 
6012                                         pFuncTailcall3));    
6013
6014     return 
6015         g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks3(pFuncEnter3, 
6016                                                                        pFuncLeave3, 
6017                                                                        pFuncTailcall3);
6018 }
6019
6020
6021
6022 HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks3WithInfo(FunctionEnter3WithInfo * pFuncEnter3WithInfo,
6023                                                                    FunctionLeave3WithInfo * pFuncLeave3WithInfo,
6024                                                                    FunctionTailcall3WithInfo * pFuncTailcall3WithInfo)
6025 {
6026     CONTRACTL
6027     {
6028         // Yay!
6029         NOTHROW;
6030
6031         // Yay!
6032         GC_NOTRIGGER;
6033
6034         // Yay!
6035         MODE_ANY;
6036
6037         // Yay!
6038         EE_THREAD_NOT_REQUIRED;
6039
6040         CANNOT_TAKE_LOCK;
6041
6042         SO_NOT_MAINLINE;
6043     }
6044     CONTRACTL_END;
6045
6046     // The profiler must call SetEnterLeaveFunctionHooks3WithInfo during initialization, since
6047     // the enter/leave events are immutable and must also be set during initialization.
6048     PROFILER_TO_CLR_ENTRYPOINT_SET_ELT((LF_CORPROF,
6049                                         LL_INFO10, 
6050                                         "**PROF: SetEnterLeaveFunctionHooks3WithInfo 0x%p, 0x%p, 0x%p.\n", 
6051                                         pFuncEnter3WithInfo, 
6052                                         pFuncLeave3WithInfo, 
6053                                         pFuncTailcall3WithInfo));    
6054
6055     return 
6056         g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks3WithInfo(pFuncEnter3WithInfo, 
6057                                                                                pFuncLeave3WithInfo, 
6058                                                                                pFuncTailcall3WithInfo);
6059 }
6060
6061
6062 HRESULT ProfToEEInterfaceImpl::SetFunctionIDMapper(FunctionIDMapper *pFunc)
6063 {
6064     CONTRACTL
6065     {
6066         // Yay!
6067         NOTHROW;
6068
6069         // Yay!
6070         GC_NOTRIGGER;
6071
6072         // Yay!
6073         MODE_ANY;
6074
6075         // Yay!
6076         EE_THREAD_NOT_REQUIRED;
6077
6078         // Yay!
6079         CANNOT_TAKE_LOCK;
6080     
6081         SO_NOT_MAINLINE;
6082     }
6083     CONTRACTL_END;
6084     
6085     PROFILER_TO_CLR_ENTRYPOINT_ASYNC((LF_CORPROF, 
6086                                       LL_INFO10, 
6087                                       "**PROF: SetFunctionIDMapper 0x%p.\n",
6088                                       pFunc));
6089     
6090     g_profControlBlock.pProfInterface->SetFunctionIDMapper(pFunc);
6091
6092     return (S_OK);
6093 }
6094
6095 HRESULT ProfToEEInterfaceImpl::SetFunctionIDMapper2(FunctionIDMapper2 *pFunc, void * clientData)
6096 {
6097     CONTRACTL
6098     {
6099         // Yay!
6100         NOTHROW;
6101
6102         // Yay!
6103         GC_NOTRIGGER;
6104
6105         // Yay!
6106         MODE_ANY;
6107
6108         // Yay!
6109         EE_THREAD_NOT_REQUIRED;
6110
6111         // Yay!
6112         CANNOT_TAKE_LOCK;
6113     
6114         SO_NOT_MAINLINE;
6115     }
6116     CONTRACTL_END;
6117     
6118     PROFILER_TO_CLR_ENTRYPOINT_ASYNC((LF_CORPROF, 
6119                                       LL_INFO10, 
6120                                       "**PROF: SetFunctionIDMapper2. pFunc: 0x%p. clientData: 0x%p.\n",
6121                                       pFunc,
6122                                       clientData));
6123     
6124     g_profControlBlock.pProfInterface->SetFunctionIDMapper2(pFunc, clientData);
6125
6126     return (S_OK);
6127 }
6128
6129 /*
6130  * GetFunctionInfo2
6131  *
6132  * This function takes the frameInfo returned from a profiler callback and splays it
6133  * out into as much information as possible.
6134  *
6135  * Parameters:
6136  *   funcId - The function that is being requested.
6137  *   frameInfo - Frame specific information from a callback (for resolving generics).
6138  *   pClassId - An optional parameter for returning the class id of the function.
6139  *   pModuleId - An optional parameter for returning the module of the function.
6140  *   pToken - An optional parameter for returning the metadata token of the function.
6141  *   cTypeArgs - The count of the size of the array typeArgs
6142  *   pcTypeArgs - Returns the number of elements of typeArgs filled in, or if typeArgs is NULL
6143  *         the number that would be needed.
6144  *   typeArgs - An array to store generic type parameters for the function.
6145  *
6146  * Returns:
6147  *   S_OK if successful.
6148  */
6149 HRESULT ProfToEEInterfaceImpl::GetFunctionInfo2(FunctionID funcId,
6150                                              COR_PRF_FRAME_INFO frameInfo,
6151                                              ClassID *pClassId,
6152                                              ModuleID *pModuleId,
6153                                              mdToken *pToken,
6154                                              ULONG32 cTypeArgs,
6155                                              ULONG32 *pcTypeArgs,
6156                                              ClassID typeArgs[])
6157 {
6158     CONTRACTL
6159     {
6160         // Yay!
6161         NOTHROW;
6162
6163         // Yay!
6164         GC_NOTRIGGER;
6165
6166         // Yay!
6167         MODE_ANY;
6168
6169         // Yay!
6170         EE_THREAD_NOT_REQUIRED;
6171
6172         // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation eventually
6173         // reads metadata which causes us to take a reader lock.  However, see
6174         // code:#DisableLockOnAsyncCalls
6175         DISABLED(CAN_TAKE_LOCK);
6176
6177         // Asynchronous functions can be called at arbitrary times when runtime 
6178         // is holding locks that cannot be reentered without causing deadlock.
6179         // This contract detects any attempts to reenter locks held at the time 
6180         // this function was called.  
6181         CANNOT_RETAKE_LOCK;
6182
6183         SO_NOT_MAINLINE;
6184
6185         PRECONDITION(CheckPointer(pClassId, NULL_OK));
6186         PRECONDITION(CheckPointer(pModuleId, NULL_OK));
6187         PRECONDITION(CheckPointer(pToken,  NULL_OK));
6188         PRECONDITION(CheckPointer(pcTypeArgs, NULL_OK));
6189         PRECONDITION(CheckPointer(typeArgs, NULL_OK));
6190     }
6191     CONTRACTL_END;
6192
6193     // See code:#DisableLockOnAsyncCalls
6194     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
6195
6196     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
6197         (LF_CORPROF, 
6198         LL_INFO1000, 
6199         "**PROF: GetFunctionInfo2 0x%p.\n",
6200         funcId));
6201
6202     //
6203     // Verify parameters.
6204     //
6205     COR_PRF_FRAME_INFO_INTERNAL *pFrameInfo = (COR_PRF_FRAME_INFO_INTERNAL *)frameInfo;
6206
6207     if ((funcId == NULL) ||
6208         ((pFrameInfo != NULL) && (pFrameInfo->funcID != funcId)))
6209     {
6210         return E_INVALIDARG;
6211     }
6212
6213     MethodDesc *pMethDesc = FunctionIdToMethodDesc(funcId);
6214
6215     if (pMethDesc == NULL)
6216     {
6217         return E_INVALIDARG;
6218     }
6219
6220     if ((cTypeArgs != 0) && (typeArgs == NULL))
6221     {
6222         return E_INVALIDARG;
6223     }
6224
6225     // it's not safe to examine a methoddesc that has not been restored so do not do so
6226     if (!pMethDesc ->IsRestored())
6227         return CORPROF_E_DATAINCOMPLETE;      
6228
6229     //
6230     // Find the exact instantiation of this function.
6231     //
6232     TypeHandle specificClass;
6233     MethodDesc* pActualMethod;
6234
6235     ClassID classId = NULL;
6236
6237     if (pMethDesc->IsSharedByGenericInstantiations())
6238     {
6239         BOOL exactMatch;
6240         OBJECTREF pThis = NULL;
6241
6242         if (pFrameInfo != NULL)
6243         {
6244             // If FunctionID represents a generic methoddesc on a struct, then pFrameInfo->thisArg
6245             // isn't an Object*.  It's a pointer directly into the struct's members (i.e., it's not pointing at the
6246             // method table).  That means pFrameInfo->thisArg cannot be casted to an OBJECTREF for
6247             // use by Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation.  However,
6248             // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation won't even need a this pointer
6249             // for the methoddesc it's processing if the methoddesc is on a value type.  So we
6250             // can safely pass NULL for the methoddesc's this in such a case.
6251             if (pMethDesc->GetMethodTable()->IsValueType())
6252             {
6253                 _ASSERTE(!pMethDesc->AcquiresInstMethodTableFromThis());
6254                 _ASSERTE(pThis == NULL);
6255             }
6256             else
6257             {
6258                 pThis = ObjectToOBJECTREF((PTR_Object)(pFrameInfo->thisArg));
6259             }
6260         }
6261
6262         exactMatch = Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation(
6263             pMethDesc,
6264             pThis,
6265             PTR_VOID((pFrameInfo != NULL) ? pFrameInfo->extraArg : NULL),
6266             &specificClass,
6267             &pActualMethod);
6268
6269         if (exactMatch)
6270         {
6271             classId = TypeHandleToClassID(specificClass);
6272         }
6273         else if (!specificClass.HasInstantiation() || !specificClass.IsSharedByGenericInstantiations())
6274         {
6275             //
6276             // In this case we could not get the type args for the method, but if the class 
6277             // is not a generic class or is instantiated with value types, this value is correct.
6278             //
6279             classId = TypeHandleToClassID(specificClass);
6280         }
6281         else
6282         {
6283             //
6284             // We could not get any class information.
6285             //
6286             classId = NULL;
6287         }
6288     }
6289     else
6290     {
6291         TypeHandle typeHandle(pMethDesc->GetMethodTable());
6292         classId = TypeHandleToClassID(typeHandle);
6293         pActualMethod = pMethDesc;
6294     }
6295
6296
6297     //
6298     // Fill in the ClassId, if desired
6299     //
6300     if (pClassId != NULL)
6301     {
6302         *pClassId = classId;
6303     }
6304
6305     //
6306     // Fill in the ModuleId, if desired.
6307     //
6308     if (pModuleId != NULL)
6309     {
6310         *pModuleId = (ModuleID)pMethDesc->GetModule();
6311     }
6312
6313     //
6314     // Fill in the token, if desired.
6315     //
6316     if (pToken != NULL)
6317     {
6318         *pToken = (mdToken)pMethDesc->GetMemberDef();
6319     }
6320
6321     if ((cTypeArgs == 0) && (pcTypeArgs != NULL))
6322     {
6323         //
6324         // They are searching for the size of the array needed, we can return that now and
6325         // short-circuit all the work below.
6326         //
6327         if (pcTypeArgs != NULL)
6328         {
6329             *pcTypeArgs = pActualMethod->GetNumGenericMethodArgs();
6330         }
6331         return S_OK;
6332     }
6333
6334     //
6335     // If no place to store resulting count, quit now.
6336     //
6337     if (pcTypeArgs == NULL)
6338     {
6339         return S_OK;
6340     }
6341
6342     //
6343     // Fill in the type args
6344     //
6345     DWORD cArgsToFill = pActualMethod->GetNumGenericMethodArgs();
6346
6347     if (cArgsToFill > cTypeArgs)
6348     {
6349         cArgsToFill = cTypeArgs;
6350     }
6351
6352     *pcTypeArgs = cArgsToFill;
6353
6354     if (cArgsToFill == 0)
6355     {
6356         return S_OK;
6357     }
6358
6359     Instantiation inst = pActualMethod->GetMethodInstantiation();
6360
6361     for (DWORD i = 0; i < cArgsToFill; i++)
6362     {
6363         typeArgs[i] = TypeHandleToClassID(inst[i]);
6364     }
6365
6366     return S_OK;
6367 }
6368
6369 /*
6370 * IsFunctionDynamic
6371 *
6372 * This function takes a functionId that maybe of a metadata-less method like an IL Stub
6373 * or LCG method and returns true in the pHasNoMetadata if it is indeed a metadata-less
6374 * method.
6375 *
6376 * Parameters:
6377 *   functionId - The function that is being requested.
6378 *   isDynamic - An optional parameter for returning if the function has metadata or not.
6379 *
6380 * Returns:
6381 *   S_OK if successful.
6382 */
6383 HRESULT ProfToEEInterfaceImpl::IsFunctionDynamic(FunctionID functionId, BOOL *isDynamic)
6384 {
6385     CONTRACTL
6386     {
6387         NOTHROW;
6388         GC_NOTRIGGER;
6389         MODE_ANY;
6390         EE_THREAD_NOT_REQUIRED;
6391
6392         // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation eventually
6393         // reads metadata which causes us to take a reader lock.  However, see
6394         // code:#DisableLockOnAsyncCalls
6395         DISABLED(CAN_TAKE_LOCK);
6396
6397         // Asynchronous functions can be called at arbitrary times when runtime 
6398         // is holding locks that cannot be reentered without causing deadlock.
6399         // This contract detects any attempts to reenter locks held at the time 
6400         // this function was called.  
6401         CANNOT_RETAKE_LOCK;
6402
6403         SO_NOT_MAINLINE;
6404
6405         PRECONDITION(CheckPointer(isDynamic, NULL_OK));
6406     }
6407     CONTRACTL_END;
6408
6409     // See code:#DisableLockOnAsyncCalls
6410     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
6411
6412     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
6413         (LF_CORPROF,
6414             LL_INFO1000,
6415             "**PROF: IsFunctionDynamic 0x%p.\n",
6416             functionId));
6417
6418     //
6419     // Verify parameters.
6420     //
6421
6422     if (functionId == NULL)
6423     {
6424         return E_INVALIDARG;
6425     }
6426
6427     MethodDesc *pMethDesc = FunctionIdToMethodDesc(functionId);
6428
6429     if (pMethDesc == NULL)
6430     {
6431         return E_INVALIDARG;
6432     }
6433
6434     // it's not safe to examine a methoddesc that has not been restored so do not do so
6435     if (!pMethDesc->IsRestored())
6436         return CORPROF_E_DATAINCOMPLETE;
6437
6438     //
6439     // Fill in the pHasNoMetadata, if desired.
6440     //
6441     if (isDynamic != NULL)
6442     {
6443         *isDynamic = pMethDesc->IsNoMetadata();
6444     }
6445
6446     return S_OK;
6447 }
6448
6449 /*
6450 * GetFunctionFromIP3
6451 *
6452 * This function takes an IP and determines if it is a managed function returning its
6453 * FunctionID. This method is different from GetFunctionFromIP in that will return
6454 * FunctionIDs even if they have no associated metadata.
6455 *
6456 * Parameters:
6457 *   ip - The instruction pointer.
6458 *   pFunctionId - An optional parameter for returning the FunctionID.
6459 *   pReJitId - The ReJIT id.
6460 *
6461 * Returns:
6462 *   S_OK if successful.
6463 */
6464 HRESULT ProfToEEInterfaceImpl::GetFunctionFromIP3(LPCBYTE ip, FunctionID * pFunctionId, ReJITID * pReJitId)
6465 {
6466     CONTRACTL
6467     {
6468         NOTHROW;
6469
6470         // Grabbing the rejitid requires entering the rejit manager's hash table & lock,
6471         // which can switch us to preemptive mode and trigger GCs
6472         GC_TRIGGERS;
6473         MODE_ANY;
6474         EE_THREAD_NOT_REQUIRED;
6475
6476         // Grabbing the rejitid requires entering the rejit manager's hash table & lock,
6477         CAN_TAKE_LOCK;
6478
6479         SO_NOT_MAINLINE;
6480     }
6481     CONTRACTL_END;
6482
6483     // See code:#DisableLockOnAsyncCalls
6484     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
6485
6486     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
6487         kP2EEAllowableAfterAttach | kP2EETriggers,
6488         (LF_CORPROF,
6489             LL_INFO1000,
6490             "**PROF: GetFunctionFromIP3 0x%p.\n",
6491             ip));
6492
6493     HRESULT hr = S_OK;
6494
6495     EECodeInfo codeInfo;
6496
6497     hr = GetFunctionFromIPInternal(ip, &codeInfo, /* failOnNoMetadata */ FALSE);
6498     if (FAILED(hr))
6499     {
6500         return hr;
6501     }
6502
6503     if (pFunctionId)
6504     {
6505         *pFunctionId = MethodDescToFunctionID(codeInfo.GetMethodDesc());
6506     }
6507
6508     if (pReJitId != NULL)
6509     {
6510         MethodDesc * pMD = codeInfo.GetMethodDesc();
6511         *pReJitId = pMD->GetReJitManager()->GetReJitId(pMD, codeInfo.GetStartAddress());
6512     }
6513
6514     return S_OK;
6515 }
6516
6517 /*
6518 * GetDynamicFunctionInfo
6519 *
6520 * This function takes a functionId that maybe of a metadata-less method like an IL Stub
6521 * or LCG method and gives information about it without failing like GetFunctionInfo.
6522 *
6523 * Parameters:
6524 *   functionId - The function that is being requested.
6525 *   pModuleId - An optional parameter for returning the module of the function.
6526 *   ppvSig -  An optional parameter for returning the signature of the function.
6527 *   pbSig - An optional parameter for returning the size of the signature of the function.
6528 *   cchName - A parameter for indicating the size of buffer for the wszName parameter.
6529 *   pcchName - An optional parameter for returning the true size of the wszName parameter.
6530 *   wszName - A parameter to the caller allocated buffer of size cchName
6531 *
6532 * Returns:
6533 *   S_OK if successful.
6534 */
6535 HRESULT ProfToEEInterfaceImpl::GetDynamicFunctionInfo(FunctionID functionId,
6536                                                       ModuleID *pModuleId,
6537                                                       PCCOR_SIGNATURE* ppvSig,
6538                                                       ULONG* pbSig,
6539                                                       ULONG cchName,
6540                                                       ULONG *pcchName,
6541             __out_ecount_part_opt(cchName, *pcchName) WCHAR wszName[])
6542 {
6543     CONTRACTL
6544     {
6545         NOTHROW;
6546         GC_NOTRIGGER;
6547         MODE_ANY;
6548         EE_THREAD_NOT_REQUIRED;
6549
6550         // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation eventually
6551         // reads metadata which causes us to take a reader lock.  However, see
6552         // code:#DisableLockOnAsyncCalls
6553         DISABLED(CAN_TAKE_LOCK);
6554
6555         // Asynchronous functions can be called at arbitrary times when runtime 
6556         // is holding locks that cannot be reentered without causing deadlock.
6557         // This contract detects any attempts to reenter locks held at the time 
6558         // this function was called.  
6559         CANNOT_RETAKE_LOCK;
6560
6561         SO_NOT_MAINLINE;
6562
6563         PRECONDITION(CheckPointer(pModuleId, NULL_OK));
6564         PRECONDITION(CheckPointer(ppvSig, NULL_OK));
6565         PRECONDITION(CheckPointer(pbSig,  NULL_OK));
6566         PRECONDITION(CheckPointer(pcchName, NULL_OK));
6567     }
6568     CONTRACTL_END;
6569
6570     // See code:#DisableLockOnAsyncCalls
6571     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
6572
6573     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
6574         (LF_CORPROF,
6575             LL_INFO1000,
6576             "**PROF: GetDynamicFunctionInfo 0x%p.\n",
6577             functionId));
6578
6579     //
6580     // Verify parameters.
6581     //
6582
6583     if (functionId == NULL)
6584     {
6585         return E_INVALIDARG;
6586     }
6587
6588     MethodDesc *pMethDesc = FunctionIdToMethodDesc(functionId);
6589
6590     if (pMethDesc == NULL)
6591     {
6592         return E_INVALIDARG;
6593     }
6594
6595     // it's not safe to examine a methoddesc that has not been restored so do not do so
6596     if (!pMethDesc->IsRestored())
6597         return CORPROF_E_DATAINCOMPLETE;
6598
6599
6600     if (!pMethDesc->IsNoMetadata())
6601         return E_INVALIDARG;
6602
6603     //
6604     // Fill in the ModuleId, if desired.
6605     //
6606     if (pModuleId != NULL)
6607     {
6608         *pModuleId = (ModuleID)pMethDesc->GetModule();
6609     }
6610
6611     //
6612     // Fill in the ppvSig and pbSig, if desired
6613     //
6614     if (ppvSig != NULL && pbSig != NULL)
6615     {
6616         pMethDesc->GetSig(ppvSig, pbSig);
6617     }
6618
6619     HRESULT hr = S_OK;
6620
6621     EX_TRY
6622     {
6623         if (wszName != NULL)
6624             *wszName = 0;
6625         if (pcchName != NULL)
6626             *pcchName = 0;
6627
6628         StackSString ss;
6629         ss.SetUTF8(pMethDesc->GetName());
6630         ss.Normalize();
6631         LPCWSTR methodName = ss.GetUnicode();
6632
6633         ULONG trueLen = (ULONG)(wcslen(methodName) + 1);
6634
6635         // Return name of method as required.
6636         if (wszName && cchName > 0)
6637         {
6638             if (cchName < trueLen)
6639             {
6640                 hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
6641             }
6642             else
6643             {
6644                 wcsncpy_s(wszName, cchName, methodName, trueLen);
6645             }
6646         }
6647
6648         // If they request the actual length of the name
6649         if (pcchName)
6650             *pcchName = trueLen;
6651     }
6652     EX_CATCH_HRESULT(hr);
6653
6654     return (hr);
6655 }
6656
6657 /*
6658  * GetStringLayout
6659  *
6660  * This function describes to a profiler the internal layout of a string.
6661  *
6662  * Parameters:
6663  *   pBufferLengthOffset - Offset within an OBJECTREF of a string of the ArrayLength field.
6664  *   pStringLengthOffset - Offset within an OBJECTREF of a string of the StringLength field.
6665  *   pBufferOffset - Offset within an OBJECTREF of a string of the Buffer field.
6666  *
6667  * Returns:
6668  *   S_OK if successful.
6669  */
6670 HRESULT ProfToEEInterfaceImpl::GetStringLayout(ULONG *pBufferLengthOffset,
6671                                              ULONG *pStringLengthOffset,
6672                                              ULONG *pBufferOffset)
6673 {
6674     CONTRACTL
6675     {
6676         // Yay!
6677         NOTHROW;
6678
6679         // Yay!
6680         GC_NOTRIGGER;
6681
6682         // Yay!
6683         MODE_ANY;
6684
6685         // Yay!
6686         EE_THREAD_NOT_REQUIRED;
6687
6688         // Yay!
6689         CANNOT_TAKE_LOCK;
6690
6691         SO_NOT_MAINLINE;
6692
6693         PRECONDITION(CheckPointer(pBufferLengthOffset, NULL_OK));
6694         PRECONDITION(CheckPointer(pStringLengthOffset, NULL_OK));
6695         PRECONDITION(CheckPointer(pBufferOffset,  NULL_OK));
6696     }
6697     CONTRACTL_END;
6698
6699     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
6700         (LF_CORPROF, 
6701         LL_INFO1000, 
6702         "**PROF: GetStringLayout.\n"));
6703
6704     return this->GetStringLayoutHelper(pBufferLengthOffset, pStringLengthOffset, pBufferOffset);
6705 }
6706
6707 /*
6708  * GetStringLayout2
6709  *
6710  * This function describes to a profiler the internal layout of a string.
6711  *
6712  * Parameters:
6713  *   pStringLengthOffset - Offset within an OBJECTREF of a string of the StringLength field.
6714  *   pBufferOffset - Offset within an OBJECTREF of a string of the Buffer field.
6715  *
6716  * Returns:
6717  *   S_OK if successful.
6718  */
6719 HRESULT ProfToEEInterfaceImpl::GetStringLayout2(ULONG *pStringLengthOffset,
6720                                              ULONG *pBufferOffset)
6721 {
6722     CONTRACTL
6723     {
6724         // Yay!
6725         NOTHROW;
6726
6727         // Yay!
6728         GC_NOTRIGGER;
6729
6730         // Yay!
6731         MODE_ANY;
6732
6733         // Yay!
6734         EE_THREAD_NOT_REQUIRED;
6735
6736         // Yay!
6737         CANNOT_TAKE_LOCK;
6738
6739         SO_NOT_MAINLINE;
6740
6741         PRECONDITION(CheckPointer(pStringLengthOffset, NULL_OK));
6742         PRECONDITION(CheckPointer(pBufferOffset,  NULL_OK));
6743     }
6744     CONTRACTL_END;
6745
6746     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
6747         (LF_CORPROF, 
6748         LL_INFO1000, 
6749         "**PROF: GetStringLayout2.\n"));
6750
6751     ULONG dummyBufferLengthOffset;
6752     return this->GetStringLayoutHelper(&dummyBufferLengthOffset, pStringLengthOffset, pBufferOffset);
6753 }
6754
6755 /*
6756  * GetStringLayoutHelper
6757  *
6758  * This function describes to a profiler the internal layout of a string.
6759  *
6760  * Parameters:
6761  *   pBufferLengthOffset - Offset within an OBJECTREF of a string of the ArrayLength field.
6762  *   pStringLengthOffset - Offset within an OBJECTREF of a string of the StringLength field.
6763  *   pBufferOffset - Offset within an OBJECTREF of a string of the Buffer field.
6764  *
6765  * Returns:
6766  *   S_OK if successful.
6767  */
6768 HRESULT ProfToEEInterfaceImpl::GetStringLayoutHelper(ULONG *pBufferLengthOffset,
6769                                              ULONG *pStringLengthOffset,
6770                                              ULONG *pBufferOffset)
6771 {
6772     CONTRACTL
6773     {
6774         // Yay!
6775         NOTHROW;
6776
6777         // Yay!
6778         GC_NOTRIGGER;
6779
6780         // Yay!
6781         MODE_ANY;
6782
6783         // Yay!
6784         EE_THREAD_NOT_REQUIRED;
6785
6786         // Yay!
6787         CANNOT_TAKE_LOCK;
6788
6789         SO_NOT_MAINLINE;
6790
6791         PRECONDITION(CheckPointer(pBufferLengthOffset, NULL_OK));
6792         PRECONDITION(CheckPointer(pStringLengthOffset, NULL_OK));
6793         PRECONDITION(CheckPointer(pBufferOffset,  NULL_OK));
6794     }
6795     CONTRACTL_END;
6796
6797     // The String class no longer has a bufferLength field in it.
6798     // We are returning the offset of the stringLength because that is the closest we can get
6799     // This is most certainly a breaking change and a new method 
6800     // ICorProfilerInfo3::GetStringLayout2 has been added on the interface ICorProfilerInfo3
6801     if (pBufferLengthOffset != NULL)
6802     {
6803         *pBufferLengthOffset = StringObject::GetStringLengthOffset();
6804     }
6805
6806     if (pStringLengthOffset != NULL)
6807     {
6808         *pStringLengthOffset = StringObject::GetStringLengthOffset();
6809     }
6810
6811     if (pBufferOffset != NULL)
6812     {
6813         *pBufferOffset = StringObject::GetBufferOffset();
6814     }
6815
6816     return S_OK;
6817 }
6818
6819 /*
6820  * GetClassLayout
6821  *
6822  * This function describes to a profiler the internal layout of a class.
6823  *
6824  * Parameters:
6825  *   classID - The class that is being queried.  It is really a TypeHandle.
6826  *   rFieldOffset - An array to store information about each field in the class.
6827  *   cFieldOffset - Count of the number of elements in rFieldOffset.
6828  *   pcFieldOffset - Upon return contains the number of elements filled in, or if
6829  *         cFieldOffset is zero, the number of elements needed.
6830  *   pulClassSize - Optional parameter for containing the size in bytes of the underlying
6831  *         internal class structure.
6832  *
6833  * Returns:
6834  *   S_OK if successful.
6835  */
6836 HRESULT ProfToEEInterfaceImpl::GetClassLayout(ClassID classID,
6837                                              COR_FIELD_OFFSET rFieldOffset[],
6838                                              ULONG cFieldOffset,
6839                                              ULONG *pcFieldOffset,
6840                                              ULONG *pulClassSize)
6841 {
6842     CONTRACTL
6843     {
6844         // Yay!
6845         NOTHROW;
6846
6847         // Yay!
6848         GC_NOTRIGGER;
6849
6850         // Yay!
6851         MODE_ANY;
6852
6853         // Yay!
6854         EE_THREAD_NOT_REQUIRED;
6855
6856         // Yay!
6857         CANNOT_TAKE_LOCK;
6858
6859         SO_NOT_MAINLINE;
6860
6861         PRECONDITION(CheckPointer(rFieldOffset, NULL_OK));
6862         PRECONDITION(CheckPointer(pcFieldOffset));
6863         PRECONDITION(CheckPointer(pulClassSize,  NULL_OK));
6864     }
6865     CONTRACTL_END;
6866     
6867     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
6868         (LF_CORPROF, 
6869         LL_INFO1000, 
6870         "**PROF: GetClassLayout 0x%p.\n", 
6871         classID));
6872     
6873     //
6874     // Verify parameters
6875     //
6876     if ((pcFieldOffset == NULL) || (classID == NULL))
6877     {
6878          return E_INVALIDARG;
6879     }
6880
6881     if ((cFieldOffset != 0) && (rFieldOffset == NULL))
6882     {
6883         return E_INVALIDARG;
6884     }
6885
6886     TypeHandle typeHandle = TypeHandle::FromPtr((void *)classID);
6887
6888     //
6889     // This is the incorrect API for arrays or strings.  Use GetArrayObjectInfo, and GetStringLayout
6890     //
6891     if (typeHandle.IsTypeDesc() || typeHandle.AsMethodTable()->IsArray())
6892     {
6893         return E_INVALIDARG;
6894     }
6895
6896     //
6897     // We used to have a bug where this API incorrectly succeeded for strings during startup. Profilers
6898     // took dependency on this bug. Let the API to succeed for strings during startup for backward compatibility.
6899     //
6900     if (typeHandle.AsMethodTable()->IsString() && g_profControlBlock.fBaseSystemClassesLoaded)
6901     {
6902         return E_INVALIDARG;
6903     }
6904
6905     //
6906     // If this class is not fully restored, that is all the information we can get at this time.
6907     //
6908     if (!typeHandle.IsRestored())
6909     {
6910         return CORPROF_E_DATAINCOMPLETE;
6911     }
6912
6913     // Types can be pre-restored, but they still aren't expected to handle queries before
6914     // eager fixups have run. This is a targetted band-aid for a bug intellitrace was
6915     // running into - attempting to get the class layout for all types at module load time.
6916     // If we don't detect this the runtime will AV during the field iteration below. Feel
6917     // free to eliminate this check when a more complete solution is available.
6918     if (CORCOMPILE_IS_POINTER_TAGGED(*(typeHandle.AsMethodTable()->GetParentMethodTablePtr())))
6919     {
6920         return CORPROF_E_DATAINCOMPLETE;
6921     }
6922
6923     // !IsValueType = IsArray || IsReferenceType   Since IsArry has been ruled out above, it must 
6924     // be a reference type if !IsValueType.
6925     BOOL fReferenceType = !typeHandle.IsValueType();
6926
6927     //
6928     // Fill in class size now
6929     //
6930     // Move after the check for typeHandle.GetMethodTable()->IsRestored() 
6931     // because an unrestored MethodTable may have a bad EE class pointer
6932     // which will be used by MethodTable::GetNumInstanceFieldBytes
6933     //
6934     if (pulClassSize != NULL)
6935     {
6936         if (fReferenceType)
6937         {
6938             // aligned size including the object header for reference types
6939             *pulClassSize = typeHandle.GetMethodTable()->GetBaseSize();
6940         }
6941         else
6942         {
6943             // unboxed and unaligned size for value types
6944             *pulClassSize = typeHandle.GetMethodTable()->GetNumInstanceFieldBytes();
6945         }
6946     }
6947
6948     ApproxFieldDescIterator fieldDescIterator(typeHandle.GetMethodTable(), ApproxFieldDescIterator::INSTANCE_FIELDS);
6949
6950     ULONG cFields = fieldDescIterator.Count();
6951
6952     //
6953     // If they are looking to just get the count, return that.
6954     //
6955     if ((cFieldOffset == 0)  || (rFieldOffset == NULL))
6956     {
6957         *pcFieldOffset = cFields;
6958         return S_OK;
6959     }
6960
6961     //
6962     // Dont put too many in the array.
6963     //
6964     if (cFields > cFieldOffset)
6965     {
6966         cFields = cFieldOffset;
6967     }
6968
6969     *pcFieldOffset = cFields;
6970
6971     //
6972     // Now fill in the array
6973     //
6974     ULONG i;
6975     FieldDesc *pField;
6976
6977     for (i = 0; i < cFields; i++)
6978     {
6979         pField = fieldDescIterator.Next();
6980         rFieldOffset[i].ridOfField = (ULONG)pField->GetMemberDef();
6981         rFieldOffset[i].ulOffset = (ULONG)pField->GetOffset() + (fReferenceType ? Object::GetOffsetOfFirstField() : 0);
6982     }
6983
6984     return S_OK;
6985 }
6986
6987
6988 typedef struct _PROFILER_STACK_WALK_DATA
6989 {
6990     StackSnapshotCallback *callback;
6991     ULONG32 infoFlags;
6992     ULONG32 contextFlags;
6993     void *clientData;
6994     
6995 #ifdef WIN64EXCEPTIONS
6996     StackFrame sfParent;
6997 #endif
6998 } PROFILER_STACK_WALK_DATA;
6999
7000
7001 /*
7002  * ProfilerStackWalkCallback
7003  *
7004  * This routine is used as the callback from the general stack walker for
7005  * doing snapshot stack walks
7006  *
7007  */
7008 StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_DATA *pData)
7009 {
7010     CONTRACTL
7011     {
7012         SO_NOT_MAINLINE;
7013         NOTHROW;  // throw is RIGHT out... the throw at minimum allocates the thrown object which we *must* not do
7014         GC_NOTRIGGER; // the stack is not necessarily crawlable at this state !!!) we must not induce a GC 
7015     } 
7016     CONTRACTL_END;
7017
7018     MethodDesc *pFunc = pCf->GetFunction();
7019
7020     COR_PRF_FRAME_INFO_INTERNAL frameInfo;
7021     ULONG32 contextSize = 0;
7022     BYTE *context = NULL;
7023
7024     UINT_PTR currentIP = 0;
7025     REGDISPLAY *pRegDisplay = pCf->GetRegisterSet();
7026 #if defined(_TARGET_X86_)
7027     CONTEXT builtContext;
7028 #endif
7029
7030     //
7031     // For Unmanaged-to-managed transitions we get a NativeMarker back, which we want
7032     // to return to the profiler as the context seed if it wants to walk the unmanaged
7033     // stack frame, so we report the functionId as NULL to indicate this.
7034     //
7035     if (pCf->IsNativeMarker())
7036     {
7037         pFunc = NULL;
7038     }
7039
7040     //
7041     // Skip all Lightweight reflection/emit functions
7042     //
7043     if ((pFunc != NULL) && pFunc->IsNoMetadata())
7044     {
7045         return SWA_CONTINUE;
7046     }
7047
7048     //
7049     // If this is not a transition of any sort and not a managed
7050     // method, ignore it.
7051     //
7052     if (!pCf->IsNativeMarker() && !pCf->IsFrameless())
7053     {
7054         return SWA_CONTINUE;
7055     }
7056
7057     currentIP = (UINT_PTR)pRegDisplay->ControlPC;
7058
7059     frameInfo.size = sizeof(COR_PRF_FRAME_INFO_INTERNAL);
7060     frameInfo.version = COR_PRF_FRAME_INFO_INTERNAL_CURRENT_VERSION;
7061
7062     if (pFunc != NULL)
7063     {
7064         frameInfo.funcID = MethodDescToFunctionID(pFunc);
7065         frameInfo.extraArg = NULL;
7066     }
7067     else
7068     {
7069         frameInfo.funcID = NULL;
7070         frameInfo.extraArg = NULL;
7071     }
7072
7073     frameInfo.IP = currentIP;
7074     frameInfo.thisArg = NULL;
7075
7076     if (pData->infoFlags & COR_PRF_SNAPSHOT_REGISTER_CONTEXT)
7077     {
7078 #if defined(_TARGET_X86_)
7079         //
7080         // X86 stack walking does not keep the context up-to-date during the
7081         // walk.  Instead it keeps the REGDISPLAY up-to-date.  Thus, we need to
7082         // build a CONTEXT from the REGDISPLAY.
7083         //
7084
7085         memset(&builtContext, 0, sizeof(builtContext));
7086         builtContext.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
7087         CopyRegDisplay(pRegDisplay, NULL, &builtContext);
7088         context = (BYTE *)(&builtContext);
7089 #else
7090         context = (BYTE *)pRegDisplay->pCurrentContext;
7091 #endif
7092         contextSize = sizeof(CONTEXT);
7093     }
7094     
7095     // NOTE:  We are intentionally not setting any callback state flags here (i.e., not using
7096     // SetCallbackStateFlagsHolder), as we want the DSS callback to "inherit" the
7097     // same callback state that DSS has:  if DSS was called asynchronously, then consider
7098     // the DSS callback to be called asynchronously.
7099     if (pData->callback(frameInfo.funcID,
7100                         frameInfo.IP,
7101                         (COR_PRF_FRAME_INFO)&frameInfo,
7102                         contextSize,
7103                         context,
7104                         pData->clientData) == S_OK)
7105     {
7106         return SWA_CONTINUE;
7107     }
7108
7109     return SWA_ABORT;
7110 }
7111
7112 #ifdef _TARGET_X86_
7113
7114 //---------------------------------------------------------------------------------------
7115 // Normally, calling GetFunction() on the frame is sufficient to ensure
7116 // HelperMethodFrames are intialized. However, sometimes we need to be able to specify
7117 // that we should not enter the host while initializing, so we need to initialize such
7118 // frames more directly. This small helper function directly forces the initialization,
7119 // and ensures we don't enter the host as a result if we're executing in an asynchronous
7120 // call (i.e., hijacked thread)
7121 //
7122 // Arguments:
7123 //      pFrame - Frame to initialize.
7124 //
7125 // Return Value:
7126 //     TRUE iff pFrame was successfully initialized (or was already initialized). If
7127 //     pFrame is not a HelperMethodFrame (or derived type), this returns TRUE
7128 //     immediately. FALSE indicates we tried to initialize w/out entering the host, and
7129 //     had to abort as a result when a reader lock was needed but unavailable.
7130 //
7131
7132 static BOOL EnsureFrameInitialized(Frame * pFrame)
7133 {
7134     CONTRACTL
7135     {
7136         NOTHROW;
7137         GC_NOTRIGGER;
7138
7139         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
7140         // host (SQL).  Corners will be cut to ensure this is the case
7141         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
7142
7143         SUPPORTS_DAC;
7144     }
7145     CONTRACTL_END;
7146
7147     if (pFrame->GetFrameType() != Frame::TYPE_HELPER_METHOD_FRAME)
7148     {
7149         // This frame is not a HelperMethodFrame or a frame derived from
7150         // HelperMethodFrame, so HMF-specific lazy initialization is not an issue.
7151         return TRUE;
7152     }
7153
7154     HelperMethodFrame * pHMF = (HelperMethodFrame *) pFrame;
7155
7156     if (pHMF->InsureInit(
7157         false,                      // initialInit
7158         NULL,                       // unwindState
7159         (ShouldAvoidHostCalls() ?
7160             NoHostCalls :
7161             AllowHostCalls)
7162         ) != NULL)
7163     {
7164         // InsureInit() succeeded and found the return address
7165         return TRUE;
7166     }
7167
7168     // No return address was found. It must be because we asked InsureInit() to bail if
7169     // it would have entered the host
7170     _ASSERTE(ShouldAvoidHostCalls());
7171     return FALSE;
7172 }
7173
7174 //---------------------------------------------------------------------------------------
7175 //
7176 // Implements the COR_PRF_SNAPSHOT_X86_OPTIMIZED algorithm called by DoStackSnapshot. 
7177 // Does a simple EBP walk, rather than invoking all of StackWalkFramesEx.
7178 //
7179 // Arguments:
7180 //      pThreadToSnapshot - Thread whose stack should be walked
7181 //      pctxSeed - Register context with which to seed the walk
7182 //      callback - Function to call at each frame found during the walk
7183 //      clientData - Parameter to pass through to callback
7184 //
7185 // Return Value:
7186 //     HRESULT indicating success or failure.
7187 //
7188
7189 HRESULT ProfToEEInterfaceImpl::ProfilerEbpWalker(
7190     Thread * pThreadToSnapshot, 
7191     LPCONTEXT pctxSeed, 
7192     StackSnapshotCallback * callback, 
7193     void * clientData)
7194 {
7195     CONTRACTL
7196     {
7197         GC_NOTRIGGER;
7198         NOTHROW;
7199         MODE_ANY;
7200         EE_THREAD_NOT_REQUIRED;
7201
7202         // If this is called asynchronously (from a hijacked thread, as with F1), it must not re-enter the
7203         // host (SQL).  Corners will be cut to ensure this is the case
7204         if (ShouldAvoidHostCalls()) { HOST_NOCALLS; } else { HOST_CALLS; }
7205     }
7206     CONTRACTL_END;
7207
7208     HRESULT hr;
7209
7210     // We haven't set the stackwalker thread type flag yet (see next line), so it shouldn't be set. Only
7211     // exception to this is if the current call is made by a hijacking profiler which
7212     // redirected this thread while it was previously in the middle of another stack walk
7213     _ASSERTE(IsCalledAsynchronously() || !IsStackWalkerThread());
7214
7215     // Remember that we're walking the stack.  This holder will reinstate the original
7216     // value of the stackwalker flag (from the thread type mask) in its destructor.
7217     ClrFlsValueSwitch _threadStackWalking(TlsIdx_StackWalkerWalkingThread, pThreadToSnapshot);
7218    
7219     // This flag remembers if we reported a managed frame since the last unmanaged block
7220     // we reported. It's used to avoid reporting two unmanaged blocks in a row.
7221     BOOL fReportedAtLeastOneManagedFrameSinceLastUnmanagedBlock = FALSE;
7222
7223     Frame * pFrameCur = pThreadToSnapshot->GetFrame();
7224
7225     CONTEXT ctxCur;
7226     ZeroMemory(&ctxCur, sizeof(ctxCur));
7227
7228     // Use seed if we got one.  Otherwise, EE explicit Frame chain will seed the walk.
7229     if (pctxSeed != NULL)
7230     {
7231         ctxCur.Ebp = pctxSeed->Ebp;
7232         ctxCur.Eip = pctxSeed->Eip;
7233         ctxCur.Esp = pctxSeed->Esp;
7234     }
7235
7236     while (TRUE)
7237     {
7238         // At each iteration of the loop:
7239         //     * Analyze current frame (get managed data if it's a managed frame)
7240         //     * Report current frame via callback()
7241         //     * Walk down to next frame
7242         
7243         // **** Managed or unmanaged frame? ****
7244         
7245         EECodeInfo codeInfo;
7246         MethodDesc * pMethodDescCur = NULL;
7247
7248         if (ctxCur.Eip != 0)
7249         {
7250             hr = GetFunctionInfoInternal(
7251                 (LPCBYTE) ctxCur.Eip, 
7252                 &codeInfo);
7253             if (hr == CORPROF_E_ASYNCHRONOUS_UNSAFE)
7254             {
7255                 _ASSERTE(ShouldAvoidHostCalls());
7256                 return hr;
7257             }
7258             if (SUCCEEDED(hr))
7259             {
7260                 pMethodDescCur = codeInfo.GetMethodDesc();
7261             }
7262         }
7263
7264         // **** Report frame to profiler ****
7265
7266         if (
7267             // Make sure the frame gave us an IP
7268             (ctxCur.Eip != 0) &&              
7269
7270             // Make sure any managed frame isn't for an IL stub or LCG
7271             ((pMethodDescCur == NULL) || !pMethodDescCur->IsNoMetadata()) &&
7272
7273             // Only report unmanaged frames if the last frame we reported was managed
7274             // (avoid reporting two unmanaged blocks in a row)
7275             ((pMethodDescCur != NULL) || fReportedAtLeastOneManagedFrameSinceLastUnmanagedBlock))
7276         {
7277             // Around the call to the profiler, temporarily clear the
7278             // ThreadType_StackWalker type flag, as we have no control over what the
7279             // profiler may do inside its callback (it could theoretically attempt to
7280             // load other types, though I don't personally know of profilers that
7281             // currently do this).
7282             
7283             CLEAR_THREAD_TYPE_STACKWALKER();
7284             hr = callback(
7285                 (FunctionID) pMethodDescCur, 
7286                 ctxCur.Eip, 
7287                 NULL,               // COR_PRF_FRAME_INFO
7288                 sizeof(ctxCur),     // contextSize,
7289                 (LPBYTE) &ctxCur,   // context,
7290                 clientData);
7291             SET_THREAD_TYPE_STACKWALKER(pThreadToSnapshot);
7292             
7293             if (hr != S_OK)
7294             {
7295                 return hr;
7296             }
7297             if (pMethodDescCur == NULL)
7298             {
7299                 // Just reported an unmanaged block, so reset the flag
7300                 fReportedAtLeastOneManagedFrameSinceLastUnmanagedBlock = FALSE;
7301             }
7302             else
7303             {
7304                 // Just reported a managed block, so remember it
7305                 fReportedAtLeastOneManagedFrameSinceLastUnmanagedBlock = TRUE;
7306             }
7307         }
7308
7309         // **** Walk down to next frame ****
7310
7311         // Is current frame managed or unmanaged?
7312         if (pMethodDescCur == NULL)
7313         {
7314             // Unmanaged frame.  Use explicit EE Frame chain to help
7315
7316             REGDISPLAY frameRD;
7317             ZeroMemory(&frameRD, sizeof(frameRD));
7318
7319             while (pFrameCur != FRAME_TOP)
7320             {
7321                 // Frame is only useful if it will contain register context info
7322                 if (!pFrameCur->NeedsUpdateRegDisplay())
7323                 {
7324                     goto Loop;
7325                 }
7326
7327
7328                 // This should be the first call we make to the Frame, as it will
7329                 // ensure we force lazy initialize of HelperMethodFrames
7330                 if (!EnsureFrameInitialized(pFrameCur))
7331                 {
7332                     return CORPROF_E_ASYNCHRONOUS_UNSAFE;
7333                 }
7334                     
7335                 // This frame is only useful if it gives us an actual return address,
7336                 // and is situated on the stack at or below our current ESP (stack
7337                 // grows up)
7338                 if ((pFrameCur->GetReturnAddress() != NULL) &&
7339                     (dac_cast<TADDR>(pFrameCur) >= dac_cast<TADDR>(ctxCur.Esp)))
7340                 {
7341                     pFrameCur->UpdateRegDisplay(&frameRD);
7342                     break;
7343                 }
7344
7345 Loop:
7346                 pFrameCur = pFrameCur->PtrNextFrame();
7347             }
7348
7349             if (pFrameCur == FRAME_TOP)
7350             {
7351                 // No more frames.  Stackwalk is over
7352                 return S_OK;
7353             }
7354
7355             // Update ctxCur based on frame
7356             ctxCur.Eip = pFrameCur->GetReturnAddress();
7357             ctxCur.Ebp = GetRegdisplayFP(&frameRD);
7358             ctxCur.Esp = GetRegdisplaySP(&frameRD);
7359         }
7360         else
7361         {
7362             // Managed frame.
7363
7364             // GC info will assist us in determining whether this is a non-EBP frame and
7365             // info about pushed arguments.
7366             GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken();
7367             PTR_VOID gcInfo = gcInfoToken.Info;
7368             InfoHdr header;
7369             unsigned uiMethodSizeDummy;
7370             PTR_CBYTE table = PTR_CBYTE(gcInfo);
7371             table += decodeUnsigned(table, &uiMethodSizeDummy);
7372             table = decodeHeader(table, gcInfoToken.Version, &header);
7373
7374             // Ok, GCInfo, can we do a simple EBP walk or what?
7375
7376             if ((codeInfo.GetRelOffset() < header.prologSize) || 
7377                 (!header.ebpFrame && !header.doubleAlign))
7378             {
7379                 // We're either in the prolog or we're not in an EBP frame, in which case
7380                 // we'll just defer to the code manager to unwind for us. This condition
7381                 // is relatively rare, but can occur if:
7382                 // 
7383                 //     * The profiler did a DSS from its Enter hook, in which case we're
7384                 //         still inside the prolog, OR
7385                 //     * The seed context or explicit EE Frame chain seeded us with a
7386                 //         non-EBP frame function. In this case, using a naive EBP
7387                 //         unwinding algorithm would actually skip over the next EBP
7388                 //         frame, and would get SP all wrong as we try skipping over
7389                 //         the pushed parameters. So let's just ask the code manager for
7390                 //         help.
7391                 // 
7392                 // Note that there are yet more conditions (much more rare) where the EBP
7393                 // walk could get lost (e.g., we're inside an epilog). But we only care
7394                 // about the most likely cases, and it's ok if the unlikely cases result
7395                 // in truncated stacks, as unlikely cases will be statistically
7396                 // irrelevant to CPU performance sampling profilers
7397                 CodeManState codeManState;
7398                 codeManState.dwIsSet = 0;
7399                 REGDISPLAY rd;
7400                 ZeroMemory(&rd, sizeof(rd));
7401
7402                 rd.SetEbpLocation(&ctxCur.Ebp);
7403                 rd.SP = ctxCur.Esp;
7404                 rd.ControlPC = ctxCur.Eip;
7405
7406                 codeInfo.GetCodeManager()->UnwindStackFrame(
7407                     &rd, 
7408                     &codeInfo, 
7409                     SpeculativeStackwalk, 
7410                     &codeManState, 
7411                     NULL);
7412
7413                 ctxCur.Ebp = *rd.GetEbpLocation();
7414                 ctxCur.Esp = rd.SP;
7415                 ctxCur.Eip = rd.ControlPC;
7416             }
7417             else
7418             {
7419                 // We're in an actual EBP frame, so we can simplistically walk down to
7420                 // the next frame using EBP.
7421                 
7422                 // Return address is stored just below saved EBP (stack grows up)
7423                 ctxCur.Eip = *(DWORD *) (ctxCur.Ebp + sizeof(DWORD));
7424                 
7425                 ctxCur.Esp = 
7426                     // Stack location where current function pushed its EBP
7427                     ctxCur.Ebp +
7428
7429                     // Skip past that EBP
7430                     sizeof(DWORD) +
7431                     
7432                     // Skip past return address pushed by caller
7433                     sizeof(DWORD) + 
7434                     
7435                     // Skip past arguments to current function that were pushed by caller. 
7436                     // (Caller will pop varargs, so don't count those.)
7437                     (header.varargs ? 0 : (header.argCount * sizeof(DWORD)));
7438
7439                 // EBP for frame below us (stack grows up) has been saved onto our own
7440                 // frame. Dereference it now.
7441                 ctxCur.Ebp = *(DWORD *) ctxCur.Ebp;
7442             }
7443         }
7444     }
7445 }
7446 #endif // _TARGET_X86_
7447
7448 //*****************************************************************************
7449 //  The profiler stackwalk Wrapper
7450 //*****************************************************************************
7451 HRESULT ProfToEEInterfaceImpl::ProfilerStackWalkFramesWrapper(Thread * pThreadToSnapshot, PROFILER_STACK_WALK_DATA * pData, unsigned flags)
7452 {
7453     STATIC_CONTRACT_WRAPPER;
7454
7455     StackWalkAction swaRet = pThreadToSnapshot->StackWalkFrames(
7456         (PSTACKWALKFRAMESCALLBACK)ProfilerStackWalkCallback,
7457          pData,
7458          flags,
7459          NULL);
7460
7461     switch (swaRet)
7462     {
7463     default:
7464         _ASSERTE(!"Unexpected StackWalkAction returned from Thread::StackWalkFrames");
7465         return E_FAIL;
7466         
7467     case SWA_FAILED:
7468         return E_FAIL;
7469         
7470     case SWA_ABORT:
7471         return CORPROF_E_STACKSNAPSHOT_ABORTED;
7472
7473     case SWA_DONE:
7474         return S_OK;
7475     }
7476 }
7477
7478 //---------------------------------------------------------------------------------------
7479 //
7480 // DoStackSnapshot helper to call FindJitMan to determine if the specified
7481 // context is in managed code.
7482 //
7483 // Arguments:
7484 //      pCtx - Context to look at
7485 //      hostCallPreference - Describes how to acquire the reader lock--either AllowHostCalls
7486 //          or NoHostCalls (see code:HostCallPreference).
7487 //
7488 // Return Value:
7489 //      S_OK: The context is in managed code
7490 //      S_FALSE: The context is not in managed code.
7491 //      Error: Unable to determine (typically because hostCallPreference was NoHostCalls
7492 //         and the reader lock was unattainable without yielding)
7493 //
7494
7495 HRESULT IsContextInManagedCode(const CONTEXT * pCtx, HostCallPreference hostCallPreference)
7496 {
7497     WRAPPER_NO_CONTRACT;
7498     BOOL fFailedReaderLock = FALSE;
7499
7500     // if there's no Jit Manager for the IP, it's not managed code.
7501     BOOL fIsManagedCode = ExecutionManager::IsManagedCode(GetIP(pCtx), hostCallPreference, &fFailedReaderLock);
7502     if (fFailedReaderLock)
7503     {
7504         return CORPROF_E_ASYNCHRONOUS_UNSAFE;
7505     }
7506     
7507     return fIsManagedCode ? S_OK : S_FALSE;
7508 }
7509
7510 //*****************************************************************************
7511 // Perform a stack walk, calling back to callback at each managed frame.
7512 //*****************************************************************************
7513 HRESULT ProfToEEInterfaceImpl::DoStackSnapshot(ThreadID thread,
7514                                               StackSnapshotCallback *callback,
7515                                               ULONG32 infoFlags,
7516                                               void *clientData,
7517                                                BYTE * pbContext,
7518                                               ULONG32 contextSize)
7519 {
7520
7521 #if !defined(FEATURE_HIJACK)
7522
7523     // DoStackSnapshot needs Thread::Suspend/ResumeThread functionality.
7524     // On platforms w/o support for these APIs return E_NOTIMPL.
7525     return E_NOTIMPL;
7526
7527 #else // !defined(FEATURE_HIJACK)
7528
7529     CONTRACTL
7530     {
7531         // Yay!  (Note: NOTHROW is vital.  The throw at minimum allocates
7532         // the thrown object which we *must* not do.)
7533         NOTHROW;
7534
7535         // Yay!  (Note: this is called asynchronously to view the stack at arbitrary times,
7536         // so the stack is not necessarily crawlable for GC at this state!)
7537         GC_NOTRIGGER;
7538
7539         // Yay!
7540         MODE_ANY;
7541
7542         // Yay!
7543         EE_THREAD_NOT_REQUIRED;
7544
7545         // #DisableLockOnAsyncCalls
7546         // This call is allowed asynchronously, however it does take locks.  Therefore,
7547         // we will hit contract asserts if we happen to be in a CANNOT_TAKE_LOCK zone when
7548         // a hijacking profiler hijacks this thread to run DoStackSnapshot.  CANNOT_RETAKE_LOCK
7549         // is a more granular locking contract that says "I promise that if I take locks, I 
7550         // won't reenter any locks that were taken before this function was called".  
7551         DISABLED(CAN_TAKE_LOCK);
7552
7553         // Asynchronous functions can be called at arbitrary times when runtime 
7554         // is holding locks that cannot be reentered without causing deadlock.
7555         // This contract detects any attempts to reenter locks held at the time 
7556         // this function was called.  
7557         CANNOT_RETAKE_LOCK;
7558
7559         SO_NOT_MAINLINE;
7560     }
7561     CONTRACTL_END;
7562
7563     // This CONTRACT_VIOLATION is still needed because DISABLED(CAN_TAKE_LOCK) does not 
7564     // turn off contract violations.
7565     PERMANENT_CONTRACT_VIOLATION(TakesLockViolation, ReasonProfilerAsyncCannotRetakeLock);
7566
7567     LPCONTEXT pctxSeed = reinterpret_cast<LPCONTEXT> (pbContext);
7568
7569     PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
7570         (LF_CORPROF, 
7571         LL_INFO1000, 
7572         "**PROF: DoStackSnapshot 0x%p, 0x%p, 0x%08x, 0x%p, 0x%p, 0x%08x.\n", 
7573         thread, 
7574         callback, 
7575         infoFlags, 
7576         clientData, 
7577         pctxSeed, 
7578         contextSize));
7579    
7580     HRESULT hr = E_UNEXPECTED;
7581     // (hr assignment is to appease the rotor compiler; we won't actually return without explicitly setting hr again)
7582     
7583     Thread *pThreadToSnapshot = NULL;
7584     Thread * pCurrentThread = GetThreadNULLOk();
7585     BOOL fResumeThread = FALSE;
7586     INDEBUG(ULONG ulForbidTypeLoad = 0;)
7587     BOOL fResetSnapshotThreadExternalCount = FALSE;
7588     int cRefsSnapshotThread = 0;
7589     
7590     // Remember whether we've already determined the current context of the target thread
7591     // is in managed (S_OK), not in managed (S_FALSE), or unknown (error).
7592     HRESULT hrCurrentContextIsManaged = E_FAIL;
7593
7594     CONTEXT ctxCurrent;
7595     memset(&ctxCurrent, 0, sizeof(ctxCurrent));
7596
7597     REGDISPLAY rd;
7598
7599     PROFILER_STACK_WALK_DATA data;
7600
7601     if (!g_fEEStarted )
7602     {
7603         // no managed code has run and things are likely in a very bad have loaded state
7604         // this is a bad time to try to walk the stack
7605         
7606         // Returning directly as there is nothing to cleanup yet
7607         return CORPROF_E_STACKSNAPSHOT_UNSAFE;
7608     }
7609
7610     if (!CORProfilerStackSnapshotEnabled())
7611     {
7612         // Returning directly as there is nothing to cleanup yet, and can't skip gcholder ctor
7613         return CORPROF_E_INCONSISTENT_WITH_FLAGS;
7614     }
7615
7616     if (thread == NULL)
7617     {
7618         pThreadToSnapshot = pCurrentThread;
7619     }
7620     else
7621     {
7622         pThreadToSnapshot = (Thread *)thread;
7623     }
7624
7625 #ifdef _TARGET_X86_
7626     if ((infoFlags & ~(COR_PRF_SNAPSHOT_REGISTER_CONTEXT | COR_PRF_SNAPSHOT_X86_OPTIMIZED)) != 0)
7627 #else
7628     if ((infoFlags & ~(COR_PRF_SNAPSHOT_REGISTER_CONTEXT)) != 0)
7629 #endif
7630     {
7631         // Returning directly as there is nothing to cleanup yet, and can't skip gcholder ctor
7632         return E_INVALIDARG;
7633     }
7634
7635     if (!IsManagedThread(pThreadToSnapshot) || !IsGarbageCollectorFullyInitialized())
7636     {
7637         //
7638         // No managed frames, return now.
7639         //
7640         // Returning directly as there is nothing to cleanup yet, and can't skip gcholder ctor
7641         return S_OK;
7642     }
7643
7644     // We must make sure no other thread tries to hijack the thread we're about to walk
7645     // Hijacking means Thread::HijackThread, i.e. bashing return addresses which would break the stack walk
7646     Thread::HijackLockHolder hijackLockHolder(pThreadToSnapshot);
7647     if (!hijackLockHolder.Acquired())
7648     {
7649         // Returning directly as there is nothing to cleanup yet, and can't skip gcholder ctor
7650         return CORPROF_E_STACKSNAPSHOT_UNSAFE;
7651     }
7652
7653     if (pThreadToSnapshot != pCurrentThread         // Walking separate thread
7654         && pCurrentThread != NULL                         // Walker (current) thread is a managed / VM thread
7655         && ThreadSuspend::SysIsSuspendInProgress())          // EE is trying suspend itself
7656     {
7657         // Since we're walking a separate thread, we'd have to suspend it first (see below).
7658         // And since the current thread is a VM thread, that means the current thread's
7659         // m_dwForbidSuspendThread count will go up while it's trying to suspend the
7660         // target thread (see Thread::SuspendThread).  THAT means no one will be able
7661         // to suspend the current thread until its m_dwForbidSuspendThread is decremented
7662         // (which happens as soon as the target thread of DoStackSnapshot has been suspended).
7663         // Since we're in the process of suspending the entire runtime, now would be a bad time to
7664         // make the walker thread un-suspendable (see VsWhidbey bug 454936).  So let's just abort
7665         // now.  Note that there is no synchronization around calling Thread::SysIsSuspendInProgress().
7666         // So we will get occasional false positives or false negatives.  But that's benign, as the worst
7667         // that might happen is we might occasionally delay the EE suspension a little bit, or we might
7668         // too eagerly fail from ProfToEEInterfaceImpl::DoStackSnapshot sometimes.  But there won't
7669         // be any corruption or AV.  
7670         //
7671         // Returning directly as there is nothing to cleanup yet, and can't skip gcholder ctor
7672         return CORPROF_E_STACKSNAPSHOT_UNSAFE;
7673     }
7674
7675     // We only allow stackwalking if:
7676     // 1) Target thread to walk == current thread OR Target thread is suspended, AND
7677     // 2) Target thread to walk is currently executing JITted / NGENd code, AND
7678     // 3) Target thread to walk is seeded OR currently NOT unwinding the stack, AND
7679     // 4) Target thread to walk != current thread OR current thread is NOT in a can't stop or forbid suspend region
7680
7681     // If the thread is in a forbid suspend region, it's dangerous to do anything:
7682     // - The code manager datastructures accessed during the stackwalk may be in inconsistent state.
7683     // - Thread::Suspend won't be able to suspend the thread.
7684     if (pThreadToSnapshot->IsInForbidSuspendRegion())
7685     {
7686         hr = CORPROF_E_STACKSNAPSHOT_UNSAFE;
7687         goto Cleanup;
7688     }
7689
7690     HostCallPreference hostCallPreference;
7691     
7692     // First, check "1) Target thread to walk == current thread OR Target thread is suspended"
7693     if (pThreadToSnapshot != pCurrentThread)
7694     {
7695 #ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7696         hr = E_NOTIMPL;
7697         goto Cleanup;
7698 #else
7699         // Walking separate thread, so it must be suspended.  First, ensure that
7700         // target thread exists.
7701         //
7702         // NOTE: We're using the "dangerous" variant of this refcount function, because we
7703         // rely on the profiler to ensure it never tries to walk a thread being destroyed.
7704         // (Profiler must block in its ThreadDestroyed() callback until all uses of that thread,
7705         // such as walking its stack, are complete.)
7706         cRefsSnapshotThread = pThreadToSnapshot->IncExternalCountDANGEROUSProfilerOnly();
7707         fResetSnapshotThreadExternalCount = TRUE;
7708
7709         if (cRefsSnapshotThread == 1 || !pThreadToSnapshot->HasValidThreadHandle())
7710         {
7711             // At this point, we've modified the VM state based on bad input
7712             // (pThreadToSnapshot) from the profiler.  This could cause
7713             // memory corruption and leave us vulnerable to security problems.
7714             // So destroy the process.
7715             _ASSERTE(!"Profiler trying to walk destroyed thread");
7716             EEPOLICY_HANDLE_FATAL_ERROR(CORPROF_E_STACKSNAPSHOT_INVALID_TGT_THREAD);
7717         }
7718
7719         // Thread::SuspendThread() ensures that no one else should try to suspend us
7720         // while we're suspending pThreadToSnapshot.
7721         //
7722         // TRUE: OneTryOnly.  Don't loop waiting for others to get out of our way in
7723         // order to suspend the thread.  If it's not safe, just return an error immediately.
7724         Thread::SuspendThreadResult str = pThreadToSnapshot->SuspendThread(TRUE);
7725         if (str == Thread::STR_Success)
7726         {
7727             fResumeThread = TRUE;
7728         }
7729         else
7730         {
7731             hr = CORPROF_E_STACKSNAPSHOT_UNSAFE;
7732             goto Cleanup;            
7733         }
7734 #endif // !PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7735     }
7736
7737     hostCallPreference =
7738         ShouldAvoidHostCalls() ?
7739             NoHostCalls :       // Async call: Ensure this thread won't yield & re-enter host
7740             AllowHostCalls;     // Synchronous calls may re-enter host just fine
7741
7742     // If target thread is in pre-emptive mode, the profiler's seed context is unnecessary
7743     // because our frame chain is good enough: it will give us at least as accurate a
7744     // starting point as the profiler could.  Also, since profiler contexts cannot be
7745     // trusted, we don't want to set the thread's profiler filter context to this, as a GC
7746     // that interrupts the profiler's stackwalk will end up using the profiler's (potentially
7747     // bogus) filter context.
7748     if (!pThreadToSnapshot->PreemptiveGCDisabledOther())
7749     {
7750         // Thread to be walked is in preemptive mode.  Throw out seed.
7751         pctxSeed = NULL;
7752     }
7753     else if (pThreadToSnapshot != pCurrentThread)
7754     {
7755     // With cross-thread stack-walks, the target thread's context could be unreliable.
7756     // That would shed doubt on either a profiler-provided context, or a default
7757     // context we chose.  So check if we're in a potentially unreliable case, and return
7758     // an error if so.
7759     // 
7760     // These heurisitics are based on an actual bug where GetThreadContext returned a
7761     // self-consistent, but stale, context for a thread suspended after being redirected by
7762     // the GC (TFS Dev 10 bug # 733263).
7763         //
7764         // (Note that this whole block is skipped if pThreadToSnapshot is in preemptive mode (the IF
7765         // above), as the context is unused in such a case--the EE Frame chain is used
7766         // to seed the walk instead.)
7767 #ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7768         hr = E_NOTIMPL;
7769         goto Cleanup;
7770 #else
7771         if (!pThreadToSnapshot->GetSafelyRedirectableThreadContext(Thread::kDefaultChecks, &ctxCurrent, &rd))
7772         {
7773             LOG((LF_CORPROF, LL_INFO100, "**PROF: GetSafelyRedirectableThreadContext failure leads to CORPROF_E_STACKSNAPSHOT_UNSAFE.\n"));
7774             hr = CORPROF_E_STACKSNAPSHOT_UNSAFE;
7775             goto Cleanup;
7776         }
7777
7778         hrCurrentContextIsManaged = IsContextInManagedCode(&ctxCurrent, hostCallPreference);
7779         if (FAILED(hrCurrentContextIsManaged))
7780         {
7781             // Couldn't get the info.  Try again later
7782             _ASSERTE(ShouldAvoidHostCalls());
7783             hr = CORPROF_E_ASYNCHRONOUS_UNSAFE;
7784             goto Cleanup;
7785         }
7786
7787         if ((hrCurrentContextIsManaged == S_OK) &&
7788             (!pThreadToSnapshot->PreemptiveGCDisabledOther()))
7789         {
7790             // Thread is in preemptive mode while executing managed code?!  This lie is
7791             // an early warning sign that the context is bogus.  Bail.
7792             LOG((LF_CORPROF, LL_INFO100, "**PROF: Target thread context is likely bogus.  Returning CORPROF_E_STACKSNAPSHOT_UNSAFE.\n"));
7793             hr = CORPROF_E_STACKSNAPSHOT_UNSAFE;
7794             goto Cleanup;
7795         }
7796
7797         Frame * pFrame = pThreadToSnapshot->GetFrame();
7798         if (pFrame != FRAME_TOP)
7799         {
7800             TADDR spTargetThread = GetSP(&ctxCurrent);
7801             if (dac_cast<TADDR>(pFrame) < spTargetThread)
7802             {
7803                 // An Explicit EE Frame is more recent on the stack than the current
7804                 // stack pointer itself?  This lie is an early warning sign that the
7805                 // context is bogus. Bail.
7806                 LOG((LF_CORPROF, LL_INFO100, "**PROF: Target thread context is likely bogus.  Returning CORPROF_E_STACKSNAPSHOT_UNSAFE.\n"));
7807                 hr = CORPROF_E_STACKSNAPSHOT_UNSAFE;
7808                 goto Cleanup;
7809             }
7810         }
7811
7812         // If the profiler did not specify a seed context of its own, use the current one we
7813         // just produced.
7814         //            
7815         // Failing to seed the walk can cause us to to "miss" functions on the stack.  This is
7816         // because StackWalkFrames(), when doing an unseeded stackwalk, sets the
7817         // starting regdisplay's IP/SP to 0.  This, in turn causes StackWalkFramesEx
7818         // to set cf.isFrameless = (pEEJM != NULL); (which is FALSE, since we have no
7819         // jit manager, since we have no IP).  Once frameless is false, we look solely to
7820         // the Frame chain for our goodies, rather than looking at the code actually
7821         // being executed by the thread.  The problem with the frame chain is that some
7822         // frames (e.g., GCFrame) don't point to any functions being executed.  So
7823         // StackWalkFramesEx just skips such frames and moves to the next one.  That
7824         // can cause a chunk of calls to be skipped.  To prevent this from happening, we
7825         // "fake" a seed by just seeding the thread with its current context.  This forces
7826         // StackWalkFramesEx() to look at the IP rather than just the frame chain.
7827         if (pctxSeed == NULL)
7828         {
7829             pctxSeed = &ctxCurrent;
7830         }
7831 #endif // !PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7832     }
7833
7834     // Second, check "2) Target thread to walk is currently executing JITted / NGENd code"
7835     // To do this, we need to find the proper context to investigate.  Start with
7836     // the seeded context, if available.  If not, use the target thread's current context.
7837     if (pctxSeed != NULL)
7838     {
7839         BOOL fSeedIsManaged;
7840
7841         // Short cut: If we're just using the current context as the seed, we may
7842         // already have determined whether it's in managed code.  If so, just use that
7843         // result rather than calculating it again
7844         if ((pctxSeed == &ctxCurrent) && SUCCEEDED(hrCurrentContextIsManaged))
7845         {
7846             fSeedIsManaged = (hrCurrentContextIsManaged == S_OK);
7847         }
7848         else
7849         {
7850             hr = IsContextInManagedCode(pctxSeed, hostCallPreference);
7851             if (FAILED(hr))
7852             {
7853                 hr = CORPROF_E_ASYNCHRONOUS_UNSAFE;
7854                 goto Cleanup;
7855             }
7856             fSeedIsManaged = (hr == S_OK);
7857         }
7858
7859         if (!fSeedIsManaged)
7860         {
7861             hr = CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX;
7862             goto Cleanup;
7863         }
7864     }
7865
7866 #ifdef _DEBUG
7867     //
7868     // Sanity check: If we are doing a cross-thread walk and there is no seed context, then
7869     // we better not be in managed code, otw we do not have a Frame on the stack from which to start
7870     // walking and we may miss the leaf-most chain of managed calls due to the way StackWalkFrames 
7871     // is implemented.  However, there is an exception when the leaf-most EE frame of pThreadToSnapshot
7872     // is an InlinedCallFrame, which has an active call, implying pThreadToShanpshot is inside an 
7873     // inlined P/Invoke.  In this case, the InlinedCallFrame will be used to help start off our
7874     // stackwalk at the top of the stack.
7875     //
7876     if (pThreadToSnapshot != pCurrentThread)
7877     {
7878 #ifndef PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7879         hr = E_NOTIMPL;
7880         goto Cleanup;
7881 #else
7882         if (pctxSeed == NULL)
7883         {
7884             if (pThreadToSnapshot->GetSafelyRedirectableThreadContext(Thread::kDefaultChecks, &ctxCurrent, &rd))
7885             {
7886                 BOOL fFailedReaderLock = FALSE;
7887                 BOOL fIsManagedCode = ExecutionManager::IsManagedCode(GetIP(&ctxCurrent), hostCallPreference, &fFailedReaderLock);
7888
7889                 if (!fFailedReaderLock)
7890                 {
7891                     // not in jitted or ngend code or inside an inlined P/Invoke (the leaf-most EE Frame is
7892                     // an InlinedCallFrame with an active call)
7893                     _ASSERTE(!fIsManagedCode ||
7894                              (InlinedCallFrame::FrameHasActiveCall(pThreadToSnapshot->GetFrame())));
7895                 }
7896             }
7897         }
7898 #endif // !PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7899     }
7900 #endif //_DEBUG
7901     // Third, verify the target thread is seeded or not in the midst of an unwind.
7902     if (pctxSeed == NULL)
7903     {
7904         ThreadExceptionState* pExState = pThreadToSnapshot->GetExceptionState();
7905
7906         // this tests to see if there is an exception in flight
7907         if (pExState->IsExceptionInProgress() && pExState->GetFlags()->UnwindHasStarted())
7908         {
7909             EHClauseInfo *pCurrentEHClauseInfo = pThreadToSnapshot->GetExceptionState()->GetCurrentEHClauseInfo();
7910
7911             // if the exception code is telling us that we have entered a managed context then all is well
7912             if (!pCurrentEHClauseInfo->IsManagedCodeEntered())
7913             {
7914                 hr = CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX;
7915                 goto Cleanup;
7916             }
7917         }
7918     }
7919
7920     // Check if the exception state is consistent.  See the comment for ThreadExceptionFlag for more information. 
7921     if (pThreadToSnapshot->GetExceptionState()->HasThreadExceptionFlag(ThreadExceptionState::TEF_InconsistentExceptionState))
7922     {
7923         hr = CORPROF_E_STACKSNAPSHOT_UNSAFE;
7924         goto Cleanup;
7925     }
7926
7927     data.callback = callback;
7928     data.infoFlags = infoFlags;
7929     data.contextFlags = 0;
7930     data.clientData = clientData;
7931 #ifdef WIN64EXCEPTIONS
7932     data.sfParent.Clear();
7933 #endif
7934
7935     // workaround: The ForbidTypeLoad book keeping in the stackwalker is not robust against exceptions.
7936     // Unfortunately, it is hard to get it right in the stackwalker since it has to be exception 
7937     // handling free (frame unwinding may never return). We restore the ForbidTypeLoad counter here
7938     // in case it got messed up by exception thrown during the stackwalk.
7939     INDEBUG(if (pCurrentThread) ulForbidTypeLoad = pCurrentThread->m_ulForbidTypeLoad;)
7940
7941     {
7942         // An AV during a profiler stackwalk is an isolated event and shouldn't bring
7943         // down the runtime.  Need to place the holder here, outside of ProfilerStackWalkFramesWrapper
7944         // since ProfilerStackWalkFramesWrapper uses __try, which doesn't like objects
7945         // with destructors.
7946         AVInRuntimeImplOkayHolder AVOkay;
7947
7948         hr = DoStackSnapshotHelper(
7949                  pThreadToSnapshot, 
7950                  &data, 
7951                  HANDLESKIPPEDFRAMES |
7952                      FUNCTIONSONLY |
7953                      NOTIFY_ON_U2M_TRANSITIONS |
7954                      ((pThreadToSnapshot == pCurrentThread) ?
7955                          0 : 
7956                          ALLOW_ASYNC_STACK_WALK | THREAD_IS_SUSPENDED) |
7957                      THREAD_EXECUTING_MANAGED_CODE |
7958                      PROFILER_DO_STACK_SNAPSHOT |
7959                      ALLOW_INVALID_OBJECTS, // stack walk logic should not look at objects - we could be in the middle of a gc.
7960                  pctxSeed);
7961     }
7962
7963     INDEBUG(if (pCurrentThread) pCurrentThread->m_ulForbidTypeLoad = ulForbidTypeLoad;)
7964
7965 Cleanup:
7966 #if defined(PLATFORM_SUPPORTS_SAFE_THREADSUSPEND)
7967     if (fResumeThread)
7968     {
7969         pThreadToSnapshot->ResumeThread();
7970     }
7971 #endif // PLATFORM_SUPPORTS_SAFE_THREADSUSPEND
7972     if (fResetSnapshotThreadExternalCount)
7973     {
7974         pThreadToSnapshot->DecExternalCountDANGEROUSProfilerOnly();
7975     }
7976
7977     return hr;
7978
7979 #endif // !defined(FEATURE_HIJACK)
7980 }
7981
7982
7983 //---------------------------------------------------------------------------------------
7984 //
7985 // Exception swallowing wrapper around the profiler stackwalk
7986 //
7987 // Arguments:
7988 //      pThreadToSnapshot - Thread whose stack should be walked
7989 //      pData - data for stack walker
7990 //      flags - flags parameter to pass to StackWalkFramesEx, and StackFrameIterator 
7991 //      pctxSeed - Register context with which to seed the walk
7992 //
7993 // Return Value:
7994 //     HRESULT indicating success or failure.
7995 //
7996 HRESULT ProfToEEInterfaceImpl::DoStackSnapshotHelper(Thread * pThreadToSnapshot,
7997                                                      PROFILER_STACK_WALK_DATA * pData,
7998                                                      unsigned flags,
7999                                                      LPCONTEXT pctxSeed)
8000 {
8001     STATIC_CONTRACT_NOTHROW;
8002
8003     // We want to catch and swallow AVs here. For example, if the profiler gives 
8004     // us a bogus seed context (this happens), we could AV when inspecting memory pointed to 
8005     // by the (bogus) EBP register.
8006     //
8007     // EX_TRY/EX_CATCH does a lot of extras that we do not need and that can go wrong for us. 
8008     // E.g. It asserts in debug build for AVs in mscorwks or it synthetizes an object for the exception.
8009     // We use a plain PAL_TRY/PAL_EXCEPT since it is all we need.
8010     struct Param {
8011         HRESULT                     hr;
8012         Thread *                    pThreadToSnapshot;
8013         PROFILER_STACK_WALK_DATA *  pData;
8014         unsigned                    flags;
8015         ProfToEEInterfaceImpl *     pProfToEE;
8016         LPCONTEXT                   pctxSeed;
8017         BOOL                        fResetProfilerFilterContext;
8018     };
8019
8020     Param param;
8021     param.hr = E_UNEXPECTED;
8022     param.pThreadToSnapshot = pThreadToSnapshot;
8023     param.pData = pData;
8024     param.flags = flags; 
8025     param.pProfToEE = this;
8026     param.pctxSeed = pctxSeed;
8027     param.fResetProfilerFilterContext = FALSE;
8028
8029     PAL_TRY(Param *, pParam, &param)
8030     {
8031         if ((pParam->pData->infoFlags & COR_PRF_SNAPSHOT_X86_OPTIMIZED) != 0)
8032         {
8033 #ifndef _TARGET_X86_
8034             // If check in the begining of DoStackSnapshot (to return E_INVALIDARG) should 
8035             // make this unreachable
8036             _ASSERTE(!"COR_PRF_SNAPSHOT_X86_OPTIMIZED on non-X86 should be unreachable!");
8037 #else
8038             // New, simple EBP walker
8039             pParam->hr = pParam->pProfToEE->ProfilerEbpWalker(
8040                              pParam->pThreadToSnapshot,
8041                              pParam->pctxSeed,
8042                              pParam->pData->callback,
8043                              pParam->pData->clientData);
8044 #endif  // _TARGET_X86_
8045         }
8046         else
8047         {
8048             // We're now fairly confident the stackwalk should be ok, so set
8049             // the context seed, if one was provided or cooked up.
8050             if (pParam->pctxSeed != NULL)
8051             {
8052                 pParam->pThreadToSnapshot->SetProfilerFilterContext(pParam->pctxSeed);
8053                 pParam->fResetProfilerFilterContext = TRUE;
8054             }
8055
8056             // Whidbey-style walker, uses StackWalkFramesEx
8057             pParam->hr = pParam->pProfToEE->ProfilerStackWalkFramesWrapper(
8058                              pParam->pThreadToSnapshot,
8059                              pParam->pData,
8060                              pParam->flags);
8061         }
8062     }
8063     PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
8064     {
8065         param.hr = E_UNEXPECTED;
8066     }
8067     PAL_ENDTRY;
8068
8069     // Undo the context seeding & thread suspend we did (if any)
8070     // to ensure that the thread we walked stayed suspended
8071     if (param.fResetProfilerFilterContext)
8072     {
8073         pThreadToSnapshot->SetProfilerFilterContext(NULL);
8074     }
8075
8076     return param.hr;
8077 }
8078
8079
8080 HRESULT ProfToEEInterfaceImpl::GetGenerationBounds(ULONG cObjectRanges,
8081                                                    ULONG *pcObjectRanges,
8082                                                    COR_PRF_GC_GENERATION_RANGE ranges[])
8083 {
8084     CONTRACTL
8085     {
8086         // Yay!
8087         NOTHROW;
8088
8089         // Yay!
8090         GC_NOTRIGGER;
8091
8092         // Yay!
8093         MODE_ANY;
8094
8095         // Yay!
8096         EE_THREAD_NOT_REQUIRED;
8097
8098         // Yay!
8099         CANNOT_TAKE_LOCK;
8100
8101         SO_NOT_MAINLINE;
8102
8103         PRECONDITION(CheckPointer(pcObjectRanges));
8104         PRECONDITION(cObjectRanges <= 0 || ranges != NULL);
8105         PRECONDITION(s_generationTableLock >= 0);
8106     }
8107     CONTRACTL_END;
8108
8109     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
8110         (LF_CORPROF, 
8111         LL_INFO1000, 
8112         "**PROF: GetGenerationBounds.\n"));
8113     
8114     // Announce we are using the generation table now
8115     CounterHolder genTableLock(&s_generationTableLock);
8116
8117     GenerationTable *generationTable = s_currentGenerationTable;
8118
8119     if (generationTable == NULL)
8120     {
8121         return E_FAIL;
8122     }
8123
8124     _ASSERTE(generationTable->magic == GENERATION_TABLE_MAGIC);
8125
8126     GenerationDesc *genDescTable = generationTable->genDescTable;
8127     ULONG count = min(generationTable->count, cObjectRanges);
8128     for (ULONG i = 0; i < count; i++)
8129     {
8130         ranges[i].generation          = (COR_PRF_GC_GENERATION)genDescTable[i].generation;
8131         ranges[i].rangeStart          = (ObjectID)genDescTable[i].rangeStart;
8132         ranges[i].rangeLength         = genDescTable[i].rangeEnd         - genDescTable[i].rangeStart;
8133         ranges[i].rangeLengthReserved = genDescTable[i].rangeEndReserved - genDescTable[i].rangeStart;
8134     }
8135
8136     *pcObjectRanges = generationTable->count;
8137
8138     return S_OK;
8139 }
8140
8141
8142 HRESULT ProfToEEInterfaceImpl::GetNotifiedExceptionClauseInfo(COR_PRF_EX_CLAUSE_INFO * pinfo)
8143 {
8144     CONTRACTL
8145     {
8146         // Yay!
8147         NOTHROW;
8148
8149         // Yay!
8150         GC_NOTRIGGER;
8151
8152         // Yay!
8153         MODE_ANY;
8154
8155         // Yay!
8156         CANNOT_TAKE_LOCK;
8157
8158         SO_NOT_MAINLINE;
8159
8160         PRECONDITION(CheckPointer(pinfo));
8161     }
8162     CONTRACTL_END;
8163
8164     PROFILER_TO_CLR_ENTRYPOINT_SYNC((LF_CORPROF, 
8165                                      LL_INFO1000, 
8166                                      "**PROF: GetNotifiedExceptionClauseInfo.\n"));    
8167     
8168     HRESULT hr = S_OK;
8169
8170     ThreadExceptionState* pExState             = NULL;
8171     EHClauseInfo*         pCurrentEHClauseInfo = NULL;
8172
8173     // notification requires that we are on a managed thread with an exception in flight
8174     Thread *pThread = GetThread();
8175
8176     // If pThread is null, then the thread has never run managed code 
8177     if (pThread == NULL)
8178     {
8179         hr = CORPROF_E_NOT_MANAGED_THREAD;
8180         goto NullReturn;
8181     }
8182
8183     pExState = pThread->GetExceptionState();
8184     if (!pExState->IsExceptionInProgress())
8185     {
8186         // no exception is in flight -- successful failure
8187         hr = S_FALSE;
8188         goto NullReturn;
8189     }
8190
8191     pCurrentEHClauseInfo = pExState->GetCurrentEHClauseInfo();
8192     if (pCurrentEHClauseInfo->GetClauseType() == COR_PRF_CLAUSE_NONE)
8193     {
8194         // no exception is in flight -- successful failure
8195         hr = S_FALSE;
8196         goto NullReturn;
8197     }
8198
8199     pinfo->clauseType     = pCurrentEHClauseInfo->GetClauseType();
8200     pinfo->programCounter = pCurrentEHClauseInfo->GetIPForEHClause();
8201     pinfo->framePointer   = pCurrentEHClauseInfo->GetFramePointerForEHClause();
8202     pinfo->shadowStackPointer = 0;
8203
8204     return S_OK;
8205
8206 NullReturn:
8207     memset(pinfo, 0, sizeof(*pinfo));
8208     return hr;
8209 }
8210
8211
8212 HRESULT ProfToEEInterfaceImpl::GetObjectGeneration(ObjectID objectId,
8213                                                    COR_PRF_GC_GENERATION_RANGE *range)
8214 {
8215     CONTRACTL
8216     {
8217         // Yay!
8218         NOTHROW;
8219
8220         // Yay!
8221         GC_NOTRIGGER;
8222
8223         // Yay!
8224         MODE_ANY;
8225
8226         // Yay!
8227         EE_THREAD_NOT_REQUIRED;
8228
8229         // Yay!
8230         CANNOT_TAKE_LOCK;
8231
8232         SO_NOT_MAINLINE;
8233
8234         PRECONDITION(objectId != NULL);
8235         PRECONDITION(CheckPointer(range));
8236         PRECONDITION(s_generationTableLock >= 0);
8237     }
8238     CONTRACTL_END;
8239
8240     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
8241                                        (LF_CORPROF, 
8242                                        LL_INFO1000, 
8243                                        "**PROF: GetObjectGeneration 0x%p.\n",
8244                                        objectId));        
8245
8246     BEGIN_GETTHREAD_ALLOWED;
8247     _ASSERTE((GetThread() == NULL) || (GetThread()->PreemptiveGCDisabled()));
8248     END_GETTHREAD_ALLOWED;
8249     
8250     // Announce we are using the generation table now
8251     CounterHolder genTableLock(&s_generationTableLock);
8252
8253     GenerationTable *generationTable = s_currentGenerationTable;
8254
8255     if (generationTable == NULL)
8256     {
8257         return E_FAIL;
8258     }
8259
8260     _ASSERTE(generationTable->magic == GENERATION_TABLE_MAGIC);
8261
8262     GenerationDesc *genDescTable = generationTable->genDescTable;
8263     ULONG count = generationTable->count;
8264     for (ULONG i = 0; i < count; i++)
8265     {
8266         if (genDescTable[i].rangeStart <= (BYTE *)objectId && (BYTE *)objectId < genDescTable[i].rangeEndReserved)
8267         {
8268             range->generation          = (COR_PRF_GC_GENERATION)genDescTable[i].generation;
8269             range->rangeStart          = (ObjectID)genDescTable[i].rangeStart;
8270             range->rangeLength         = genDescTable[i].rangeEnd         - genDescTable[i].rangeStart;
8271             range->rangeLengthReserved = genDescTable[i].rangeEndReserved - genDescTable[i].rangeStart;
8272
8273             return S_OK;
8274         }
8275     }
8276
8277     return E_FAIL;
8278 }
8279
8280 HRESULT ProfToEEInterfaceImpl::GetReJITIDs(
8281                            FunctionID          functionId,  // in
8282                            ULONG               cReJitIds,   // in
8283                            ULONG *             pcReJitIds,  // out
8284                            ReJITID             reJitIds[])  // out
8285 {
8286     CONTRACTL
8287     {
8288         // Yay!
8289         NOTHROW;
8290
8291         // taking a lock causes a GC
8292         GC_TRIGGERS;
8293
8294         // Yay!
8295         MODE_ANY;
8296
8297         // The rejit tables use a lock
8298         CAN_TAKE_LOCK;
8299
8300         SO_NOT_MAINLINE;
8301
8302         PRECONDITION(CheckPointer(pcReJitIds, NULL_OK));
8303         PRECONDITION(CheckPointer(reJitIds, NULL_OK));
8304
8305     }
8306     CONTRACTL_END;
8307
8308     PROFILER_TO_CLR_ENTRYPOINT_SYNC((LF_CORPROF, 
8309                                     LL_INFO1000, 
8310                                     "**PROF: GetReJITIDs 0x%p.\n", 
8311                                      functionId));     
8312
8313     if (functionId == 0)
8314     {
8315         return E_INVALIDARG;
8316     }
8317
8318     if ((cReJitIds == 0) || (pcReJitIds == NULL) || (reJitIds == NULL))
8319     {
8320         return E_INVALIDARG;
8321     }
8322
8323     MethodDesc * pMD = FunctionIdToMethodDesc(functionId);
8324
8325     return pMD->GetReJitManager()->GetReJITIDs(pMD, cReJitIds, pcReJitIds, reJitIds);
8326 }
8327
8328 HRESULT ProfToEEInterfaceImpl::RequestReJIT(ULONG       cFunctions,   // in
8329                                             ModuleID    moduleIds[],  // in
8330                                             mdMethodDef methodIds[])  // in
8331 {
8332     CONTRACTL
8333     {
8334         // Yay!
8335         NOTHROW;
8336
8337         // When we suspend the runtime we drop into premptive mode
8338         GC_TRIGGERS;
8339
8340         // Yay!
8341         MODE_ANY;
8342
8343         // We need to suspend the runtime, this takes a lot of locks!
8344         CAN_TAKE_LOCK;
8345
8346         SO_NOT_MAINLINE;
8347
8348         PRECONDITION(CheckPointer(moduleIds, NULL_OK));
8349         PRECONDITION(CheckPointer(methodIds, NULL_OK));
8350     }
8351     CONTRACTL_END;
8352
8353     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
8354         kP2EETriggers,
8355         (LF_CORPROF, 
8356          LL_INFO1000, 
8357          "**PROF: RequestReJIT.\n"));
8358
8359     if (!g_profControlBlock.pProfInterface->IsCallback4Supported())
8360     {
8361         return CORPROF_E_CALLBACK4_REQUIRED;
8362     }
8363
8364     if (!CORProfilerEnableRejit())
8365     {
8366         return CORPROF_E_REJIT_NOT_ENABLED;
8367     }
8368
8369     // Request at least 1 method to reJIT!
8370     if ((cFunctions == 0) || (moduleIds == NULL) || (methodIds == NULL))
8371     {
8372         return E_INVALIDARG;
8373     }
8374
8375     // Remember the profiler is doing this, as that means we must never detach it!
8376     g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
8377     
8378     GCX_PREEMP();
8379     return ReJitManager::RequestReJIT(cFunctions, moduleIds, methodIds);
8380 }
8381
8382 HRESULT ProfToEEInterfaceImpl::RequestRevert(ULONG       cFunctions,  // in
8383                                              ModuleID    moduleIds[], // in
8384                                              mdMethodDef methodIds[], // in
8385                                              HRESULT     rgHrStatuses[])    // out
8386 {
8387     CONTRACTL
8388     {
8389         // Yay!
8390         NOTHROW;
8391
8392         // The rejit manager requires a lock to iterate through methods to revert, and
8393         // taking the lock can drop us into preemptive mode.
8394         GC_TRIGGERS;
8395
8396         // Yay!
8397         MODE_ANY;
8398
8399         // The rejit manager requires a lock to iterate through methods to revert
8400         CAN_TAKE_LOCK;
8401
8402         SO_NOT_MAINLINE;
8403
8404         PRECONDITION(CheckPointer(moduleIds, NULL_OK));
8405         PRECONDITION(CheckPointer(methodIds, NULL_OK));
8406         PRECONDITION(CheckPointer(rgHrStatuses, NULL_OK));
8407     }
8408     CONTRACTL_END;
8409
8410     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
8411         kP2EETriggers,
8412         (LF_CORPROF, 
8413          LL_INFO1000, 
8414          "**PROF: RequestRevert.\n"));
8415
8416     if (!CORProfilerEnableRejit())
8417     {
8418         return CORPROF_E_REJIT_NOT_ENABLED;
8419     }
8420
8421     // Request at least 1 method to revert!
8422     if ((cFunctions == 0) || (moduleIds == NULL) || (methodIds == NULL))
8423     {
8424         return E_INVALIDARG;
8425     }
8426
8427     // Remember the profiler is doing this, as that means we must never detach it!
8428     g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
8429
8430     // Initialize the status array
8431     if (rgHrStatuses != NULL)
8432     {
8433         memset(rgHrStatuses, 0, sizeof(HRESULT) * cFunctions);
8434         _ASSERTE(S_OK == rgHrStatuses[0]);
8435     }
8436
8437     GCX_PREEMP();
8438     return ReJitManager::RequestRevert(cFunctions, moduleIds, methodIds, rgHrStatuses);
8439 }
8440
8441
8442 HRESULT ProfToEEInterfaceImpl::EnumJITedFunctions(ICorProfilerFunctionEnum ** ppEnum)
8443 {
8444     CONTRACTL
8445     {
8446         // Yay!
8447         NOTHROW;
8448
8449         // Yay!
8450         GC_NOTRIGGER;
8451
8452         // Yay!
8453         MODE_ANY;
8454
8455         // If we're in preemptive mode we need to take a read lock to safely walk
8456         // the JIT data structures.
8457         CAN_TAKE_LOCK;
8458
8459         SO_NOT_MAINLINE;
8460
8461         PRECONDITION(CheckPointer(ppEnum, NULL_OK));
8462
8463     }
8464     CONTRACTL_END;
8465
8466     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
8467         (LF_CORPROF, 
8468         LL_INFO10, 
8469         "**PROF: EnumJITedFunctions.\n"));
8470
8471     if (ppEnum == NULL)
8472     {
8473         return E_INVALIDARG;
8474     }
8475
8476     *ppEnum = NULL;
8477
8478     NewHolder<ProfilerFunctionEnum> pJitEnum(new (nothrow) ProfilerFunctionEnum());
8479     if (pJitEnum == NULL)
8480     {
8481         return E_OUTOFMEMORY;
8482     }
8483
8484     if (!pJitEnum->Init())
8485     {
8486         return E_OUTOFMEMORY;
8487     }
8488
8489     // Ownership transferred to [out] param.  Caller must Release() when done with this.
8490     *ppEnum = (ICorProfilerFunctionEnum *)pJitEnum.Extract();
8491
8492     return S_OK;
8493 }
8494
8495 HRESULT ProfToEEInterfaceImpl::EnumJITedFunctions2(ICorProfilerFunctionEnum ** ppEnum)
8496 {
8497     CONTRACTL
8498     {
8499         // Yay!
8500         NOTHROW;
8501
8502         // Gathering rejitids requires taking a lock and that lock might switch to
8503         // preemptimve mode... 
8504         GC_TRIGGERS;
8505
8506         // Yay!
8507         MODE_ANY;
8508
8509         // If we're in preemptive mode we need to take a read lock to safely walk
8510         // the JIT data structures.
8511         // Gathering RejitIDs also takes a lock.
8512         CAN_TAKE_LOCK;
8513
8514         SO_NOT_MAINLINE;
8515
8516         PRECONDITION(CheckPointer(ppEnum, NULL_OK));
8517
8518     }
8519     CONTRACTL_END;
8520
8521     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
8522         kP2EEAllowableAfterAttach | kP2EETriggers,
8523         (LF_CORPROF, 
8524         LL_INFO10, 
8525         "**PROF: EnumJITedFunctions.\n"));
8526
8527     if (ppEnum == NULL)
8528     {
8529         return E_INVALIDARG;
8530     }
8531
8532     *ppEnum = NULL;
8533
8534     NewHolder<ProfilerFunctionEnum> pJitEnum(new (nothrow) ProfilerFunctionEnum());
8535     if (pJitEnum == NULL)
8536     {
8537         return E_OUTOFMEMORY;
8538     }
8539
8540     if (!pJitEnum->Init(TRUE /* fWithReJITIDs */))
8541     {
8542         // If it fails, it's because of OOM.
8543         return E_OUTOFMEMORY;
8544     }
8545
8546     // Ownership transferred to [out] param.  Caller must Release() when done with this.
8547     *ppEnum = (ICorProfilerFunctionEnum *)pJitEnum.Extract();
8548
8549     return S_OK;
8550 }
8551
8552 HRESULT ProfToEEInterfaceImpl::EnumModules(ICorProfilerModuleEnum ** ppEnum)
8553 {
8554     CONTRACTL
8555     {
8556         // Yay!
8557         NOTHROW;
8558
8559         // This method populates the enumerator, which requires iterating over
8560         // AppDomains, which adds, then releases, a reference on each AppDomain iterated.
8561         // This causes locking, and can cause triggering if the AppDomain gets destroyed
8562         // as a result of the release. (See code:AppDomainIterator::Next and its call to
8563         // code:AppDomain::Release.)
8564         GC_TRIGGERS;
8565
8566         // Yay!
8567         MODE_ANY;
8568
8569         // (See comment above GC_TRIGGERS.)
8570         CAN_TAKE_LOCK;
8571
8572         SO_NOT_MAINLINE;
8573
8574         PRECONDITION(CheckPointer(ppEnum, NULL_OK));
8575
8576     }
8577     CONTRACTL_END;
8578
8579     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
8580         kP2EEAllowableAfterAttach | kP2EETriggers,
8581         (LF_CORPROF, 
8582         LL_INFO10, 
8583         "**PROF: EnumModules.\n"));
8584
8585     HRESULT hr;
8586
8587     if (ppEnum == NULL)
8588     {
8589         return E_INVALIDARG;
8590     }
8591
8592     *ppEnum = NULL;
8593
8594     // ProfilerModuleEnum uese AppDomainIterator, which cannot be called while the current thead
8595     // is holding the ThreadStore lock.
8596     if (ThreadStore::HoldingThreadStore())
8597     {
8598         return CORPROF_E_UNSUPPORTED_CALL_SEQUENCE;
8599     }
8600
8601     NewHolder<ProfilerModuleEnum> pModuleEnum(new (nothrow) ProfilerModuleEnum);
8602     if (pModuleEnum == NULL)
8603     {
8604         return E_OUTOFMEMORY;
8605     }
8606
8607     hr = pModuleEnum->Init();
8608     if (FAILED(hr))
8609     {
8610         return hr;
8611     }
8612
8613     // Ownership transferred to [out] param.  Caller must Release() when done with this.
8614     *ppEnum = (ICorProfilerModuleEnum *) pModuleEnum.Extract();
8615
8616     return S_OK;
8617 }
8618
8619 HRESULT ProfToEEInterfaceImpl::GetRuntimeInformation(USHORT * pClrInstanceId,
8620                                                      COR_PRF_RUNTIME_TYPE * pRuntimeType,
8621                                                      USHORT * pMajorVersion,
8622                                                      USHORT * pMinorVersion,
8623                                                      USHORT * pBuildNumber,
8624                                                      USHORT * pQFEVersion,
8625                                                      ULONG  cchVersionString,
8626                                                      ULONG  * pcchVersionString,
8627                                                      __out_ecount_part_opt(cchVersionString, *pcchVersionString) WCHAR  szVersionString[])
8628 {
8629     CONTRACTL
8630     {
8631         // Yay!
8632         NOTHROW;
8633
8634         // Yay!
8635         GC_NOTRIGGER;
8636
8637         // Yay!
8638         MODE_ANY;
8639
8640         // Yay!
8641         EE_THREAD_NOT_REQUIRED;
8642
8643         // Yay!
8644         CANNOT_TAKE_LOCK;
8645
8646         SO_NOT_MAINLINE;
8647     }
8648     CONTRACTL_END;
8649
8650     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
8651         (LF_CORPROF, 
8652         LL_INFO1000, 
8653         "**PROF: GetRuntimeInformation.\n"));
8654
8655     if ((szVersionString != NULL) && (pcchVersionString == NULL))
8656     {
8657         return E_INVALIDARG;
8658     }
8659
8660     if (pcchVersionString != NULL)
8661     {
8662         HRESULT hr = GetCORVersionInternal(szVersionString, (DWORD)cchVersionString, (DWORD *)pcchVersionString);
8663         if (FAILED(hr))
8664             return hr;
8665     }    
8666
8667     if (pClrInstanceId != NULL)
8668         *pClrInstanceId = static_cast<USHORT>(GetClrInstanceId());
8669
8670     if (pRuntimeType != NULL)
8671     {
8672         *pRuntimeType = COR_PRF_CORE_CLR;
8673     }
8674
8675     if (pMajorVersion != NULL)
8676         *pMajorVersion = VER_MAJORVERSION;
8677
8678     if (pMinorVersion != NULL)
8679         *pMinorVersion = VER_MINORVERSION;
8680
8681     if (pBuildNumber != NULL)
8682         *pBuildNumber = VER_PRODUCTBUILD;
8683
8684     if (pQFEVersion != NULL)
8685         *pQFEVersion = VER_PRODUCTBUILD_QFE;
8686
8687     return S_OK;
8688 }
8689
8690
8691 HRESULT ProfToEEInterfaceImpl::RequestProfilerDetach(DWORD dwExpectedCompletionMilliseconds)
8692 {
8693     CONTRACTL
8694     {
8695        // Yay!
8696         NOTHROW;
8697
8698         // Crst is used in ProfilingAPIDetach::RequestProfilerDetach so GC may be triggered
8699         GC_TRIGGERS;
8700
8701         // Yay!
8702         MODE_ANY;
8703
8704         // Yay!
8705         EE_THREAD_NOT_REQUIRED;
8706
8707         // Crst is used in ProfilingAPIDetach::RequestProfilerDetach
8708         CAN_TAKE_LOCK;
8709
8710         SO_NOT_MAINLINE;    
8711     }
8712     CONTRACTL_END;
8713
8714     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
8715         kP2EEAllowableAfterAttach | kP2EETriggers,
8716         (LF_CORPROF, 
8717         LL_INFO1000, 
8718         "**PROF: RequestProfilerDetach.\n"));    
8719
8720 #ifdef FEATURE_PROFAPI_ATTACH_DETACH
8721     return ProfilingAPIDetach::RequestProfilerDetach(dwExpectedCompletionMilliseconds);
8722 #else // FEATURE_PROFAPI_ATTACH_DETACH
8723     return E_NOTIMPL;
8724 #endif // FEATURE_PROFAPI_ATTACH_DETACH
8725 }
8726
8727 typedef struct _COR_PRF_ELT_INFO_INTERNAL
8728 {
8729     // Point to a platform dependent structure ASM helper push on the stack
8730     void * platformSpecificHandle;
8731
8732     // startAddress of COR_PRF_FUNCTION_ARGUMENT_RANGE structure needs to point 
8733     // TO the argument value, not BE the argument value.  So, when the argument 
8734     // is this, we need to point TO this.  Because of the calling sequence change
8735     // in ELT3, we need to reserve the pointer here instead of using one of our 
8736     // stack variables.
8737     void * pThis;
8738
8739     // Reserve space for output parameter COR_PRF_FRAME_INFO of 
8740     // GetFunctionXXXX3Info functions
8741     COR_PRF_FRAME_INFO_INTERNAL frameInfo;
8742
8743 } COR_PRF_ELT_INFO_INTERNAL;
8744
8745 //---------------------------------------------------------------------------------------
8746 //
8747 // ProfilingGetFunctionEnter3Info provides frame information and argument infomation of 
8748 // the function ELT callback is inspecting.  It is called either by the profiler or the 
8749 // C helper function.
8750 // 
8751 // Arguments:
8752 //      * functionId - [in] FunctionId of the function being inspected by ELT3
8753 //      * eltInfo - [in] The opaque pointer FunctionEnter3WithInfo callback passed to the profiler
8754 //      * pFrameInfo - [out] Pointer to COR_PRF_FRAME_INFO the profiler later can use to inspect 
8755 //                     generic types
8756 //      * pcbArgumentInfo - [in, out] Pointer to ULONG that specifies the size of structure 
8757 //                          pointed by pArgumentInfo
8758 //      * pArgumentInfo - [out] Pointer to COR_PRF_FUNCTION_ARGUMENT_INFO structure the profiler
8759 //                        must preserve enough space for the function it is inspecting
8760 //          
8761 // Return Value:
8762 //    HRESULT indicating success or failure.
8763 //    
8764
8765 HRESULT ProfilingGetFunctionEnter3Info(FunctionID functionId,                              // in
8766                                        COR_PRF_ELT_INFO eltInfo,                           // in
8767                                        COR_PRF_FRAME_INFO * pFrameInfo,                    // out
8768                                        ULONG * pcbArgumentInfo,                            // in, out
8769                                        COR_PRF_FUNCTION_ARGUMENT_INFO * pArgumentInfo)     // out
8770 {
8771     CONTRACTL
8772     {
8773         // Yay!
8774         NOTHROW;
8775
8776         // Yay!
8777         GC_NOTRIGGER;
8778
8779         // Yay!
8780         MODE_ANY;
8781
8782         // ProfileArgIterator::ProfileArgIterator may take locks
8783         CAN_TAKE_LOCK;
8784
8785         SO_NOT_MAINLINE;
8786
8787     }
8788     CONTRACTL_END;
8789
8790     if ((functionId == NULL) || (eltInfo == NULL))
8791     {
8792         return E_INVALIDARG;
8793     }
8794
8795     COR_PRF_ELT_INFO_INTERNAL * pELTInfo = (COR_PRF_ELT_INFO_INTERNAL *)eltInfo;
8796     ProfileSetFunctionIDInPlatformSpecificHandle(pELTInfo->platformSpecificHandle, functionId);
8797
8798     // The loader won't trigger a GC or throw for already loaded argument types.
8799     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
8800
8801     //
8802     // Find the method this is referring to, so we can get the signature
8803     //
8804     MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
8805     MetaSig metaSig(pMethodDesc);
8806
8807     NewHolder<ProfileArgIterator> pProfileArgIterator;
8808
8809     {
8810         // Can handle E_OUTOFMEMORY from ProfileArgIterator.
8811         FAULT_NOT_FATAL();
8812
8813         pProfileArgIterator = new (nothrow) ProfileArgIterator(&metaSig, pELTInfo->platformSpecificHandle);
8814
8815         if (pProfileArgIterator == NULL)
8816         {
8817             return E_UNEXPECTED;
8818         }
8819     }
8820
8821     if (CORProfilerFrameInfoEnabled())
8822     {
8823         if (pFrameInfo == NULL)
8824         {
8825             return E_INVALIDARG;
8826         }
8827
8828         //
8829         // Setup the COR_PRF_FRAME_INFO structure first.
8830         //
8831         COR_PRF_FRAME_INFO_INTERNAL * pCorPrfFrameInfo = &(pELTInfo->frameInfo);
8832
8833         pCorPrfFrameInfo->size = sizeof(COR_PRF_FRAME_INFO_INTERNAL);
8834         pCorPrfFrameInfo->version = COR_PRF_FRAME_INFO_INTERNAL_CURRENT_VERSION;
8835         pCorPrfFrameInfo->funcID = functionId;
8836         pCorPrfFrameInfo->IP = ProfileGetIPFromPlatformSpecificHandle(pELTInfo->platformSpecificHandle);
8837         pCorPrfFrameInfo->extraArg = pProfileArgIterator->GetHiddenArgValue();
8838         pCorPrfFrameInfo->thisArg = pProfileArgIterator->GetThis();
8839
8840         *pFrameInfo = (COR_PRF_FRAME_INFO)pCorPrfFrameInfo;
8841     }
8842
8843     //
8844     // Do argument processing if desired.
8845     //
8846     if (CORProfilerFunctionArgsEnabled())
8847     {
8848         if (pcbArgumentInfo == NULL)
8849         {
8850             return E_INVALIDARG;
8851         }
8852
8853         if ((*pcbArgumentInfo != 0) && (pArgumentInfo == NULL))
8854         {
8855             return E_INVALIDARG;
8856         }
8857
8858         ULONG32 count = pProfileArgIterator->GetNumArgs();
8859
8860         if (metaSig.HasThis())
8861         {
8862             count++;
8863         }
8864
8865         ULONG ulArgInfoSize = sizeof(COR_PRF_FUNCTION_ARGUMENT_INFO) + (count * sizeof(COR_PRF_FUNCTION_ARGUMENT_RANGE));
8866
8867         if (*pcbArgumentInfo < ulArgInfoSize)
8868         {
8869             *pcbArgumentInfo = ulArgInfoSize;
8870             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
8871         }
8872
8873         _ASSERTE(pArgumentInfo != NULL);
8874
8875         pArgumentInfo->numRanges         = count;
8876         pArgumentInfo->totalArgumentSize = 0;
8877
8878         count = 0;
8879
8880         if (metaSig.HasThis())
8881         {
8882             pELTInfo->pThis = pProfileArgIterator->GetThis();
8883             pArgumentInfo->ranges[count].startAddress = (UINT_PTR) (&(pELTInfo->pThis));
8884
8885             UINT length = sizeof(pELTInfo->pThis);
8886             pArgumentInfo->ranges[count].length = length;
8887             pArgumentInfo->totalArgumentSize += length;
8888             count++;
8889         }
8890
8891         while (count < pArgumentInfo->numRanges)
8892         {
8893             pArgumentInfo->ranges[count].startAddress = (UINT_PTR)(pProfileArgIterator->GetNextArgAddr());
8894
8895             UINT length = pProfileArgIterator->GetArgSize();
8896             pArgumentInfo->ranges[count].length = length;
8897             pArgumentInfo->totalArgumentSize += length;
8898             count++;
8899         }
8900     }
8901
8902     return S_OK;
8903 }
8904
8905
8906
8907 HRESULT ProfToEEInterfaceImpl::GetFunctionEnter3Info(FunctionID functionId,                              // in
8908                                                      COR_PRF_ELT_INFO eltInfo,                           // in
8909                                                      COR_PRF_FRAME_INFO * pFrameInfo,                    // out
8910                                                      ULONG * pcbArgumentInfo,                            // in, out
8911                                                      COR_PRF_FUNCTION_ARGUMENT_INFO * pArgumentInfo)     // out
8912 {
8913     CONTRACTL
8914     {
8915         // Yay!
8916         NOTHROW;
8917
8918         // Yay!
8919         GC_NOTRIGGER;
8920
8921         // Yay!
8922         MODE_ANY;
8923
8924         // ProfilingGetFunctionEnter3Info may take locks
8925         CAN_TAKE_LOCK;
8926
8927         SO_NOT_MAINLINE;
8928
8929     }
8930     CONTRACTL_END;
8931
8932     PROFILER_TO_CLR_ENTRYPOINT_SYNC((LF_CORPROF, 
8933                                     LL_INFO1000, 
8934                                     "**PROF: GetFunctionEnter3Info.\n"));
8935
8936     _ASSERTE(g_profControlBlock.pProfInterface->GetEnter3WithInfoHook() != NULL);
8937
8938     if (!CORProfilerELT3SlowPathEnterEnabled())
8939     {
8940         return CORPROF_E_INCONSISTENT_WITH_FLAGS;
8941     }
8942
8943     return ProfilingGetFunctionEnter3Info(functionId, eltInfo, pFrameInfo, pcbArgumentInfo, pArgumentInfo);
8944 }
8945
8946 //---------------------------------------------------------------------------------------
8947 //
8948 // ProfilingGetFunctionLeave3Info provides frame information and return value infomation 
8949 // of the function ELT callback is inspecting.  It is called either by the profiler or the 
8950 // C helper function.
8951 // 
8952 // Arguments:
8953 //      * functionId - [in] FunctionId of the function being inspected by ELT3
8954 //      * eltInfo - [in] The opaque pointer FunctionLeave3WithInfo callback passed to the profiler
8955 //      * pFrameInfo - [out] Pointer to COR_PRF_FRAME_INFO the profiler later can use to inspect 
8956 //                     generic types
8957 //      * pRetvalRange - [out] Pointer to COR_PRF_FUNCTION_ARGUMENT_RANGE to store return value
8958 //          
8959 // Return Value:
8960 //    HRESULT indicating success or failure.
8961 //    
8962
8963 HRESULT ProfilingGetFunctionLeave3Info(FunctionID functionId,                              // in
8964                                        COR_PRF_ELT_INFO eltInfo,                           // in
8965                                        COR_PRF_FRAME_INFO * pFrameInfo,                    // out
8966                                        COR_PRF_FUNCTION_ARGUMENT_RANGE * pRetvalRange)     // out
8967 {
8968     CONTRACTL
8969     {
8970         // Yay!
8971         NOTHROW;
8972
8973         // Yay!
8974         GC_NOTRIGGER;
8975
8976         // Yay!
8977         MODE_ANY;
8978
8979         // ProfileArgIterator::ProfileArgIterator may take locks
8980         CAN_TAKE_LOCK;
8981
8982         SO_NOT_MAINLINE;
8983     }
8984     CONTRACTL_END;
8985
8986     if ((pFrameInfo == NULL) || (eltInfo == NULL))
8987     {
8988         return E_INVALIDARG;
8989     }
8990
8991     COR_PRF_ELT_INFO_INTERNAL * pELTInfo = (COR_PRF_ELT_INFO_INTERNAL *)eltInfo;
8992     ProfileSetFunctionIDInPlatformSpecificHandle(pELTInfo->platformSpecificHandle, functionId);
8993
8994     // The loader won't trigger a GC or throw for already loaded argument types.
8995     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
8996
8997     //
8998     // Find the method this is referring to, so we can get the signature
8999     //
9000     MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
9001     MetaSig metaSig(pMethodDesc);
9002
9003     NewHolder<ProfileArgIterator> pProfileArgIterator;
9004
9005     {
9006         // Can handle E_OUTOFMEMORY from ProfileArgIterator.
9007         FAULT_NOT_FATAL();
9008
9009         pProfileArgIterator = new (nothrow) ProfileArgIterator(&metaSig, pELTInfo->platformSpecificHandle);
9010
9011         if (pProfileArgIterator == NULL)
9012         {
9013             return E_UNEXPECTED;
9014         }
9015     }
9016
9017     if (CORProfilerFrameInfoEnabled())
9018     {
9019         if (pFrameInfo == NULL)
9020         {
9021             return E_INVALIDARG;
9022         }
9023
9024         COR_PRF_FRAME_INFO_INTERNAL * pCorPrfFrameInfo = &(pELTInfo->frameInfo);
9025
9026         //
9027         // Setup the COR_PRF_FRAME_INFO structure first.
9028         //
9029         pCorPrfFrameInfo->size = sizeof(COR_PRF_FRAME_INFO_INTERNAL);
9030         pCorPrfFrameInfo->version = COR_PRF_FRAME_INFO_INTERNAL_CURRENT_VERSION;
9031         pCorPrfFrameInfo->funcID = functionId;
9032         pCorPrfFrameInfo->IP = ProfileGetIPFromPlatformSpecificHandle(pELTInfo->platformSpecificHandle);
9033
9034         // Upon entering Leave hook, the register assigned to store this pointer on function calls may 
9035         // already be reused and is likely not to contain this pointer.
9036         pCorPrfFrameInfo->extraArg = NULL;
9037         pCorPrfFrameInfo->thisArg = NULL;
9038
9039         *pFrameInfo = (COR_PRF_FRAME_INFO)pCorPrfFrameInfo;
9040     }
9041
9042     //
9043     // Do argument processing if desired.
9044     //
9045     if (CORProfilerFunctionReturnValueEnabled())
9046     {
9047         if (pRetvalRange == NULL)
9048         {
9049             return E_INVALIDARG;
9050         }
9051
9052         if (!metaSig.IsReturnTypeVoid())
9053         {
9054             pRetvalRange->length = metaSig.GetReturnTypeSize();
9055             pRetvalRange->startAddress = (UINT_PTR)pProfileArgIterator->GetReturnBufferAddr();
9056         }
9057         else
9058         {
9059             pRetvalRange->length = 0;
9060             pRetvalRange->startAddress = 0;
9061         }
9062     }
9063
9064     return S_OK;
9065 }
9066
9067
9068 HRESULT ProfToEEInterfaceImpl::GetFunctionLeave3Info(FunctionID functionId,                              // in
9069                                                      COR_PRF_ELT_INFO eltInfo,                           // in
9070                                                      COR_PRF_FRAME_INFO * pFrameInfo,                    // out
9071                                                      COR_PRF_FUNCTION_ARGUMENT_RANGE * pRetvalRange)     // out
9072 {
9073     CONTRACTL
9074     {
9075         // Yay!
9076         NOTHROW;
9077
9078         // Yay!
9079         GC_NOTRIGGER;
9080
9081         // Yay!
9082         MODE_ANY;
9083
9084         // ProfilingGetFunctionLeave3Info may take locks
9085         CAN_TAKE_LOCK;
9086
9087         SO_NOT_MAINLINE;
9088
9089     }
9090     CONTRACTL_END;
9091
9092     PROFILER_TO_CLR_ENTRYPOINT_SYNC((LF_CORPROF, 
9093                                     LL_INFO1000, 
9094                                     "**PROF: GetFunctionLeave3Info.\n"));
9095
9096     _ASSERTE(g_profControlBlock.pProfInterface->GetLeave3WithInfoHook() != NULL);
9097
9098     if (!CORProfilerELT3SlowPathLeaveEnabled())
9099     {
9100         return CORPROF_E_INCONSISTENT_WITH_FLAGS;
9101     }
9102
9103     return ProfilingGetFunctionLeave3Info(functionId, eltInfo, pFrameInfo, pRetvalRange);
9104 }
9105
9106 //---------------------------------------------------------------------------------------
9107 //
9108 // ProfilingGetFunctionTailcall3Info provides frame information of the function ELT callback 
9109 // is inspecting.  It is called either by the profiler or the C helper function.
9110 // 
9111 // Arguments:
9112 //      * functionId - [in] FunctionId of the function being inspected by ELT3
9113 //      * eltInfo - [in] The opaque pointer FunctionTailcall3WithInfo callback passed to the 
9114 //                  profiler
9115 //      * pFrameInfo - [out] Pointer to COR_PRF_FRAME_INFO the profiler later can use to inspect 
9116 //                     generic types
9117 //          
9118 // Return Value:
9119 //    HRESULT indicating success or failure.
9120 //    
9121
9122 HRESULT ProfilingGetFunctionTailcall3Info(FunctionID functionId,                              // in
9123                                           COR_PRF_ELT_INFO eltInfo,                           // in
9124                                           COR_PRF_FRAME_INFO * pFrameInfo)                    // out
9125 {
9126     CONTRACTL
9127     {
9128         // Yay!
9129         NOTHROW;
9130
9131         // Yay!
9132         GC_NOTRIGGER;
9133
9134         // Yay!
9135         MODE_ANY;
9136
9137         // ProfileArgIterator::ProfileArgIterator may take locks
9138         CAN_TAKE_LOCK;
9139
9140         SO_NOT_MAINLINE;
9141
9142     }
9143     CONTRACTL_END;
9144
9145     if ((functionId == NULL) || (eltInfo == NULL) || (pFrameInfo == NULL))
9146     {
9147         return E_INVALIDARG;
9148     }
9149
9150     COR_PRF_ELT_INFO_INTERNAL * pELTInfo = (COR_PRF_ELT_INFO_INTERNAL *)eltInfo;
9151     ProfileSetFunctionIDInPlatformSpecificHandle(pELTInfo->platformSpecificHandle, functionId);
9152
9153     // The loader won't trigger a GC or throw for already loaded argument types.
9154     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
9155
9156     //
9157     // Find the method this is referring to, so we can get the signature
9158     //
9159     MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
9160     MetaSig metaSig(pMethodDesc);
9161
9162     NewHolder<ProfileArgIterator> pProfileArgIterator;
9163
9164     {
9165         // Can handle E_OUTOFMEMORY from ProfileArgIterator.
9166         FAULT_NOT_FATAL();
9167
9168         pProfileArgIterator = new (nothrow) ProfileArgIterator(&metaSig, pELTInfo->platformSpecificHandle);
9169
9170         if (pProfileArgIterator == NULL)
9171         {
9172             return E_UNEXPECTED;
9173         }
9174     }
9175
9176     COR_PRF_FRAME_INFO_INTERNAL * pCorPrfFrameInfo = &(pELTInfo->frameInfo);
9177
9178     //
9179     // Setup the COR_PRF_FRAME_INFO structure first.
9180     //
9181     pCorPrfFrameInfo->size = sizeof(COR_PRF_FRAME_INFO_INTERNAL);
9182     pCorPrfFrameInfo->version = COR_PRF_FRAME_INFO_INTERNAL_CURRENT_VERSION;
9183     pCorPrfFrameInfo->funcID = functionId;
9184     pCorPrfFrameInfo->IP = ProfileGetIPFromPlatformSpecificHandle(pELTInfo->platformSpecificHandle);
9185
9186     // Tailcall is designed to report the caller, not the callee.  But the taillcall hook is invoked 
9187     // with registers containing parameters passed to the callee before calling into the callee.  
9188     // This pointer we get here is for the callee.  Because of the constraints imposed on tailcall
9189     // optimization, this pointer passed to the callee accidentally happens to be the same this pointer 
9190     // passed to the caller.  
9191     // 
9192     // It is a fragile coincidence we should not depend on because JIT is free to change the 
9193     // implementation details in the future.
9194     pCorPrfFrameInfo->extraArg = NULL;
9195     pCorPrfFrameInfo->thisArg = NULL;
9196
9197     *pFrameInfo = (COR_PRF_FRAME_INFO)pCorPrfFrameInfo;
9198
9199     return S_OK;
9200 }
9201
9202
9203 HRESULT ProfToEEInterfaceImpl::GetFunctionTailcall3Info(FunctionID functionId,                              // in
9204                                                         COR_PRF_ELT_INFO eltInfo,                           // in
9205                                                         COR_PRF_FRAME_INFO * pFrameInfo)                    // out
9206 {
9207     CONTRACTL
9208     {
9209         // Yay!
9210         NOTHROW;
9211
9212         // Yay!
9213         GC_NOTRIGGER;
9214
9215         // Yay!
9216         MODE_ANY;
9217
9218         // ProfilingGetFunctionTailcall3Info may take locks
9219         CAN_TAKE_LOCK;
9220
9221         SO_NOT_MAINLINE;
9222
9223     }
9224     CONTRACTL_END;
9225
9226     PROFILER_TO_CLR_ENTRYPOINT_SYNC((LF_CORPROF, 
9227                                     LL_INFO1000, 
9228                                     "**PROF: GetFunctionTailcall3Info.\n"));
9229
9230     _ASSERTE(g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook() != NULL);
9231
9232     if (!CORProfilerELT3SlowPathTailcallEnabled())
9233     {
9234         return CORPROF_E_INCONSISTENT_WITH_FLAGS;
9235     }
9236
9237     return ProfilingGetFunctionTailcall3Info(functionId, eltInfo, pFrameInfo);
9238 }
9239
9240 HRESULT ProfToEEInterfaceImpl::EnumThreads(
9241     /* out */ ICorProfilerThreadEnum ** ppEnum)
9242 {
9243
9244     CONTRACTL
9245     {
9246         // Yay!
9247         NOTHROW;
9248
9249         // Yay!
9250         GC_NOTRIGGER;
9251
9252         // Yay!
9253         MODE_ANY;
9254
9255         // Need to acquire the thread store lock
9256         CAN_TAKE_LOCK;
9257         
9258         SO_NOT_MAINLINE;
9259
9260         PRECONDITION(CheckPointer(ppEnum, NULL_OK));
9261
9262     }
9263     CONTRACTL_END;
9264
9265     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
9266         kP2EEAllowableAfterAttach,
9267         (LF_CORPROF, 
9268         LL_INFO10, 
9269         "**PROF: EnumThreads.\n"));
9270
9271     HRESULT hr;
9272
9273     if (ppEnum == NULL)
9274     {
9275         return E_INVALIDARG;
9276     }
9277
9278     *ppEnum = NULL;
9279
9280     NewHolder<ProfilerThreadEnum> pThreadEnum(new (nothrow) ProfilerThreadEnum);
9281     if (pThreadEnum == NULL)
9282     {
9283         return E_OUTOFMEMORY;
9284     }
9285
9286     hr = pThreadEnum->Init();
9287     if (FAILED(hr))
9288     {
9289         return hr;
9290     }
9291
9292     // Ownership transferred to [out] param.  Caller must Release() when done with this.
9293     *ppEnum = (ICorProfilerThreadEnum *) pThreadEnum.Extract();
9294
9295     return S_OK;
9296 }
9297
9298 // This function needs to be called on any thread before making any ICorProfilerInfo* calls and must be 
9299 // made before any thread is suspended by this profiler.
9300 // As you might have already figured out, this is done to avoid deadlocks situation when 
9301 // the suspended thread holds on the loader lock / heap lock while the current thread is trying to obtain
9302 // the same lock.
9303 HRESULT ProfToEEInterfaceImpl::InitializeCurrentThread()
9304 {
9305
9306     CONTRACTL
9307     {
9308         // Yay!
9309         NOTHROW;
9310
9311         // Yay!
9312         GC_NOTRIGGER;
9313
9314         // Yay!
9315         MODE_ANY;
9316
9317         // May take thread store lock and OS APIs may also take locks
9318         CAN_TAKE_LOCK;
9319         
9320         SO_NOT_MAINLINE;
9321     }
9322     CONTRACTL_END;
9323     
9324    
9325     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
9326             kP2EEAllowableAfterAttach,
9327             (LF_CORPROF, 
9328             LL_INFO10, 
9329             "**PROF: InitializeCurrentThread.\n"));
9330
9331     HRESULT hr = S_OK;
9332     
9333     EX_TRY
9334     {
9335         CExecutionEngine::SetupTLSForThread(GetThread());
9336     }
9337     EX_CATCH_HRESULT(hr);
9338
9339     if (FAILED(hr))
9340         return hr;
9341     
9342      return S_OK;
9343 }
9344
9345 struct InternalProfilerModuleEnum : public ProfilerModuleEnum
9346 {
9347     CDynArray<ModuleID> *GetRawElementsArray()
9348     {
9349         return &m_elements;
9350     }
9351 };
9352
9353 HRESULT ProfToEEInterfaceImpl::EnumNgenModuleMethodsInliningThisMethod(
9354     ModuleID    inlinersModuleId,
9355     ModuleID    inlineeModuleId,
9356     mdMethodDef inlineeMethodId,
9357     BOOL       *incompleteData,
9358     ICorProfilerMethodEnum** ppEnum)
9359 {
9360     CONTRACTL
9361     {
9362         NOTHROW;
9363         GC_TRIGGERS; 
9364         MODE_ANY;
9365         SO_NOT_MAINLINE;
9366         CAN_TAKE_LOCK;
9367         PRECONDITION(CheckPointer(ppEnum));
9368     }
9369     CONTRACTL_END;
9370
9371     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EETriggers, (LF_CORPROF, LL_INFO1000,  "**PROF: EnumNgenModuleMethodsInliningThisMethod.\n"));
9372
9373     if (ppEnum == NULL)
9374     {
9375         return E_INVALIDARG;
9376     }
9377     *ppEnum = NULL;
9378     HRESULT hr = S_OK;
9379
9380     Module *inlineeOwnerModule = reinterpret_cast<Module *>(inlineeModuleId);
9381     if (inlineeOwnerModule == NULL)
9382     {
9383         return E_INVALIDARG;
9384     }
9385     if (inlineeOwnerModule->IsBeingUnloaded())
9386     {
9387         return CORPROF_E_DATAINCOMPLETE;
9388     }
9389
9390     Module  *inlinersModule = reinterpret_cast<Module *>(inlinersModuleId);
9391     if (inlinersModule == NULL)
9392     {
9393         return E_INVALIDARG;
9394     }
9395     if(inlinersModule->IsBeingUnloaded())
9396     {
9397         return CORPROF_E_DATAINCOMPLETE;
9398     }
9399
9400     PersistentInlineTrackingMap *inliningMap = inlinersModule->GetNgenInlineTrackingMap();
9401     if (inliningMap == NULL)
9402     {
9403         return CORPROF_E_DATAINCOMPLETE;
9404     }
9405
9406     CDynArray<COR_PRF_METHOD> results;
9407     const COUNT_T staticBufferSize = 10;
9408     MethodInModule staticBuffer[staticBufferSize];
9409     NewArrayHolder<MethodInModule> dynamicBuffer;
9410     MethodInModule *methodsBuffer = staticBuffer;
9411     EX_TRY
9412     {
9413         // Trying to use static buffer
9414         COUNT_T methodsAvailable = inliningMap->GetInliners(inlineeOwnerModule, inlineeMethodId, staticBufferSize, staticBuffer, incompleteData);
9415
9416         // If static buffer is not enough, allocate an array.
9417         if (methodsAvailable > staticBufferSize)
9418         {
9419             DWORD dynamicBufferSize = methodsAvailable;
9420             dynamicBuffer = methodsBuffer = new MethodInModule[dynamicBufferSize];
9421             methodsAvailable = inliningMap->GetInliners(inlineeOwnerModule, inlineeMethodId, dynamicBufferSize, dynamicBuffer, incompleteData);                
9422             if (methodsAvailable > dynamicBufferSize)
9423             {
9424                 _ASSERTE(!"Ngen image inlining info changed, this shouldn't be possible.");
9425                 methodsAvailable = dynamicBufferSize;
9426             }
9427         }
9428
9429         //Go through all inliners found in the inlinersModule and prepare them to export via results.
9430         results.AllocateBlockThrowing(methodsAvailable);
9431         for (COUNT_T j = 0; j < methodsAvailable; j++)
9432         {
9433             COR_PRF_METHOD *newPrfMethod = &results[j];
9434             newPrfMethod->moduleId = reinterpret_cast<ModuleID>(methodsBuffer[j].m_module);
9435             newPrfMethod->methodId = methodsBuffer[j].m_methodDef;
9436         }
9437         *ppEnum = new ProfilerMethodEnum(&results);
9438     }
9439     EX_CATCH_HRESULT(hr);
9440
9441     return hr;
9442 }
9443
9444 HRESULT ProfToEEInterfaceImpl::GetInMemorySymbolsLength(
9445     ModuleID moduleId,
9446     DWORD* pCountSymbolBytes)
9447 {
9448
9449     CONTRACTL
9450     {
9451         NOTHROW;
9452         GC_NOTRIGGER;
9453         MODE_ANY;
9454         SO_NOT_MAINLINE;
9455     }
9456     CONTRACTL_END;
9457
9458
9459     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
9460         kP2EEAllowableAfterAttach,
9461         (LF_CORPROF,
9462             LL_INFO10,
9463             "**PROF: GetInMemorySymbolsLength.\n"));
9464
9465     HRESULT hr = S_OK;
9466     if (pCountSymbolBytes == NULL)
9467     {
9468         return E_INVALIDARG;
9469     }
9470     *pCountSymbolBytes = 0;
9471
9472     Module* pModule = reinterpret_cast< Module* >(moduleId);
9473     if (pModule == NULL)
9474     {
9475         return E_INVALIDARG;
9476     }
9477     if (pModule->IsBeingUnloaded())
9478     {
9479         return CORPROF_E_DATAINCOMPLETE;
9480     }
9481
9482     //This method would work fine on reflection.emit, but there would be no way to know
9483     //if some other thread was changing the size of the symbols before this method returned.
9484     //Adding events or locks to detect/prevent changes would make the scenario workable
9485     if (pModule->IsReflection())
9486     {
9487         return COR_PRF_MODULE_DYNAMIC;
9488     }
9489     
9490     CGrowableStream* pStream = pModule->GetInMemorySymbolStream();
9491     if (pStream == NULL)
9492     {
9493         return S_OK;
9494     }
9495
9496     STATSTG SizeData = { 0 };
9497     hr = pStream->Stat(&SizeData, STATFLAG_NONAME);
9498     if (FAILED(hr))
9499     {
9500         return hr;
9501     }
9502     if (SizeData.cbSize.u.HighPart > 0)
9503     {
9504         return COR_E_OVERFLOW;
9505     }
9506     *pCountSymbolBytes = SizeData.cbSize.u.LowPart;
9507
9508     return S_OK;
9509 }
9510
9511 HRESULT ProfToEEInterfaceImpl::ReadInMemorySymbols(
9512     ModuleID moduleId,
9513     DWORD symbolsReadOffset,
9514     BYTE* pSymbolBytes,
9515     DWORD countSymbolBytes,
9516     DWORD* pCountSymbolBytesRead)
9517 {
9518     CONTRACTL
9519     {
9520         NOTHROW;
9521         GC_NOTRIGGER;
9522         MODE_ANY;
9523         SO_NOT_MAINLINE;
9524     }
9525     CONTRACTL_END;
9526
9527     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
9528         kP2EEAllowableAfterAttach,
9529         (LF_CORPROF,
9530             LL_INFO10,
9531             "**PROF: ReadInMemorySymbols.\n"));
9532
9533     HRESULT hr = S_OK;
9534     if (pSymbolBytes == NULL)
9535     {
9536         return E_INVALIDARG;
9537     }
9538     if (pCountSymbolBytesRead == NULL)
9539     {
9540         return E_INVALIDARG;
9541     }
9542     *pCountSymbolBytesRead = 0;
9543
9544     Module* pModule = reinterpret_cast< Module* >(moduleId);
9545     if (pModule == NULL)
9546     {
9547         return E_INVALIDARG;
9548     }
9549     if (pModule->IsBeingUnloaded())
9550     {
9551         return CORPROF_E_DATAINCOMPLETE;
9552     }
9553
9554     //This method would work fine on reflection.emit, but there would be no way to know
9555     //if some other thread was changing the size of the symbols before this method returned.
9556     //Adding events or locks to detect/prevent changes would make the scenario workable
9557     if (pModule->IsReflection())
9558     {
9559         return COR_PRF_MODULE_DYNAMIC;
9560     }
9561
9562     CGrowableStream* pStream = pModule->GetInMemorySymbolStream();
9563     if (pStream == NULL)
9564     {
9565         return E_INVALIDARG;
9566     }
9567
9568     STATSTG SizeData = { 0 };
9569     hr = pStream->Stat(&SizeData, STATFLAG_NONAME);
9570     if (FAILED(hr))
9571     {
9572         return hr;
9573     }
9574     if (SizeData.cbSize.u.HighPart > 0)
9575     {
9576         return COR_E_OVERFLOW;
9577     }
9578     DWORD streamSize = SizeData.cbSize.u.LowPart;
9579     if (symbolsReadOffset >= streamSize)
9580     {
9581         return E_INVALIDARG;
9582     }
9583
9584     *pCountSymbolBytesRead = min(streamSize - symbolsReadOffset, countSymbolBytes);
9585     memcpy_s(pSymbolBytes, countSymbolBytes, ((BYTE*)pStream->GetRawBuffer().StartAddress()) + symbolsReadOffset, *pCountSymbolBytesRead);
9586
9587     return S_OK;
9588 }
9589
9590 HRESULT ProfToEEInterfaceImpl::ApplyMetaData(
9591     ModuleID    moduleId)
9592 {
9593     CONTRACTL
9594     {
9595         NOTHROW;
9596         GC_NOTRIGGER;
9597         MODE_ANY;
9598         SO_NOT_MAINLINE;
9599     }
9600     CONTRACTL_END;
9601
9602     PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach, (LF_CORPROF, LL_INFO1000, "**PROF: ApplyMetaData.\n"));
9603
9604     if (moduleId == NULL)
9605     {
9606         return E_INVALIDARG;
9607     }
9608
9609     HRESULT hr = S_OK;
9610     EX_TRY
9611     {
9612         Module *pModule = (Module *)moduleId;
9613         _ASSERTE(pModule != NULL);
9614         if (pModule->IsBeingUnloaded())
9615         {
9616             hr = CORPROF_E_DATAINCOMPLETE;
9617         }
9618        else
9619        {
9620             pModule->ApplyMetaData();
9621        }
9622     }
9623     EX_CATCH_HRESULT(hr);
9624     return hr;
9625 }
9626
9627 //---------------------------------------------------------------------------------------
9628 //
9629 // Simple wrapper around EEToProfInterfaceImpl::ManagedToUnmanagedTransition.  This
9630 // can be called by C++ code and directly by generated stubs.
9631 //
9632 // Arguments:
9633 //      pMD - MethodDesc for the managed function involved in the transition
9634 //      reason - Passed on to profiler to indicate why the transition is occurring
9635 //
9636
9637 void __stdcall ProfilerManagedToUnmanagedTransitionMD(MethodDesc *pMD,
9638                                                       COR_PRF_TRANSITION_REASON reason)
9639 {
9640     CONTRACTL
9641     {
9642         NOTHROW;
9643         GC_TRIGGERS;
9644         MODE_PREEMPTIVE;
9645         SO_TOLERANT;
9646     }
9647     CONTRACTL_END;
9648
9649     // This function is called within the runtime, not directly from managed code.
9650     // Also, the only case MD is NULL is the calli pinvoke case, and we still
9651     // want to notify the profiler in that case.
9652
9653     // Do not notify the profiler about QCalls
9654     if (pMD == NULL || !pMD->IsQCall())
9655     {
9656         BEGIN_PIN_PROFILER(CORProfilerPresent());
9657         g_profControlBlock.pProfInterface->ManagedToUnmanagedTransition(MethodDescToFunctionID(pMD),
9658                                                                         reason);
9659         END_PIN_PROFILER();
9660     }
9661 }
9662
9663 //---------------------------------------------------------------------------------------
9664 //
9665 // Simple wrapper around EEToProfInterfaceImpl::UnmanagedToManagedTransition.  This
9666 // can be called by C++ code and directly by generated stubs.
9667 //
9668 // Arguments:
9669 //      pMD - MethodDesc for the managed function involved in the transition
9670 //      reason - Passed on to profiler to indicate why the transition is occurring
9671 //
9672
9673 void __stdcall ProfilerUnmanagedToManagedTransitionMD(MethodDesc *pMD,
9674                                                       COR_PRF_TRANSITION_REASON reason)
9675 {
9676     CONTRACTL
9677     {
9678         NOTHROW;
9679         GC_TRIGGERS;
9680         MODE_PREEMPTIVE;
9681         SO_TOLERANT;
9682     }
9683     CONTRACTL_END;
9684
9685     // This function is called within the runtime, not directly from managed code.
9686     // Also, the only case MD is NULL is the calli pinvoke case, and we still
9687     // want to notify the profiler in that case.
9688
9689     // Do not notify the profiler about QCalls
9690     if (pMD == NULL || !pMD->IsQCall())
9691     {
9692         BEGIN_PIN_PROFILER(CORProfilerPresent());
9693         g_profControlBlock.pProfInterface->UnmanagedToManagedTransition(MethodDescToFunctionID(pMD),
9694                                                                         reason);
9695         END_PIN_PROFILER();
9696     }
9697 }
9698
9699
9700
9701 #endif // PROFILING_SUPPORTED
9702
9703
9704 FCIMPL0(FC_BOOL_RET, ProfilingFCallHelper::FC_TrackRemoting)
9705 {
9706     FCALL_CONTRACT;
9707
9708 #ifdef PROFILING_SUPPORTED
9709     FC_RETURN_BOOL(CORProfilerTrackRemoting());
9710 #else // !PROFILING_SUPPORTED
9711     FC_RETURN_BOOL(FALSE);
9712 #endif // !PROFILING_SUPPORTED
9713 }
9714 FCIMPLEND
9715
9716 FCIMPL0(FC_BOOL_RET, ProfilingFCallHelper::FC_TrackRemotingCookie)
9717 {
9718     FCALL_CONTRACT;
9719
9720 #ifdef PROFILING_SUPPORTED
9721     FC_RETURN_BOOL(CORProfilerTrackRemotingCookie());
9722 #else // !PROFILING_SUPPORTED
9723     FC_RETURN_BOOL(FALSE);
9724 #endif // !PROFILING_SUPPORTED
9725 }
9726 FCIMPLEND
9727
9728 FCIMPL0(FC_BOOL_RET, ProfilingFCallHelper::FC_TrackRemotingAsync)
9729 {
9730     FCALL_CONTRACT;
9731
9732 #ifdef PROFILING_SUPPORTED
9733     FC_RETURN_BOOL(CORProfilerTrackRemotingAsync());
9734 #else // !PROFILING_SUPPORTED
9735     FC_RETURN_BOOL(FALSE);
9736 #endif // !PROFILING_SUPPORTED
9737 }
9738 FCIMPLEND
9739
9740 FCIMPL2(void, ProfilingFCallHelper::FC_RemotingClientSendingMessage, GUID *pId, CLR_BOOL fIsAsync)
9741 {
9742     FCALL_CONTRACT;
9743
9744 #ifdef PROFILING_SUPPORTED
9745     // Need to erect a GC frame so that GCs can occur without a problem
9746     // within the profiler code.
9747
9748     // Note that we don't need to worry about pId moving around since
9749     // it is a value class declared on the stack and so GC doesn't
9750     // know about it.
9751
9752     _ASSERTE (!GCHeapUtilities::GetGCHeap()->IsHeapPointer(pId));     // should be on the stack, not in the heap
9753     HELPER_METHOD_FRAME_BEGIN_NOPOLL();
9754
9755     {
9756         BEGIN_PIN_PROFILER(CORProfilerPresent());
9757         GCX_PREEMP();
9758         if (CORProfilerTrackRemotingCookie())
9759         {
9760             g_profControlBlock.pProfInterface->GetGUID(pId);
9761             _ASSERTE(pId->Data1);
9762
9763             g_profControlBlock.pProfInterface->RemotingClientSendingMessage(pId, fIsAsync);
9764         }
9765         else
9766         {
9767             g_profControlBlock.pProfInterface->RemotingClientSendingMessage(NULL, fIsAsync);
9768         }
9769         END_PIN_PROFILER();
9770     }
9771     HELPER_METHOD_FRAME_END_POLL();
9772 #endif // PROFILING_SUPPORTED
9773 }
9774 FCIMPLEND
9775
9776
9777 FCIMPL2_VI(void, ProfilingFCallHelper::FC_RemotingClientReceivingReply, GUID id, CLR_BOOL fIsAsync)
9778 {
9779     FCALL_CONTRACT;
9780
9781 #ifdef PROFILING_SUPPORTED
9782     // Need to erect a GC frame so that GCs can occur without a problem
9783     // within the profiler code.
9784
9785     // Note that we don't need to worry about pId moving around since
9786     // it is a value class declared on the stack and so GC doesn't
9787     // know about it.
9788
9789     HELPER_METHOD_FRAME_BEGIN_NOPOLL();
9790
9791
9792     {
9793         BEGIN_PIN_PROFILER(CORProfilerPresent());
9794         GCX_PREEMP();
9795         if (CORProfilerTrackRemotingCookie())
9796         {
9797             g_profControlBlock.pProfInterface->RemotingClientReceivingReply(&id, fIsAsync);
9798         }
9799         else
9800         {
9801             g_profControlBlock.pProfInterface->RemotingClientReceivingReply(NULL, fIsAsync);
9802         }
9803         END_PIN_PROFILER();
9804     }
9805
9806     HELPER_METHOD_FRAME_END_POLL();
9807 #endif // PROFILING_SUPPORTED
9808 }
9809 FCIMPLEND
9810
9811
9812 FCIMPL2_VI(void, ProfilingFCallHelper::FC_RemotingServerReceivingMessage, GUID id, CLR_BOOL fIsAsync)
9813 {
9814     FCALL_CONTRACT;
9815
9816 #ifdef PROFILING_SUPPORTED
9817     // Need to erect a GC frame so that GCs can occur without a problem
9818     // within the profiler code.
9819
9820     // Note that we don't need to worry about pId moving around since
9821     // it is a value class declared on the stack and so GC doesn't
9822     // know about it.
9823
9824     HELPER_METHOD_FRAME_BEGIN_NOPOLL();
9825
9826     {
9827         BEGIN_PIN_PROFILER(CORProfilerPresent());
9828         GCX_PREEMP();
9829         if (CORProfilerTrackRemotingCookie())
9830         {
9831             g_profControlBlock.pProfInterface->RemotingServerReceivingMessage(&id, fIsAsync);
9832         }
9833         else
9834         {
9835             g_profControlBlock.pProfInterface->RemotingServerReceivingMessage(NULL, fIsAsync);
9836         }
9837         END_PIN_PROFILER();
9838     }
9839
9840     HELPER_METHOD_FRAME_END_POLL();
9841 #endif // PROFILING_SUPPORTED
9842 }
9843 FCIMPLEND
9844
9845 FCIMPL2(void, ProfilingFCallHelper::FC_RemotingServerSendingReply, GUID *pId, CLR_BOOL fIsAsync)
9846 {
9847     FCALL_CONTRACT;
9848
9849 #ifdef PROFILING_SUPPORTED
9850     // Need to erect a GC frame so that GCs can occur without a problem
9851     // within the profiler code.
9852
9853     // Note that we don't need to worry about pId moving around since
9854     // it is a value class declared on the stack and so GC doesn't
9855     // know about it.
9856
9857     HELPER_METHOD_FRAME_BEGIN_NOPOLL();
9858
9859     {
9860         BEGIN_PIN_PROFILER(CORProfilerPresent());
9861         GCX_PREEMP();
9862         if (CORProfilerTrackRemotingCookie())
9863         {
9864             g_profControlBlock.pProfInterface->GetGUID(pId);
9865             _ASSERTE(pId->Data1);
9866
9867             g_profControlBlock.pProfInterface->RemotingServerSendingReply(pId, fIsAsync);
9868         }
9869         else
9870         {
9871             g_profControlBlock.pProfInterface->RemotingServerSendingReply(NULL, fIsAsync);
9872         }
9873         END_PIN_PROFILER();
9874     }
9875
9876     HELPER_METHOD_FRAME_END_POLL();
9877 #endif // PROFILING_SUPPORTED
9878 }
9879 FCIMPLEND
9880
9881
9882 //*******************************************************************************************
9883 // These do a lot of work for us, setting up Frames, gathering arg info and resolving generics.
9884   //*******************************************************************************************
9885
9886 HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecificHandle)
9887 {
9888     FCALL_CONTRACT;
9889
9890 #ifdef PROFILING_SUPPORTED
9891
9892 #ifdef PROF_TEST_ONLY_FORCE_ELT
9893     // If this test-only flag is set, it's possible we might not have a profiler
9894     // attached, or might not have any of the hooks set. See
9895     // code:ProfControlBlock#TestOnlyELT
9896     if (g_profControlBlock.fTestOnlyForceEnterLeave)
9897     {
9898         if ((g_profControlBlock.pProfInterface.Load() == NULL) ||
9899             (
9900                 (g_profControlBlock.pProfInterface->GetEnterHook()          == NULL) &&
9901                 (g_profControlBlock.pProfInterface->GetEnter2Hook()         == NULL) &&
9902                 (g_profControlBlock.pProfInterface->GetEnter3Hook()         == NULL) &&
9903                 (g_profControlBlock.pProfInterface->GetEnter3WithInfoHook() == NULL)
9904             )
9905            )
9906         {
9907             return;
9908         }
9909     }       
9910 #endif // PROF_TEST_ONLY_FORCE_ELT
9911
9912     // ELT3 Fast-Path hooks should be NULL when ELT intermediary is used.
9913     _ASSERTE(g_profControlBlock.pProfInterface->GetEnter3Hook() == NULL);
9914     _ASSERTE(GetThread()->PreemptiveGCDisabled());
9915     _ASSERTE(platformSpecificHandle != NULL);
9916
9917     // Set up a frame
9918     HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_CAPTURE_DEPTH_2);
9919
9920     // Our contract is FCALL_CONTRACT, which is considered triggers if you set up a
9921     // frame, like we're about to do.
9922     SetCallbackStateFlagsHolder csf(
9923         COR_PRF_CALLBACKSTATE_INCALLBACK | COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE);
9924    
9925     COR_PRF_ELT_INFO_INTERNAL eltInfo;
9926     eltInfo.platformSpecificHandle = platformSpecificHandle;
9927
9928     //
9929     // CLR v4 Slow-Path ELT
9930     //
9931     if (g_profControlBlock.pProfInterface->GetEnter3WithInfoHook() != NULL)
9932     {
9933         FunctionIDOrClientID functionIDOrClientID;
9934         functionIDOrClientID.clientID = clientData;
9935         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
9936         g_profControlBlock.pProfInterface->GetEnter3WithInfoHook()(
9937             functionIDOrClientID, 
9938             (COR_PRF_ELT_INFO)&eltInfo);
9939         goto LExit;
9940     }
9941
9942     if (g_profControlBlock.pProfInterface->GetEnter2Hook() != NULL)
9943     {
9944         // We have run out of heap memory, so the content of the mapping table becomes stale.
9945         // All Whidbey ETL hooks must be turned off.
9946         if (!g_profControlBlock.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
9947         {
9948             goto LExit;
9949         }
9950
9951         // If ELT2 is in use, FunctionID will be returned to the JIT to be embedded into the ELT3 probes 
9952         // instead of using clientID because the profiler may map several functionIDs to a clientID to 
9953         // do things like code coverage analysis.  FunctionID to clientID has the one-on-one relationship, 
9954         // while the reverse may not have this one-on-one mapping.  Therefore, FunctionID is used as the 
9955         // key to retrieve the corresponding clientID from the internal FunctionID hash table.
9956         FunctionID functionId = clientData;
9957         _ASSERTE(functionId != NULL);
9958         clientData = g_profControlBlock.pProfInterface->LookupClientIDFromCache(functionId);
9959
9960         //
9961         // Whidbey Fast-Path ELT
9962         //
9963         if (CORProfilerELT2FastPathEnterEnabled())
9964         {
9965             REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
9966             g_profControlBlock.pProfInterface->GetEnter2Hook()(
9967                 functionId,
9968                 clientData, 
9969                 NULL,
9970                 NULL);
9971             goto LExit;
9972         }
9973
9974         //
9975         // Whidbey Slow-Path ELT
9976         //
9977         ProfileSetFunctionIDInPlatformSpecificHandle(platformSpecificHandle, functionId);
9978
9979         COR_PRF_FRAME_INFO frameInfo = NULL;
9980         COR_PRF_FUNCTION_ARGUMENT_INFO * pArgumentInfo = NULL;
9981         ULONG ulArgInfoSize = 0;
9982
9983         if (CORProfilerFunctionArgsEnabled())
9984         {
9985             // The loader won't trigger a GC or throw for already loaded argument types.
9986             ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
9987
9988             //
9989             // Find the method this is referring to, so we can get the signature
9990             //
9991             MethodDesc * pMethodDesc = FunctionIdToMethodDesc(functionId);
9992             MetaSig metaSig(pMethodDesc);
9993
9994             NewHolder<ProfileArgIterator> pProfileArgIterator;
9995
9996             {
9997                 // Can handle E_OUTOFMEMORY from ProfileArgIterator.
9998                 FAULT_NOT_FATAL();
9999
10000                 pProfileArgIterator = new (nothrow) ProfileArgIterator(&metaSig, platformSpecificHandle);
10001
10002                 if (pProfileArgIterator == NULL)
10003                 {
10004                     goto LExit;
10005                 }
10006             }
10007
10008             ULONG32 count = pProfileArgIterator->GetNumArgs();
10009
10010             if (metaSig.HasThis())
10011             {
10012                 count++;
10013             }
10014             
10015             ulArgInfoSize = sizeof(COR_PRF_FUNCTION_ARGUMENT_INFO) + count * sizeof(COR_PRF_FUNCTION_ARGUMENT_RANGE);
10016             pArgumentInfo = (COR_PRF_FUNCTION_ARGUMENT_INFO *)_alloca(ulArgInfoSize);
10017         }
10018
10019         HRESULT hr = ProfilingGetFunctionEnter3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo, &ulArgInfoSize, pArgumentInfo);
10020
10021         _ASSERTE(hr == S_OK);
10022         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10023         g_profControlBlock.pProfInterface->GetEnter2Hook()(functionId, clientData, frameInfo, pArgumentInfo);
10024
10025         goto LExit;
10026     }
10027
10028
10029     // We will not be here unless the jit'd or ngen'd function we're about to enter
10030     // was backpatched with this wrapper around the profiler's hook, and that
10031     // wouldn't have happened unless the profiler supplied us with a hook
10032     // in the first place.  (Note that SetEnterLeaveFunctionHooks* will return
10033     // an error unless it's called in the profiler's Initialize(), so a profiler can't change
10034     // its mind about where the hooks are.)
10035     _ASSERTE(g_profControlBlock.pProfInterface->GetEnterHook() != NULL);
10036
10037     // Note that we cannot assert CORProfilerTrackEnterLeave() (i.e., profiler flag
10038     // COR_PRF_MONITOR_ENTERLEAVE), because the profiler may decide whether
10039     // to enable the jitter to add enter/leave callouts independently of whether
10040     // the profiler actually has enter/leave hooks.  (If the profiler has no such hooks,
10041     // the callouts quickly return and do nothing.)
10042
10043     //
10044     // Everett ELT
10045     //
10046     {
10047         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10048         g_profControlBlock.pProfInterface->GetEnterHook()((FunctionID)clientData);
10049     }
10050
10051 LExit:
10052     ;
10053
10054     HELPER_METHOD_FRAME_END();      // Un-link the frame
10055
10056 #endif // PROFILING_SUPPORTED
10057 }
10058 HCIMPLEND
10059
10060 HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecificHandle)
10061 {
10062     FCALL_CONTRACT;
10063
10064     FC_GC_POLL_NOT_NEEDED();            // we pulse GC mode, so we are doing a poll
10065
10066 #ifdef PROFILING_SUPPORTED
10067
10068 #ifdef PROF_TEST_ONLY_FORCE_ELT
10069     // If this test-only flag is set, it's possible we might not have a profiler
10070     // attached, or might not have any of the hooks set. See
10071     // code:ProfControlBlock#TestOnlyELT
10072     if (g_profControlBlock.fTestOnlyForceEnterLeave)
10073     {
10074         if ((g_profControlBlock.pProfInterface.Load() == NULL) ||
10075             (
10076                 (g_profControlBlock.pProfInterface->GetLeaveHook()          == NULL) &&
10077                 (g_profControlBlock.pProfInterface->GetLeave2Hook()         == NULL) &&
10078                 (g_profControlBlock.pProfInterface->GetLeave3Hook()         == NULL) &&
10079                 (g_profControlBlock.pProfInterface->GetLeave3WithInfoHook() == NULL)
10080             )
10081            )
10082         {
10083             return;
10084         }
10085     }
10086 #endif // PROF_TEST_ONLY_FORCE_ELT
10087
10088     // ELT3 Fast-Path hooks should be NULL when ELT intermediary is used.
10089     _ASSERTE(g_profControlBlock.pProfInterface->GetLeave3Hook() == NULL);
10090     _ASSERTE(GetThread()->PreemptiveGCDisabled());
10091     _ASSERTE(platformSpecificHandle != NULL);
10092
10093     // Set up a frame
10094     HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_CAPTURE_DEPTH_2); 
10095
10096     // Our contract is FCALL_CONTRACT, which is considered triggers if you set up a
10097     // frame, like we're about to do.
10098     SetCallbackStateFlagsHolder csf(
10099         COR_PRF_CALLBACKSTATE_INCALLBACK | COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE);
10100     
10101     COR_PRF_ELT_INFO_INTERNAL eltInfo;
10102     eltInfo.platformSpecificHandle = platformSpecificHandle;
10103     
10104     //
10105     // CLR v4 Slow-Path ELT
10106     //
10107     if (g_profControlBlock.pProfInterface->GetLeave3WithInfoHook() != NULL)
10108     {
10109         FunctionIDOrClientID functionIDOrClientID;
10110         functionIDOrClientID.clientID = clientData;
10111         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10112         g_profControlBlock.pProfInterface->GetLeave3WithInfoHook()(
10113             functionIDOrClientID, 
10114             (COR_PRF_ELT_INFO)&eltInfo);
10115         goto LExit;
10116     }
10117
10118     if (g_profControlBlock.pProfInterface->GetLeave2Hook() != NULL)
10119     {
10120         // We have run out of heap memory, so the content of the mapping table becomes stale.
10121         // All Whidbey ETL hooks must be turned off.
10122         if (!g_profControlBlock.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
10123         {
10124             goto LExit;
10125         }
10126
10127         // If ELT2 is in use, FunctionID will be returned to the JIT to be embedded into the ELT3 probes 
10128         // instead of using clientID because the profiler may map several functionIDs to a clientID to 
10129         // do things like code coverage analysis.  FunctionID to clientID has the one-on-one relationship, 
10130         // while the reverse may not have this one-on-one mapping.  Therefore, FunctionID is used as the 
10131         // key to retrieve the corresponding clientID from the internal FunctionID hash table.
10132         FunctionID functionId = clientData;
10133         _ASSERTE(functionId != NULL);
10134         clientData = g_profControlBlock.pProfInterface->LookupClientIDFromCache(functionId);
10135
10136         //
10137         // Whidbey Fast-Path ELT
10138         //
10139         if (CORProfilerELT2FastPathLeaveEnabled())
10140         {
10141             REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10142             g_profControlBlock.pProfInterface->GetLeave2Hook()(
10143                 functionId,
10144                 clientData, 
10145                 NULL,
10146                 NULL);
10147             goto LExit;
10148         }
10149
10150         //
10151         // Whidbey Slow-Path ELT
10152         //
10153         COR_PRF_FRAME_INFO frameInfo = NULL;
10154         COR_PRF_FUNCTION_ARGUMENT_RANGE argumentRange;
10155
10156         HRESULT hr = ProfilingGetFunctionLeave3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo, &argumentRange);
10157         _ASSERTE(hr == S_OK);
10158
10159         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10160         g_profControlBlock.pProfInterface->GetLeave2Hook()(functionId, clientData, frameInfo, &argumentRange);
10161         goto LExit;
10162     }
10163
10164     // We will not be here unless the jit'd or ngen'd function we're about to leave
10165     // was backpatched with this wrapper around the profiler's hook, and that
10166     // wouldn't have happened unless the profiler supplied us with a hook
10167     // in the first place.  (Note that SetEnterLeaveFunctionHooks* will return
10168     // an error unless it's called in the profiler's Initialize(), so a profiler can't change
10169     // its mind about where the hooks are.)
10170     _ASSERTE(g_profControlBlock.pProfInterface->GetLeaveHook() != NULL);
10171
10172     // Note that we cannot assert CORProfilerTrackEnterLeave() (i.e., profiler flag
10173     // COR_PRF_MONITOR_ENTERLEAVE), because the profiler may decide whether
10174     // to enable the jitter to add enter/leave callouts independently of whether
10175     // the profiler actually has enter/leave hooks.  (If the profiler has no such hooks,
10176     // the callouts quickly return and do nothing.)
10177
10178     //
10179     // Everett ELT
10180     //
10181     {
10182         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10183         g_profControlBlock.pProfInterface->GetLeaveHook()((FunctionID)clientData);
10184     }
10185
10186 LExit:
10187
10188     ;
10189
10190     HELPER_METHOD_FRAME_END();      // Un-link the frame
10191
10192 #endif // PROFILING_SUPPORTED
10193 }
10194 HCIMPLEND
10195
10196 HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpecificHandle)
10197 {
10198     FCALL_CONTRACT;
10199
10200     FC_GC_POLL_NOT_NEEDED();            // we pulse GC mode, so we are doing a poll
10201
10202 #ifdef PROFILING_SUPPORTED
10203
10204 #ifdef PROF_TEST_ONLY_FORCE_ELT
10205     // If this test-only flag is set, it's possible we might not have a profiler
10206     // attached, or might not have any of the hooks set. See
10207     // code:ProfControlBlock#TestOnlyELT
10208     if (g_profControlBlock.fTestOnlyForceEnterLeave)
10209     {
10210         if ((g_profControlBlock.pProfInterface.Load() == NULL) ||
10211             (
10212                 (g_profControlBlock.pProfInterface->GetTailcallHook()          == NULL) &&
10213                 (g_profControlBlock.pProfInterface->GetTailcall2Hook()         == NULL) &&
10214                 (g_profControlBlock.pProfInterface->GetTailcall3Hook()         == NULL) &&
10215                 (g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook() == NULL)
10216             )
10217            )
10218         {
10219             return;
10220         }
10221     }
10222 #endif // PROF_TEST_ONLY_FORCE_ELT
10223
10224     // ELT3 fast-path hooks should be NULL when ELT intermediary is used.
10225     _ASSERTE(g_profControlBlock.pProfInterface->GetTailcall3Hook() == NULL);
10226     _ASSERTE(GetThread()->PreemptiveGCDisabled());
10227     _ASSERTE(platformSpecificHandle != NULL);
10228
10229     // Set up a frame
10230     HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_CAPTURE_DEPTH_2);
10231
10232     // Our contract is FCALL_CONTRACT, which is considered triggers if you set up a
10233     // frame, like we're about to do.
10234     SetCallbackStateFlagsHolder csf(
10235         COR_PRF_CALLBACKSTATE_INCALLBACK | COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE);
10236     
10237     COR_PRF_ELT_INFO_INTERNAL eltInfo;
10238     eltInfo.platformSpecificHandle = platformSpecificHandle;
10239
10240     //
10241     // CLR v4 Slow-Path ELT
10242     //
10243     if (g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook() != NULL)
10244     {
10245         FunctionIDOrClientID functionIDOrClientID;
10246         functionIDOrClientID.clientID = clientData;
10247         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10248         g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook()(
10249             functionIDOrClientID, 
10250             (COR_PRF_ELT_INFO)&eltInfo);
10251         goto LExit;
10252     }
10253
10254     if (g_profControlBlock.pProfInterface->GetTailcall2Hook() != NULL)
10255     {
10256         // We have run out of heap memory, so the content of the mapping table becomes stale.
10257         // All Whidbey ETL hooks must be turned off.
10258         if (!g_profControlBlock.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
10259         {
10260             goto LExit;
10261         }
10262
10263         // If ELT2 is in use, FunctionID will be returned to the JIT to be embedded into the ELT3 probes 
10264         // instead of using clientID because the profiler may map several functionIDs to a clientID to 
10265         // do things like code coverage analysis.  FunctionID to clientID has the one-on-one relationship, 
10266         // while the reverse may not have this one-on-one mapping.  Therefore, FunctionID is used as the 
10267         // key to retrieve the corresponding clientID from the internal FunctionID hash table.
10268         FunctionID functionId = clientData;
10269         _ASSERTE(functionId != NULL);
10270         clientData = g_profControlBlock.pProfInterface->LookupClientIDFromCache(functionId);
10271
10272         //
10273         // Whidbey Fast-Path ELT
10274         //
10275         if (CORProfilerELT2FastPathTailcallEnabled())
10276         {
10277             REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10278             g_profControlBlock.pProfInterface->GetTailcall2Hook()(
10279                 functionId,
10280                 clientData, 
10281                 NULL);
10282             goto LExit;
10283         }
10284
10285         //
10286         // Whidbey Slow-Path ELT
10287         //
10288         COR_PRF_FRAME_INFO frameInfo = NULL;
10289
10290         HRESULT hr = ProfilingGetFunctionTailcall3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo);
10291         _ASSERTE(hr == S_OK);
10292
10293         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10294         g_profControlBlock.pProfInterface->GetTailcall2Hook()(functionId, clientData, frameInfo);
10295         goto LExit;
10296     }
10297
10298     // We will not be here unless the jit'd or ngen'd function we're about to tailcall
10299     // was backpatched with this wrapper around the profiler's hook, and that
10300     // wouldn't have happened unless the profiler supplied us with a hook
10301     // in the first place.  (Note that SetEnterLeaveFunctionHooks* will return
10302     // an error unless it's called in the profiler's Initialize(), so a profiler can't change
10303     // its mind about where the hooks are.)
10304     _ASSERTE(g_profControlBlock.pProfInterface->GetTailcallHook() != NULL);
10305
10306     // Note that we cannot assert CORProfilerTrackEnterLeave() (i.e., profiler flag
10307     // COR_PRF_MONITOR_ENTERLEAVE), because the profiler may decide whether
10308     // to enable the jitter to add enter/leave callouts independently of whether
10309     // the profiler actually has enter/leave hooks.  (If the profiler has no such hooks,
10310     // the callouts quickly return and do nothing.)
10311     
10312     //
10313     // Everett ELT
10314     //
10315     {
10316         REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
10317         g_profControlBlock.pProfInterface->GetTailcallHook()((FunctionID)clientData);
10318     }
10319
10320 LExit:
10321
10322     ;
10323
10324     HELPER_METHOD_FRAME_END();      // Un-link the frame
10325
10326 #endif // PROFILING_SUPPORTED
10327 }
10328 HCIMPLEND
10329