///////////////////////////////////////////////////////////////////////////////// #region AppDomain EventHandler (ProcessExit / DomainUnload) private static void NativeStack_Exited( object sender, EventArgs e ) { lock (syncRoot) /* TRANSACTIONAL */ { if (ThreadContextBuffer != UIntPtr.Zero) { Marshal.FreeCoTaskMem(ConversionOps.ToIntPtr( ThreadContextBuffer)); ThreadContextBuffer = UIntPtr.Zero; AppDomain appDomain = AppDomainOps.GetCurrent(); if (appDomain != null) { if (!AppDomainOps.IsDefault(appDomain)) { appDomain.DomainUnload -= NativeStack_Exited; } else { appDomain.ProcessExit -= NativeStack_Exited; } } } } }
/////////////////////////////////////////////////////////////////////// public static Assembly FindInAppDomain( AppDomain appDomain, AssemblyName assemblyName ) { if (assemblyName != null) { if (appDomain == null) { appDomain = AppDomainOps.GetCurrent(); } if (appDomain != null) { Assembly[] assemblies = appDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly == null) { continue; } if (IsSameAssemblyName( assembly.GetName(), assemblyName)) { return(assembly); } } } } return(null); }
/////////////////////////////////////////////////////////////////////// public static Assembly FindInAppDomain( AppDomain appDomain, string name, Version version, byte[] publicKeyToken, ref Result error ) { if (appDomain == null) { appDomain = AppDomainOps.GetCurrent(); } if (appDomain != null) { Assembly[] assemblies = appDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly == null) { continue; } AssemblyName assemblyName = assembly.GetName(); if (assemblyName == null) { continue; } if ((name != null) && !String.Equals( assemblyName.Name, name, StringOps.SystemStringComparisonType)) { continue; } if ((version != null) && (PackageOps.VersionCompare( assemblyName.Version, version) != 0)) { continue; } if ((publicKeyToken != null) && !ArrayOps.Equals( assemblyName.GetPublicKeyToken(), publicKeyToken)) { continue; } return(assembly); } } error = "assembly not found in application domain"; return(null); }
public static void DebugTrace( int?threadId, string message, string category, TracePriority priority ) { if (!IsTracePossible()) { return; } if (!IsTraceEnabled(priority)) /* HACK: *PERF* Bail. */ { return; } string traceFormat = GetTraceFormat(); if (traceFormat == null) { return; } bool traceDateTime; bool tracePriority; bool traceAppDomain; bool traceInterpreter; bool traceThreadId; bool traceMethod; GetTraceFormatFlags( out traceDateTime, out tracePriority, out traceAppDomain, out traceInterpreter, out traceThreadId, out traceMethod); string methodName = null; DebugTraceRaw(FormatOps.TraceOutput(traceFormat, traceDateTime ? (DateTime?)TimeOps.GetNow() : null, tracePriority ? (TracePriority?)priority : null, traceAppDomain ? AppDomainOps.GetCurrent() : null, traceInterpreter ? Interpreter.GetActive() : null, traceThreadId ? threadId : null, message, traceMethod, ref methodName), category, methodName, priority); }
public static void DebugWriteTo( Interpreter interpreter, string value, bool force ) { if (!IsTracePossible()) { return; } string traceFormat = GetTraceFormat(); if (traceFormat == null) { return; } bool traceDateTime; bool tracePriority; bool traceAppDomain; bool traceInterpreter; bool traceThreadId; bool traceMethod; GetTraceFormatFlags( out traceDateTime, out tracePriority, out traceAppDomain, out traceInterpreter, out traceThreadId, out traceMethod); DebugOps.WriteTo(interpreter, FormatOps.TraceOutput(traceFormat, traceDateTime ? (DateTime?)TimeOps.GetNow() : null, null, traceAppDomain ? AppDomainOps.GetCurrent() : null, traceInterpreter ? interpreter : null, traceThreadId ? (int?)GlobalState.GetCurrentSystemThreadId() : null, value, traceMethod), force); }
/////////////////////////////////////////////////////////////////////// #region Tracing Support Methods private static bool IsTracePossible() { /* NO-LOCK */ return(isTracePossible && !AppDomainOps.IsCurrentFinalizing()); }
///////////////////////////////////////////////////////////////////////////////// private static UIntPtr GetNativeRegister( IntPtr thread, uint flags, int offset, int size ) { // // NOTE: Are we able to query the thread context (i.e. we know // what platform we are on and the appropriate constants // have been setup)? // if (!CanQueryThread) { if (Interlocked.Increment(ref CannotQueryThread) == 1) { TraceOps.DebugTrace( "GetNativeRegister: cannot query thread", typeof(NativeStack).Name, TracePriority.NativeError); } return(UIntPtr.Zero); } // // NOTE: We do not allow anybody to attempt to read outside what // we think the bounds of the CONTEXT structure are. // if ((offset < 0) || (offset > (CONTEXT_SIZE - IntPtr.Size))) { return(UIntPtr.Zero); } try { lock (syncRoot) /* TRANSACTIONAL */ { // // NOTE: Perform one-time allocation of the fixed-size // thread context buffer, on demand and schedule // to have it freed prior to process exit. // if (ThreadContextBuffer == UIntPtr.Zero) { // // NOTE: Schedule the fixed-size thread context // buffer to be freed either upon the // AppDomain being unloaded (if we are not // in the default AppDomain) or when the // process exits. This should gracefully // handle both embedding and stand-alone // scenarios. // AppDomain appDomain = AppDomainOps.GetCurrent(); if (appDomain != null) { if (!AppDomainOps.IsDefault(appDomain)) { appDomain.DomainUnload += NativeStack_Exited; } else { appDomain.ProcessExit += NativeStack_Exited; } } // // NOTE: Now that we are sure that we have // succeeded in scheduling the cleanup for // this buffer, allocate it. // // NOTE: For safety, we now allocate at least a // whole page for this buffer. // // ThreadContextBuffer = ConversionOps.ToUIntPtr( // Marshal.AllocCoTaskMem((int)CONTEXT_SIZE)); // ThreadContextBuffer = ConversionOps.ToUIntPtr( Marshal.AllocCoTaskMem((int)Math.Max( CONTEXT_SIZE, PlatformOps.GetPageSize()))); } // // NOTE: Make sure we were able to allocate the // thread context buffer. // if (ThreadContextBuffer == UIntPtr.Zero) { return(UIntPtr.Zero); } // // NOTE: Internally convert our buffer UIntPtr to // IntPtr, as required by Marshal class. // This is absolutely required because // otherwise we end up calling the generic // version of the WriteInt32 and ReadInt32 // methods (that take an object instead of // an IntPtr) and getting the wrong results. // IntPtr threadContext = ConversionOps.ToIntPtr( ThreadContextBuffer); // // NOTE: Write flags that tell GetThreadContext // which fields of the thread context buffer // we would like it to populate. For now, // we mainly want to support the control // registers (primarily for ESP and EBP). // Marshal.WriteInt32( threadContext, (int)CONTEXT_FLAGS_OFFSET, (int)flags); // // NOTE: Query the Win32 API to obtain the // requested thread context. In theory, // this could fail or throw an exception // at this point. In that case, we would // return zero from this function and the // stack checking code would assume that // native stack checking is unavailable // and should not be relied upon. // if (UnsafeNativeMethods.GetThreadContext( thread, threadContext)) { if (size == IntPtr.Size) { return(ConversionOps.ToUIntPtr( Marshal.ReadIntPtr(threadContext, offset))); } else { switch (size) { case sizeof(long): { return(ConversionOps.ToUIntPtr( Marshal.ReadInt64(threadContext, offset))); } case sizeof(int): { return(ConversionOps.ToUIntPtr( Marshal.ReadInt32(threadContext, offset))); } case sizeof(short): { return(ConversionOps.ToUIntPtr( Marshal.ReadInt16(threadContext, offset))); } case sizeof(byte): { return(ConversionOps.ToUIntPtr( Marshal.ReadByte(threadContext, offset))); } } } } } } catch (Exception e) { if (Interlocked.Increment(ref ContextException) == 1) { TraceOps.DebugTrace( e, typeof(NativeStack).Name, TracePriority.NativeError); } } return(UIntPtr.Zero); }