Exemplo n.º 1
0
ULONG EtpStopEtwRundownSession(
    VOID
    )
{
    EtpRundownTraceProperties->LogFileNameOffset = 0;
    return ControlTrace(0, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties, EVENT_TRACE_CONTROL_STOP);
}
Exemplo n.º 2
0
ULONG StartDotNetTrace(
    __in PASMPAGE_CONTEXT Context,
    __out PTRACEHANDLE SessionHandle,
    __out PEVENT_TRACE_PROPERTIES *Properties
    )
{
    ULONG result;
    ULONG bufferSize;
    PEVENT_TRACE_PROPERTIES properties;
    TRACEHANDLE sessionHandle;

    bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + DotNetLoggerName.Length + sizeof(WCHAR);
    properties = PhAllocate(bufferSize);
    memset(properties, 0, sizeof(EVENT_TRACE_PROPERTIES));

    properties->Wnode.BufferSize = bufferSize;
    properties->Wnode.ClientContext = 2; // System time clock resolution
    properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY;
    properties->LogFileNameOffset = 0;
    properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);

    result = StartTrace(&sessionHandle, DotNetLoggerName.Buffer, properties);

    if (result == 0)
    {
        *SessionHandle = sessionHandle;
        *Properties = properties;

        return 0;
    }
    else if (result == ERROR_ALREADY_EXISTS)
    {
        // Session already exists, so use that. Get the existing session handle.

        result = ControlTrace(0, DotNetLoggerName.Buffer, properties, EVENT_TRACE_CONTROL_QUERY);

        if (result != 0)
        {
            PhFree(properties);
            return result;
        }

        *SessionHandle = properties->Wnode.HistoricalContext;
        *Properties = properties;

        return 0;
    }
    else
    {
        PhFree(properties);

        return result;
    }
}
Exemplo n.º 3
0
AMDTResult tpCollectImpl::tpStopThreadProfile()
{
    AMDTResult retVal = AMDT_STATUS_OK;
    ULONG status = ERROR_SUCCESS;

    //if (!tpIsProfileInitialized())
    //{
    //    retVal = AMDT_ERROR_PROFILE_NOT_CONFIGURED;
    //}

    if (!tpIsProfileRunning())
    {
        retVal = AMDT_ERROR_PROFILE_NOT_STARTED;
    }

    PEVENT_TRACE_PROPERTIES pSessionProperties = m_pSessionProperties;
    bool isCollectCStack = m_callstack;

    if (NULL == pSessionProperties)
    {
        retVal = AMDT_ERROR_INTERNAL;
    }

    //fprintf(stderr, "tpStopThreadProfile .. retVal(%lx), state(%u)\n", retVal, m_tpState);

    if (AMDT_STATUS_OK == retVal)
    {
        // To disable stack tracing, call this function with InformationClass set to TraceStackTracingInfo
        // and InformationLength set to 0
        if (isCollectCStack)
        {
            status = TraceSetInformation(m_sessionHandle, TraceStackTracingInfo, NULL, 0);
            fprintf(stderr, "Disable stack tracing - TraceSetInformation() status(%lu)\n", status);
        }

        status = ControlTrace(m_sessionHandle,
                              KERNEL_LOGGER_NAME,
                              pSessionProperties,
                              EVENT_TRACE_CONTROL_STOP);

        //fprintf(stderr, "ControlTrace(stop) status(%lu)\n", status);

        if (ERROR_SUCCESS != status)
        {
            // FIXME: what to do if it fails
            fprintf(stderr, "ControlTrace(stop) failed with %lu\n", status);
        }

        // TODO: set this only is top succeeds
        m_tpState = AMDT_THREAD_PROFILE_STATE_UNINITIALIZED;
        status = tpClear();
    }

    return status;
} // tpStopThreadProfile
Exemplo n.º 4
0
FORCEINLINE
VOID
StopTraceListening (
    __in TRACEHANDLE SessionHandle,
    __inout PTRACE_PROPERTIES Properties,
    __in TRACEHANDLE ConsumingHandle
    )
{
    ControlTrace(SessionHandle, LOGGER_NAME, &Properties->TraceProperties, EVENT_TRACE_CONTROL_STOP);
    CloseTrace(ConsumingHandle);
}
Exemplo n.º 5
0
ULONG EtpControlEtwSession(
    _In_ ULONG ControlCode
    )
{
    // If we have a session handle, we use that instead of the logger name.

    EtpTraceProperties->LogFileNameOffset = 0; // make sure it is 0, otherwise ControlTrace crashes

    return ControlTrace(
        EtpStartedSession ? EtpSessionHandle : 0,
        EtpStartedSession ? NULL : EtpActualKernelLoggerName->Buffer,
        EtpTraceProperties,
        ControlCode
        );
}
Exemplo n.º 6
0
ULONG UpdateDotNetTraceInfo(
    _In_ PASMPAGE_QUERY_CONTEXT Context,
    _In_ BOOLEAN ClrV2
    )
{
    static _EnableTraceEx EnableTraceEx_I = NULL;

    ULONG result;
    TRACEHANDLE sessionHandle;
    PEVENT_TRACE_PROPERTIES properties;
    PGUID guidToEnable;

    if (!EnableTraceEx_I)
        EnableTraceEx_I = PhGetModuleProcAddress(L"advapi32.dll", "EnableTraceEx");
    if (!EnableTraceEx_I)
        return ERROR_NOT_SUPPORTED;

    result = StartDotNetTrace(&sessionHandle, &properties);

    if (result != 0)
        return result;

    if (!ClrV2)
        guidToEnable = &ClrRundownProviderGuid;
    else
        guidToEnable = &ClrRuntimeProviderGuid;

    EnableTraceEx_I(
        guidToEnable,
        NULL,
        sessionHandle,
        1,
        TRACE_LEVEL_INFORMATION,
        CLR_LOADER_KEYWORD | CLR_STARTENUMERATION_KEYWORD,
        0,
        0,
        NULL
        );

    result = ProcessDotNetTrace(Context);

    ControlTrace(sessionHandle, NULL, properties, EVENT_TRACE_CONTROL_STOP);
    PhFree(properties);

    return result;
}
Exemplo n.º 7
0
bool ETW::Stop()
{
	if (isActive)
	{
		ULONG controlTraceResult = ControlTrace(openedHandle, KERNEL_LOGGER_NAME, sessionProperties, EVENT_TRACE_CONTROL_STOP);

		// ERROR_CTX_CLOSE_PENDING(7007L): The call was successful. The ProcessTrace function will stop after it has processed all real-time events in its buffers (it will not receive any new events).
		// ERROR_BUSY(170L): Prior to Windows Vista, you cannot close the trace until the ProcessTrace function completes.
		// ERROR_INVALID_HANDLE(6L): One of the following is true: TraceHandle is NULL. TraceHandle is INVALID_HANDLE_VALUE.
		ULONG closeTraceStatus = CloseTrace(openedHandle);

		// Wait for ProcessThread to finish
		WaitForSingleObject(processThreadHandle, INFINITE);
		BOOL wasThreadClosed = CloseHandle(processThreadHandle);

		isActive = false;

		return wasThreadClosed && closeTraceStatus == ERROR_SUCCESS && controlTraceResult == ERROR_SUCCESS;
	}

	return false;
}
Exemplo n.º 8
0
NTSTATUS UpdateDotNetTraceInfoThreadStart(
    _In_ PVOID Parameter
    )
{
    PASMPAGE_QUERY_CONTEXT context = Parameter;
    TRACEHANDLE sessionHandle;
    PEVENT_TRACE_PROPERTIES properties;
    PGUID guidToEnable;

    context->TraceResult = StartDotNetTrace(&sessionHandle, &properties);

    if (context->TraceResult != 0)
        return context->TraceResult;

    if (!context->TraceClrV2)
        guidToEnable = &ClrRundownProviderGuid;
    else
        guidToEnable = &ClrRuntimeProviderGuid;

    EnableTraceEx(
        guidToEnable,
        NULL,
        sessionHandle,
        1,
        TRACE_LEVEL_INFORMATION,
        CLR_LOADER_KEYWORD | CLR_STARTENUMERATION_KEYWORD,
        0,
        0,
        NULL
        );

    context->TraceResult = ProcessDotNetTrace(context);

    ControlTrace(sessionHandle, NULL, properties, EVENT_TRACE_CONTROL_STOP);
    PhFree(properties);

    return context->TraceResult;
}
Exemplo n.º 9
0
int
__cdecl
wmain()
{
    CLASSIC_EVENT_ID EventId[2];
    ULONG Status = ERROR_SUCCESS;
    TRACEHANDLE SessionHandle = 0;
    PEVENT_TRACE_PROPERTIES TraceProperties;
    BOOLEAN TraceStarted = FALSE;
    ULONG SystemTraceFlags[8];
    PWSTR LoggerName = L"MyTrace";

    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);

    //
    // Allocate EVENT_TRACE_PROPERTIES structure and perform some
    // basic initialization. 
    //
    // N.B. LoggerName will be populated during StartTrace call.
    //

    TraceProperties = AllocateTraceProperties(NULL, L"SystemTrace.etl");
    if (TraceProperties == NULL) {
        Status = ERROR_OUTOFMEMORY;
        goto Exit;
    }

    //
    // Configure additinal trace settings.
    //

    TraceProperties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL | EVENT_TRACE_SYSTEM_LOGGER_MODE;
    TraceProperties->Wnode.ClientContext = 1; // Use QueryPerformanceCounter for time stamps
    TraceProperties->MaximumFileSize = 100; // Limit file size to 100MB max
    TraceProperties->BufferSize = 512; // Use 512KB trace buffers
    TraceProperties->MinimumBuffers = 64;
    TraceProperties->MaximumBuffers = 128;
    
    //
    // Start trace session which can receive events from SystemTraceProvider.
    //
    
    Status = StartTrace(&SessionHandle, LoggerName, TraceProperties);
    if (Status != ERROR_SUCCESS) {
        wprintf(L"StartTrace() failed with %lu\n", Status);
        goto Exit;
    }

    TraceStarted = TRUE;

    //
    // Configure stack walking. In this example stack traces will be collected on
    // ImageLoad and ProcessCreate events.
    //
    // N.B. Stack tracing is configured before enabling event collection.
    //    
    
    ZeroMemory(EventId, sizeof(EventId));
    EventId[0].EventGuid = ImageLoadGuid;
    EventId[0].Type =  EVENT_TRACE_TYPE_LOAD;
    EventId[1].EventGuid = ProcessGuid;
    EventId[1].Type = EVENT_TRACE_TYPE_START;
    
    Status = TraceSetInformation(SessionHandle,
                                 TraceStackTracingInfo,
                                 EventId,
                                 sizeof(EventId));

    if (Status != ERROR_SUCCESS) {
        wprintf(L"TraceSetInformation(StackTracing) failed with %lu\n", Status);
        goto Exit;
    }
    
    //
    // Enable system events for Process, Thread and Loader groups.
    //

    ZeroMemory(SystemTraceFlags, sizeof(SystemTraceFlags));
    SystemTraceFlags[0] = (EVENT_TRACE_FLAG_PROCESS | 
                           EVENT_TRACE_FLAG_THREAD |
                           EVENT_TRACE_FLAG_IMAGE_LOAD);
    
    Status = TraceSetInformation(SessionHandle, 
                                 TraceSystemTraceEnableFlagsInfo,
                                 SystemTraceFlags,
                                 sizeof(SystemTraceFlags));
    
    if (Status != ERROR_SUCCESS) {
        wprintf(L"TraceSetInformation(EnableFlags) failed with %lu\n", Status);
        goto Exit;
    }
    
    //
    // Collect trace for 30 seconds.
    //

    Sleep(30 * 1000);

Exit:

    //
    // Stop tracing.
    //

    if (TraceStarted != FALSE) {
        Status = ControlTrace(SessionHandle, NULL, TraceProperties, EVENT_TRACE_CONTROL_STOP);  
        if (Status != ERROR_SUCCESS) {
            wprintf(L"StopTrace() failed with %lu\n", Status);
        }
    }

    if (TraceProperties != NULL) {
        FreeTraceProperties(TraceProperties);
    }

    return Status;
}
Exemplo n.º 10
0
AMDTResult tpCollectImpl::tpStartThreadProfile()
{
    AMDTResult retVal = AMDT_STATUS_OK;
    ULONG status;

    if (!tpIsProfileInitialized())
    {
        retVal = AMDT_ERROR_PROFILE_NOT_CONFIGURED;
    }

    if (tpIsProfileRunning())
    {
        retVal = AMDT_ERROR_PROFILE_ALREADY_STARTED;
    }

    PTRACEHANDLE pSessionHandle = &m_sessionHandle;
    PEVENT_TRACE_PROPERTIES pSessionProperties = m_pSessionProperties;
    bool isCollectCStack = m_callstack;

    if (NULL == pSessionProperties)
    {
        retVal = AMDT_ERROR_INTERNAL;
    }

    if (AMDT_STATUS_OK == retVal)
    {
        // Create the trace session.
        status = StartTrace(pSessionHandle, KERNEL_LOGGER_NAME, pSessionProperties);

        if (ERROR_SUCCESS == status)
        {
            // StartTrace succeeded.

            // Events in "NT Kernel Logger",
            // - EVENT_TRACE_FLAG_THREAD
            //      - Supported Event Type
            //        1   - EVENT_TRACE_TYPE_START Start thread event. The Thread_V2_TypeGroup1 MOF class defines the
            //              event data for this event
            //        2   - EVENT_TRACE_TYPE_END End thread event. The Thread_V2_TypeGroup1 MOF class defines the
            //              event data for this event
            //       36   - Context switch event. The CSwitch MOF class defines the event data for this event
            //       50   - Ready thread event. The ReadyThread MOF class defines the event data for this event
            //
            // - EVENT_TRACE_FLAG_IMAGE_LOAD
            //      - Supported Event Type
            //        10   - EVENT_TRACE_TYPE_LOAD Image load event. Generated when a DLL or executable file is loaded.
            //               The provider generates only one event for the first time a given DLL is loaded.
            //               The Image_Load MOF class defines the event data for this event
            //        2    - EVENT_TRACE_TYPE_END End thread event. Image unload event. Generated when a DLL or executable
            //               file is unloaded. The provider generates only one event for the last time a given DLL is unloaded.
            //               The Image_Load MOF class defines the event data for this event
            //
            // - EVENT_TRACE_FLAG_CSWITCH
            //      - Enables the following *Thread* event type - CSWITCH
            //        FIXME: Do i need to enable EVENT_TRACE_FLAG_THREAD or just enabling EVENT_TRACE_FLAG_CSWITCH is enough?
            //

            // StackWalk_Event class will have the stack data
            //  https://msdn.microsoft.com/en-us/library/windows/desktop/dd392323(v=vs.85).aspx
            //  CLASSIC_EVENT_ID traceCSForClasses[] = { { PerfInfoGuid, 46, { 0 } },
            //                                         { ThreadGuid, 36, { 0 } },
            //                                         { ThreadGuid, 50, { 0 } } };

            if (isCollectCStack)
            {
                CLASSIC_EVENT_ID traceCallStackForClasses[] =
                {
                    //{ g_threadGuid, 1, { 0 } },   // Start Thread Event
                    //{ g_threadGuid, 2, { 0 } },   // End Thread Event
                    { g_threadGuid, 36, { 0 } },  // Context Switch Event
                    //{ g_threadGuid, 50, { 0 } }   // Ready Thread Event
                };

                status = TraceSetInformation(*pSessionHandle,
                                             TraceStackTracingInfo,
                                             traceCallStackForClasses,
                                             sizeof(traceCallStackForClasses));

                if (ERROR_SUCCESS != status)
                {
                    retVal = AMDT_ERROR_INTERNAL;
                    fprintf(stderr, "TraceSetInformation() status(%lu)\n", status);
                }
            }
        }
        else if (ERROR_ALREADY_EXISTS == status)
        {
            retVal = AMDT_ERROR_PROFILE_SESSION_EXISTS;

            fprintf(stderr, "The NT Kernel Logger session is already in use.\n");

            // TODO: Use ControlTrace() to update
            status = ControlTraceW(0, KERNEL_LOGGER_NAME, pSessionProperties, EVENT_TRACE_CONTROL_UPDATE);
            fprintf(stderr, "ControlTraceW status(%lu).\n", status);

            if (ERROR_SUCCESS == status)
            {
                retVal = AMDT_STATUS_OK;
            }
            else
            {
                // FIXME: just for testing purpose
                status = ControlTrace(m_sessionHandle,
                                      KERNEL_LOGGER_NAME,
                                      pSessionProperties,
                                      EVENT_TRACE_CONTROL_STOP);
            }
        }
        else
        {
            retVal = AMDT_ERROR_INTERNAL;
            fprintf(stderr, "StartTrace() failed with %lu\n", status);
        }
    }

    if (AMDT_STATUS_OK == retVal)
    {
        m_tpState = AMDT_THREAD_PROFILE_STATE_STARTED;
    }

    return retVal;
} // tpStartThreadProfile