Przeglądaj źródła

[MERGE #4314 @MSLaguana] Add support for emitting ETW events to LTTng

Merge pull request #4314 from MSLaguana:lttng

We define a number of ETW events on windows that we can emit for diagnostics purposes. With these changes, we support generating LTTng bindings for these same events so the same diagnostics approach can be used on linux and osx.

The script that generates the LTTng bindings from the ETW manifest is based on a similar script used by the dotnet team (see https://github.com/dotnet/coreclr/blob/master/src/scripts/genXplatLttng.py), but I have attempted to simplify it and adapt it for our purposes.
Jimmy Thomson 8 lat temu
rodzic
commit
88ebe68372

+ 16 - 0
CMakeLists.txt

@@ -491,5 +491,21 @@ add_definitions(
     -DNO_PAL_MINMAX
     -DNO_PAL_MINMAX
     -DPAL_STDCPP_COMPAT
     -DPAL_STDCPP_COMPAT
     )
     )
+
+if (ENABLE_JS_LTTNG_SH)
+    unset(ENABLE_JS_LTTNG_SH CACHE)
+    include_directories (
+      ${CMAKE_CURRENT_SOURCE_DIR}/out/lttng
+    )
+    add_subdirectory ($ENV{TARGET_PATH}/lttng ${CMAKE_CURRENT_BINARY_DIR}/lttng)
+
+    add_definitions(
+      -DENABLE_JS_ETW
+      -DENABLE_JS_LTTNG
+    )
+    set(USE_LTTNG "1")
+endif()
+
 add_subdirectory (lib)
 add_subdirectory (lib)
+
 add_subdirectory (bin)
 add_subdirectory (bin)

+ 1 - 1
bin/GCStress/StubExternalApi.cpp

@@ -21,7 +21,7 @@ void ConfigParserAPI::DisplayInitialOutput(__in LPWSTR moduleName)
     Output::Print(_u("INIT: DLL Path   : %s\n"), moduleName);
     Output::Print(_u("INIT: DLL Path   : %s\n"), moduleName);
 }
 }
 
 
-#ifdef ENABLE_JS_ETW
+#if defined(ENABLE_JS_ETW) && !defined(ENABLE_JS_LTTNG)
 void EtwCallbackApi::OnSessionChange(ULONG /* controlCode */, PVOID /* callbackContext */)
 void EtwCallbackApi::OnSessionChange(ULONG /* controlCode */, PVOID /* callbackContext */)
 {
 {
     // Does nothing
     // Does nothing

+ 17 - 1
build.sh

@@ -52,6 +52,7 @@ PRINT_USAGE() {
     echo "     --libs-only       Do not build CH and GCStress"
     echo "     --libs-only       Do not build CH and GCStress"
     echo "     --lto             Enables LLVM Full LTO"
     echo "     --lto             Enables LLVM Full LTO"
     echo "     --lto-thin        Enables LLVM Thin LTO - xcode 8+ or clang 3.9+"
     echo "     --lto-thin        Enables LLVM Thin LTO - xcode 8+ or clang 3.9+"
+    echo "     --lttng           Enables LTTng support for ETW events"
     echo "     --static          Build as static library. Default: shared library"
     echo "     --static          Build as static library. Default: shared library"
     echo "     --sanitize=CHECKS Build with clang -fsanitize checks,"
     echo "     --sanitize=CHECKS Build with clang -fsanitize checks,"
     echo "                       e.g. undefined,signed-integer-overflow."
     echo "                       e.g. undefined,signed-integer-overflow."
@@ -104,6 +105,7 @@ OS_LINUX=0
 OS_APT_GET=0
 OS_APT_GET=0
 OS_UNIX=0
 OS_UNIX=0
 LTO=""
 LTO=""
+LTTNG=""
 TARGET_OS=""
 TARGET_OS=""
 ENABLE_CC_XPLAT_TRACE=""
 ENABLE_CC_XPLAT_TRACE=""
 WB_CHECK=
 WB_CHECK=
@@ -230,6 +232,11 @@ while [[ $# -gt 0 ]]; do
         HAS_LTO=1
         HAS_LTO=1
         ;;
         ;;
 
 
+    --lttng)
+        LTTNG="-DENABLE_JS_LTTNG_SH=1"
+        HAS_LTTNG=1
+        ;;
+    
     -n | --ninja)
     -n | --ninja)
         CMAKE_GEN="-G Ninja"
         CMAKE_GEN="-G Ninja"
         MAKE=ninja
         MAKE=ninja
@@ -516,6 +523,15 @@ else
         exit 1
         exit 1
     fi
     fi
 fi
 fi
+export TARGET_PATH
+
+if [[ $HAS_LTTNG == 1 ]]; then
+    CHAKRACORE_ROOT=`dirname $0`
+    python $CHAKRACORE_ROOT/tools/lttng.py --man $CHAKRACORE_ROOT/manifests/Microsoft-Scripting-Chakra-Instrumentation.man --intermediate $TARGET_PATH/intermediate
+    mkdir -p $TARGET_PATH/lttng
+    (diff -q $TARGET_PATH/intermediate/lttng/jscriptEtw.h $TARGET_PATH/lttng/jscriptEtw.h && echo "jscriptEtw.h up to date; skipping") || cp $TARGET_PATH/intermediate/lttng/* $TARGET_PATH/lttng/
+fi
+
 
 
 BUILD_DIRECTORY="${TARGET_PATH}/${BUILD_TYPE:0}"
 BUILD_DIRECTORY="${TARGET_PATH}/${BUILD_TYPE:0}"
 echo "Build path: ${BUILD_DIRECTORY}"
 echo "Build path: ${BUILD_DIRECTORY}"
@@ -603,7 +619,7 @@ fi
 
 
 echo Generating $BUILD_TYPE makefiles
 echo Generating $BUILD_TYPE makefiles
 echo $EXTRA_DEFINES
 echo $EXTRA_DEFINES
-cmake $CMAKE_GEN $CC_PREFIX $ICU_PATH $LTO $STATIC_LIBRARY $ARCH $TARGET_OS \
+cmake $CMAKE_GEN $CC_PREFIX $ICU_PATH $LTO $LTTNG $STATIC_LIBRARY $ARCH $TARGET_OS \
     $ENABLE_CC_XPLAT_TRACE $EXTRA_DEFINES -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SANITIZE $NO_JIT $INTL_ICU \
     $ENABLE_CC_XPLAT_TRACE $EXTRA_DEFINES -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SANITIZE $NO_JIT $INTL_ICU \
     $WITHOUT_FEATURES $WB_FLAG $WB_ARGS $CMAKE_EXPORT_COMPILE_COMMANDS $LIBS_ONLY_BUILD\
     $WITHOUT_FEATURES $WB_FLAG $WB_ARGS $CMAKE_EXPORT_COMPILE_COMMANDS $LIBS_ONLY_BUILD\
     $VALGRIND $BUILD_RELATIVE_DIRECTORY
     $VALGRIND $BUILD_RELATIVE_DIRECTORY

+ 12 - 0
lib/CMakeLists.txt

@@ -14,6 +14,10 @@ if(CAN_BUILD_WABT)
     set(wabt_includes ${CHAKRACORE_SOURCE_DIR}/lib/wabt)
     set(wabt_includes ${CHAKRACORE_SOURCE_DIR}/lib/wabt)
 endif()
 endif()
 
 
+if (USE_LTTNG)
+    set(lttng_objects $<TARGET_OBJECTS:Chakra.LTTng>)
+endif()
+
 add_library (ChakraCoreStatic STATIC
 add_library (ChakraCoreStatic STATIC
   ChakraCoreStatic.cpp
   ChakraCoreStatic.cpp
   $<TARGET_OBJECTS:Chakra.Pal>
   $<TARGET_OBJECTS:Chakra.Pal>
@@ -38,8 +42,16 @@ add_library (ChakraCoreStatic STATIC
   $<TARGET_OBJECTS:Chakra.Parser>
   $<TARGET_OBJECTS:Chakra.Parser>
   ${wasm_objects}
   ${wasm_objects}
   ${wabt_objects}
   ${wabt_objects}
+  ${lttng_objects}
 )
 )
 
 
+if(USE_LTTNG)
+    target_link_libraries(ChakraCoreStatic
+      -llttng-ust
+      -ldl
+    )
+endif()
+
 if(CC_TARGET_OS_OSX)
 if(CC_TARGET_OS_OSX)
   target_link_libraries(ChakraCoreStatic
   target_link_libraries(ChakraCoreStatic
     "-framework CoreFoundation"
     "-framework CoreFoundation"

+ 3 - 1
lib/Common/Core/EtwTraceCore.cpp

@@ -6,6 +6,7 @@
 #include "Core/EtwTraceCore.h"
 #include "Core/EtwTraceCore.h"
 
 
 #ifdef ENABLE_JS_ETW
 #ifdef ENABLE_JS_ETW
+#ifndef ENABLE_JS_LTTNG
 extern "C" {
 extern "C" {
     ETW_INLINE
     ETW_INLINE
         VOID EtwCallback(
         VOID EtwCallback(
@@ -64,4 +65,5 @@ void EtwTraceCore::UnRegister()
     }
     }
 }
 }
 
 
-#endif
+#endif // !ENABLE_JS_LTTNG
+#endif // ENABLE_JS_ETW

+ 5 - 0
lib/Common/Core/EtwTraceCore.h

@@ -47,6 +47,10 @@
 #define JS_ETW(s) s
 #define JS_ETW(s) s
 #define IS_JS_ETW(s) s
 #define IS_JS_ETW(s) s
 
 
+#ifdef ENABLE_JS_LTTNG
+#include "jscriptEtw.h"
+
+#else
 // C-style callback
 // C-style callback
 extern "C" {
 extern "C" {
     void EtwCallback(
     void EtwCallback(
@@ -87,6 +91,7 @@ public:
 
 
     static bool s_registered;
     static bool s_registered;
 };
 };
+#endif // ENABLE_JS_LTTNG
 
 
 #else
 #else
 #define GCETW(e, ...)
 #define GCETW(e, ...)

+ 5 - 3
lib/Common/Memory/Recycler.cpp

@@ -5968,7 +5968,8 @@ Recycler::ThreadProc()
     }
     }
 #endif
 #endif
 
 
-#ifdef ENABLE_JS_ETW
+#if defined(ENABLE_JS_ETW) && ! defined(ENABLE_JS_LTTNG)
+    // LTTng has no concept of EventActivityIdControl
     // Create an ETW ActivityId for this thread, to help tools correlate ETW events we generate
     // Create an ETW ActivityId for this thread, to help tools correlate ETW events we generate
     GUID activityId = { 0 };
     GUID activityId = { 0 };
     auto eventActivityIdControlResult = EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &activityId);
     auto eventActivityIdControlResult = EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &activityId);
@@ -6536,7 +6537,8 @@ RecyclerParallelThread::StaticThreadProc(LPVOID lpParameter)
             dllHandle = NULL;
             dllHandle = NULL;
         }
         }
 #endif
 #endif
-#ifdef ENABLE_JS_ETW
+#if defined(ENABLE_JS_ETW) && ! defined(ENABLE_JS_LTTNG)
+        // LTTng has no concept of EventActivityIdControl
         // Create an ETW ActivityId for this thread, to help tools correlate ETW events we generate
         // Create an ETW ActivityId for this thread, to help tools correlate ETW events we generate
         GUID activityId = { 0 };
         GUID activityId = { 0 };
         auto eventActivityIdControlResult = EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &activityId);
         auto eventActivityIdControlResult = EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &activityId);
@@ -8776,4 +8778,4 @@ template char* Recycler::AllocZeroWithAttributesInlined<RecyclerVisitedHostTrace
 template char* Recycler::AllocZeroWithAttributesInlined<RecyclerVisitedHostFinalizableBits, /* nothrow = */true>(size_t);
 template char* Recycler::AllocZeroWithAttributesInlined<RecyclerVisitedHostFinalizableBits, /* nothrow = */true>(size_t);
 template char* Recycler::AllocZeroWithAttributesInlined<RecyclerVisitedHostTracedBits, /* nothrow = */true>(size_t);
 template char* Recycler::AllocZeroWithAttributesInlined<RecyclerVisitedHostTracedBits, /* nothrow = */true>(size_t);
 template char* Recycler::AllocZeroWithAttributesInlined<LeafBit, /* nothrow = */true>(size_t);
 template char* Recycler::AllocZeroWithAttributesInlined<LeafBit, /* nothrow = */true>(size_t);
-#endif
+#endif

+ 1 - 1
lib/Jsrt/JsrtHelper.cpp

@@ -143,7 +143,7 @@ void JsrtCallbackState::ObjectBeforeCallectCallbackWrapper(JsObjectBeforeCollect
             ConfigParser::ParseOnModuleLoad(parser, mod);
             ConfigParser::ParseOnModuleLoad(parser, mod);
         }
         }
 
 
-    #ifdef ENABLE_JS_ETW
+    #if defined(ENABLE_JS_ETW) && !defined(ENABLE_JS_LTTNG)
         EtwTrace::Register();
         EtwTrace::Register();
     #endif
     #endif
     #ifdef VTUNE_PROFILING
     #ifdef VTUNE_PROFILING

+ 2 - 2
lib/Jsrt/JsrtSourceHolder.cpp

@@ -113,7 +113,7 @@ namespace Js
 
 
 #if ENABLE_DEBUG_CONFIG_OPTIONS
 #if ENABLE_DEBUG_CONFIG_OPTIONS
         AssertMsg(reasonString != nullptr, "Reason string for why we are mapping the source was not provided.");
         AssertMsg(reasonString != nullptr, "Reason string for why we are mapping the source was not provided.");
-        JS_ETW(EventWriteJSCRIPT_SOURCEMAPPING((uint32)wcslen(reasonString), reasonString, (ushort)requestedFor));
+        JS_ETW(EventWriteJSCRIPT_SOURCEMAPPING(reasonString, (ushort)requestedFor));
 #endif
 #endif
     }
     }
 
 
@@ -285,7 +285,7 @@ namespace Js
 
 
 #if ENABLE_DEBUG_CONFIG_OPTIONS
 #if ENABLE_DEBUG_CONFIG_OPTIONS
         AssertMsg(reasonString != nullptr, "Reason string for why we are mapping the source was not provided.");
         AssertMsg(reasonString != nullptr, "Reason string for why we are mapping the source was not provided.");
-        JS_ETW(EventWriteJSCRIPT_SOURCEMAPPING((uint32)wcslen(reasonString), reasonString, (ushort)requestedFor));
+        JS_ETW(EventWriteJSCRIPT_SOURCEMAPPING(reasonString, (ushort)requestedFor));
 #endif
 #endif
     }
     }
 
 

+ 7 - 1
lib/Runtime/Base/EtwTrace.cpp

@@ -10,6 +10,7 @@
 
 
 using namespace Js;
 using namespace Js;
 
 
+#ifndef ENABLE_JS_LTTNG
 //
 //
 // This C style callback is invoked by ETW when a trace session is started/stopped
 // This C style callback is invoked by ETW when a trace session is started/stopped
 // by an ETW controller for the Jscript and MSHTML providers.
 // by an ETW controller for the Jscript and MSHTML providers.
@@ -47,6 +48,7 @@ void EtwCallbackApi::OnSessionChange(ULONG controlCode, PVOID callbackContext)
         }
         }
     }
     }
 }
 }
+#endif
 
 
 //
 //
 // Registers the ETW provider - this is usually done on Jscript DLL load
 // Registers the ETW provider - this is usually done on Jscript DLL load
@@ -54,7 +56,9 @@ void EtwCallbackApi::OnSessionChange(ULONG controlCode, PVOID callbackContext)
 //
 //
 void EtwTrace::Register()
 void EtwTrace::Register()
 {
 {
+#ifndef ENABLE_JS_LTTNG
     EtwTraceCore::Register();
     EtwTraceCore::Register();
+#endif
 
 
 #ifdef TEST_ETW_EVENTS
 #ifdef TEST_ETW_EVENTS
     TestEtwEventSink::Load();
     TestEtwEventSink::Load();
@@ -66,8 +70,10 @@ void EtwTrace::Register()
 //
 //
 void EtwTrace::UnRegister()
 void EtwTrace::UnRegister()
 {
 {
+#ifndef ENABLE_JS_LTTNG
     EtwTraceCore::UnRegister();
     EtwTraceCore::UnRegister();
-
+#endif
+    
 #ifdef TEST_ETW_EVENTS
 #ifdef TEST_ETW_EVENTS
     TestEtwEventSink::Unload();
     TestEtwEventSink::Unload();
 #endif
 #endif

+ 2 - 2
lib/Runtime/Base/ScriptContext.cpp

@@ -6159,11 +6159,11 @@ void ScriptContext::RegisterPrototypeChainEnsuredToHaveOnlyWritableDataPropertie
 
 
                 if (emitV2AsyncStackEvent)
                 if (emitV2AsyncStackEvent)
                 {
                 {
-                    JS_ETW(EventWriteJSCRIPT_ASYNCCAUSALITY_STACKTRACE_V2(operationID, frameCount, nameBufferLength, sizeof(StackFrameInfo), &stackFrames.Item(0), nameBufferString));
+                    JS_ETW(EventWriteJSCRIPT_ASYNCCAUSALITY_STACKTRACE_V2(operationID, frameCount, nameBufferLength, nameBufferString, sizeof(StackFrameInfo), &stackFrames.Item(0)));
                 }
                 }
                 else
                 else
                 {
                 {
-                    JS_ETW(EventWriteJSCRIPT_STACKTRACE(operationID, frameCount, nameBufferLength, sizeof(StackFrameInfo), &stackFrames.Item(0), nameBufferString));
+                    JS_ETW(EventWriteJSCRIPT_STACKTRACE(operationID, frameCount, nameBufferLength, nameBufferString, sizeof(StackFrameInfo), &stackFrames.Item(0)));
                 }
                 }
             }
             }
         }
         }

+ 1 - 2
lib/Runtime/Library/GlobalObject.cpp

@@ -1621,8 +1621,7 @@ LHexError:
             return function->GetScriptContext()->GetLibrary()->GetUndefined();
             return function->GetScriptContext()->GetLibrary()->GetUndefined();
         }
         }
 
 
-        Js::JavascriptString* jsString = Js::JavascriptConversion::ToString(args[1], function->GetScriptContext());
-        PlatformAgnostic::EventTrace::FireGenericEventTrace(jsString->GetSz());
+        JS_ETW(EventWriteJSCRIPT_INTERNAL_GENERIC_EVENT(Js::JavascriptConversion::ToString(args[1], function->GetScriptContext())->GetSz()));
         return function->GetScriptContext()->GetLibrary()->GetUndefined();
         return function->GetScriptContext()->GetLibrary()->GetUndefined();
     }
     }
 #endif
 #endif

+ 0 - 2
lib/Runtime/PlatformAgnostic/Chakra.Runtime.PlatformAgnostic.vcxproj

@@ -55,7 +55,6 @@
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\SystemInfo.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\SystemInfo.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\Thread.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\Thread.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Common\UnicodeText.Common.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Common\UnicodeText.Common.cpp" />
-    <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\EventTrace.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\PerfTrace.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\PerfTrace.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup Condition="'$(IntlICU)'=='true'">
   <ItemGroup Condition="'$(IntlICU)'=='true'">
@@ -63,7 +62,6 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="ChakraPlatform.h" />
     <ClInclude Include="ChakraPlatform.h" />
-    <ClInclude Include="EventTrace.h" />
     <ClInclude Include="PerfTrace.h" />
     <ClInclude Include="PerfTrace.h" />
     <ClInclude Include="RuntimePlatformAgnosticPch.h" />
     <ClInclude Include="RuntimePlatformAgnosticPch.h" />
     <ClInclude Include="UnicodeText.h" />
     <ClInclude Include="UnicodeText.h" />

+ 2 - 8
lib/Runtime/PlatformAgnostic/Chakra.Runtime.PlatformAgnostic.vcxproj.filters

@@ -1,12 +1,9 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Platform\Windows\UnicodeText.cpp">
     <ClCompile Include="Platform\Windows\UnicodeText.cpp">
       <Filter>Platform\Windows</Filter>
       <Filter>Platform\Windows</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="Platform\Windows\EventTrace.cpp">
-      <Filter>Platform\Windows</Filter>
-    </ClCompile>
     <ClCompile Include="Platform\Windows\DaylightHelper.cpp">
     <ClCompile Include="Platform\Windows\DaylightHelper.cpp">
       <Filter>Platform\Windows</Filter>
       <Filter>Platform\Windows</Filter>
     </ClCompile>
     </ClCompile>
@@ -51,9 +48,6 @@
     </ClInclude>
     </ClInclude>
     <ClInclude Include="ChakraPlatform.h" />
     <ClInclude Include="ChakraPlatform.h" />
     <ClInclude Include="RuntimePlatformAgnosticPch.h" />
     <ClInclude Include="RuntimePlatformAgnosticPch.h" />
-    <ClInclude Include="EventTrace.h">
-      <Filter>Interfaces</Filter>
-    </ClInclude>
     <ClInclude Include="PerfTrace.h">
     <ClInclude Include="PerfTrace.h">
       <Filter>Interfaces</Filter>
       <Filter>Interfaces</Filter>
     </ClInclude>
     </ClInclude>
@@ -61,4 +55,4 @@
       <Filter>Interfaces</Filter>
       <Filter>Interfaces</Filter>
     </ClInclude>
     </ClInclude>
   </ItemGroup>
   </ItemGroup>
-</Project>
+</Project>

+ 0 - 1
lib/Runtime/PlatformAgnostic/ChakraPlatform.h

@@ -5,7 +5,6 @@
 #pragma once
 #pragma once
 
 
 #include "UnicodeText.h"
 #include "UnicodeText.h"
-#include "EventTrace.h"
 
 
 // Configure whether we configure a signal handler
 // Configure whether we configure a signal handler
 // to produce perf-<pid>.map files
 // to produce perf-<pid>.map files

+ 0 - 15
lib/Runtime/PlatformAgnostic/EventTrace.h

@@ -1,15 +0,0 @@
-//-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
-//-------------------------------------------------------------------------------------------------------
-#pragma once
-
-#include "Core/CommonTypedefs.h"
-
-namespace PlatformAgnostic
-{
-    namespace EventTrace
-    {
-        void FireGenericEventTrace(const void* traceData);
-    }
-}

+ 0 - 1
lib/Runtime/PlatformAgnostic/Platform/CMakeLists.txt

@@ -4,7 +4,6 @@ set(PL_SOURCE_FILES
   Common/UnicodeText.Common.cpp
   Common/UnicodeText.Common.cpp
   Common/HiResTimer.cpp
   Common/HiResTimer.cpp
   Common/DateTime.cpp
   Common/DateTime.cpp
-  Linux/EventTrace.cpp
   Linux/UnicodeText.ICU.cpp
   Linux/UnicodeText.ICU.cpp
   Linux/NumbersUtility.cpp
   Linux/NumbersUtility.cpp
   Linux/Thread.cpp
   Linux/Thread.cpp

+ 0 - 18
lib/Runtime/PlatformAgnostic/Platform/Linux/EventTrace.cpp

@@ -1,18 +0,0 @@
-//-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
-//-------------------------------------------------------------------------------------------------------
-
-#include "RuntimePlatformAgnosticPch.h"
-#include "CommonPal.h"
-
-namespace PlatformAgnostic
-{
-    namespace EventTrace
-    {
-        void FireGenericEventTrace(const void* /*traceData*/)
-        {
-            // TODO: Implement this on Linux
-        }
-    } // namespace EventTrace
-} // namespace PlatformAgnostic

+ 0 - 19
lib/Runtime/PlatformAgnostic/Platform/Windows/EventTrace.cpp

@@ -1,19 +0,0 @@
-//-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
-//-------------------------------------------------------------------------------------------------------
-
-#include "RuntimePlatformAgnosticPch.h"
-#include "Common.h"
-#include "ChakraPlatform.h"
-
-namespace PlatformAgnostic
-{
-    namespace EventTrace
-    {
-        void FireGenericEventTrace(const void* traceData)
-        {
-            JS_ETW(EventWriteJSCRIPT_INTERNAL_GENERIC_EVENT(static_cast<const char16*>(traceData)));
-        }
-    }
-}

+ 12 - 17
manifests/Microsoft-Scripting-Chakra-Instrumentation.man

@@ -1614,6 +1614,11 @@
                     inType="win:UInt16"
                     inType="win:UInt16"
                     name="NameBufferCount"
                     name="NameBufferCount"
                     />
                     />
+                <data
+                    inType="win:UnicodeString"
+                    length="NameBufferCount"
+                    name="NameBuffer"
+                    />
                 <struct
                 <struct
                     count="FrameCount"
                     count="FrameCount"
                     name="Frames"
                     name="Frames"
@@ -1635,11 +1640,6 @@
                         name="NameIndex"
                         name="NameIndex"
                         />
                         />
                 </struct>
                 </struct>
-                <data
-                    inType="win:UnicodeString"
-                    length="NameBufferCount"
-                    name="NameBuffer"
-                    />
                 </template>
                 </template>
                 <template tid="Element_Zero">
                 <template tid="Element_Zero">
                 <data
                 <data
@@ -1836,7 +1836,12 @@
                     inType="win:UInt32"
                     inType="win:UInt32"
                     name="FrameNameBufferCount"
                     name="FrameNameBufferCount"
                     />
                     />
-                <struct
+                <data
+                    inType="win:UnicodeString"
+                    length="FrameNameBufferCount"
+                    name="FrameNameBuffer"
+                    />
+                  <struct
                     count="FrameCount"
                     count="FrameCount"
                     name="Frames"
                     name="Frames"
                     >
                     >
@@ -1862,11 +1867,6 @@
                         name="IsFrameNameIndex"
                         name="IsFrameNameIndex"
                         />
                         />
                 </struct>
                 </struct>
-                <data
-                    inType="win:UnicodeString"
-                    length="FrameNameBufferCount"
-                    name="FrameNameBuffer"
-                    />
                 </template>
                 </template>
                 <template tid="JscriptHostNativeModuleLoad">
                 <template tid="JscriptHostNativeModuleLoad">
                 <data
                 <data
@@ -1912,13 +1912,8 @@
                     />
                     />
                 </template>
                 </template>
                 <template tid="JScriptSourceMappingInfo">
                 <template tid="JScriptSourceMappingInfo">
-                <data
-                    inType="win:UInt32"
-                    name="ReasonBufferCount"
-                    />
                 <data
                 <data
                     inType="win:UnicodeString"
                     inType="win:UnicodeString"
-                    length="ReasonBufferCount"
                     name="ReasonBuffer"
                     name="ReasonBuffer"
                     />
                     />
                 <data
                 <data
@@ -4092,4 +4087,4 @@
             </stringTable>
             </stringTable>
         </resources>
         </resources>
     </localization>
     </localization>
-</instrumentationManifest>
+</instrumentationManifest>

+ 755 - 0
tools/lttng.py

@@ -0,0 +1,755 @@
+#-------------------------------------------------------------------------------------------------------
+# Copyright (C) Microsoft. All rights reserved.
+# Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+#-------------------------------------------------------------------------------------------------------
+import xml.dom.minidom as DOM
+
+lttngDataTypeMapping = {
+    "win:null"          :" ",
+    "win:Int64"         :"const __int64",
+    "win:ULong"         :"const unsigned long",
+    "win:count"         :"*",
+    "win:Struct"        :"const char *",
+    "win:GUID"          :"const int",
+    "win:AnsiString"    :"const char*",
+    "win:UnicodeString" :"const char*",
+    "win:Double"        :"const double",
+    "win:Int32"         :"const signed int",
+    "win:HexInt32"      :"const signed int",
+    "win:Boolean"       :"const bool",
+    "win:UInt64"        :"const unsigned __int64",
+    "win:UInt32"        :"const unsigned int",
+    "win:UInt16"        :"const unsigned short",
+    "win:UInt8"         :"const unsigned char",
+    "win:Int8"          :"const char",
+    "win:Pointer"       :"const uintptr_t",
+    "win:Binary"        :"const char"
+}
+
+ctfDataTypeMapping = {
+    "win:Int64"         :"ctf_integer",
+    "win:HexInt64"      :"ctf_integer_hex",
+    "win:ULong"         :"ctf_integer",
+    "win:count"         :"ctf_sequence",
+    "win:Struct"        :"ctf_sequence",
+    "win:GUID"          :"ctf_sequence",
+    "win:AnsiString"    :"ctf_string",
+    "win:UnicodeString" :"ctf_string",
+    "win:Double"        :"ctf_float",
+    "win:Int32"         :"ctf_integer",
+    "win:HexInt32"      :"ctf_integer_hex",
+    "win:Boolean"       :"ctf_integer",
+    "win:UInt64"        :"ctf_integer",
+    "win:UInt32"        :"ctf_integer",
+    "win:UInt16"        :"ctf_integer",
+    "win:HexInt16"      :"ctf_integer_hex",
+    "win:UInt8"         :"ctf_integer",  #actually a character
+    "win:Int8"          :"ctf_integer",  #actually a character
+    "win:Pointer"       :"ctf_integer",
+    "win:Binary"        :"ctf_sequence",
+    "xs:string"         :"ctf_string",
+    "xs:unsignedLong"   :"ctf_integer",
+    "xs:unsignedInt"    :"ctf_integer"
+}
+
+palDataTypeMapping ={
+        "win:null"          :" ",
+        "win:Int64"         :"const __int64",
+        "win:ULong"         :"const unsigned long",
+        "win:count"         :"*",
+        "win:Struct"        :"const void",
+        "win:GUID"          :"const GUID",
+        "win:AnsiString"    :"LPCSTR",
+        "win:UnicodeString" :"PCWSTR",
+        "win:Double"        :"const double",
+        "win:Int32"         :"const signed int",
+        "win:HexInt32"      :"const signed int",
+        "win:Boolean"       :"const bool",
+        "win:UInt64"        :"const unsigned __int64",
+        "win:UInt32"        :"const unsigned int",
+        "win:UInt16"        :"const unsigned short",
+        "win:UInt8"         :"const unsigned char",
+        "win:Int8"          :"const char",
+        "win:Pointer"       :"const void*",
+        "win:Binary"        :"const char"
+        }
+
+MAX_LTTNG_ARGS = 10
+
+def getParamSequenceSize(paramSequence, estimate):
+    total = 0
+    pointers =0
+    for param in paramSequence:
+        if param in ["win:Int64", "win:UInt64", "win:Double"]:
+            total += 8
+        elif param in ["win:ULong", "win:Int32", "win:Boolean",]:
+            total += 4
+        elif param == "GUID":
+            total += 16
+        elif param in ["win:UInt16"]:
+            total += 2
+        elif param in ["win:Uint8", "win:Binary"]:
+            total += 1
+        elif param == "win:Pointer":
+            if estimate:
+                total += 8
+            else:
+                pointers += 1
+        elif estimate:
+            if param in ["win:AnsiString", "win:Struct"]:
+                total += 32
+            elif param in ["win:UnicodeString"]:
+                total += 64
+        else:
+            raise Exception ("Don't know size of " + param)
+
+    if estimate:
+        return total
+
+    return total, pointers
+
+class Template:
+    def __repr__(self):
+        return "<Template " + self.name + " />"
+    
+    def __init__(self, name, prototypes, dependencies, structCounts, arrayCounts):
+        self.name = name
+        self.signature = FunctionSignature()
+        self.structCounts = structCounts
+        self.arrayCounts = arrayCounts
+
+        for variable in prototypes.paramList:
+            for dependency in dependencies[variable]:
+                if not self.signature.getParam(dependency):
+                    self.signature.append(dependency, prototypes.getParam(dependency))
+    @property
+    def num_params(self):
+        return len(self.signature.paramList)
+
+    def getParam(self, name):
+        return self.signature.getParam(name)
+
+    @property
+    def estimatedSize(self):
+        total = getParamSequenceSize((self.getParam(paramName).winType for paramName in self.signature.paramList), True)
+
+        if total < 32:
+            return 32
+        elif total > 1024:
+            return 1024
+        return total
+
+class FunctionSignature:
+    def __repr__(self):
+        return ', '.join(self.paramList)
+        
+    def __init__(self):
+        self.LUT = {}
+        self.paramList = []
+
+    def append(self, variable, param):
+        self.LUT[variable] = param
+        self.paramList.append(variable)
+
+    def getParam(self, variable):
+        return self.LUT.get(variable)
+
+    def getLength(self):
+        return len(self.paramList)
+
+class FunctionParameter:
+    def __repr__(self):
+        return self.name
+
+    def __init__(self, winType, name, count, outType, length):
+        self.winType = winType
+        self.outType = outType
+        self.name = name
+        self.length = length
+        self.count = "win:null"
+        if winType == "win:GUID" or count == "win:count":
+            self.count = "win:count"
+
+ignoredXmlAttributes = frozenset(["map"])
+usedXmlAttributes    = frozenset(["name", "inType", "count", "length", "outType"])
+knownXmlAttributes   = ignoredXmlAttributes | usedXmlAttributes
+            
+def checkKnownAttributes(nodes, templateName):
+    for node in nodes:
+        nodeMap = node.attributes
+        for attribute in nodeMap.values():
+            if attribute.name not in knownXmlAttributes:
+                raise ValueError('Unknown attribute: ' + attribute.name + ' in template ' + templateName)
+
+def getTopLevelElementsByTagName(node, tag):
+    return [e for e in node.getElementsByTagName(tag) if e.parentNode == node]
+            
+def parseTemplateNodes(templateNodes):
+    templates = {}
+
+    for templateNode in templateNodes:
+        templateName = templateNode.getAttribute('tid')
+        dataNodes = getTopLevelElementsByTagName(templateNode, 'data')
+
+        checkKnownAttributes(dataNodes, templateName)
+
+        functionPrototypes = FunctionSignature()
+        
+        arrayCounts = {}
+        structCounts = {}
+        var_Dependencies = {}
+
+        for dataNode in dataNodes:
+            variable = dataNode.getAttribute('name')
+            wintype = dataNode.getAttribute('inType')
+            outType = dataNode.getAttribute('outType')
+
+            wincount = dataNode.getAttribute('count')
+            winLength = dataNode.getAttribute('length')
+
+            var_dependency = [variable]
+            if winLength:
+                if wincount:
+                    raise Exception("Both count and length properties found on " + variable + " in template " + templateName)
+
+            if wincount.isdigit() and int(wincount) == 1:
+                wincount = ''
+
+            if wincount:
+                if wincount.isdigit():
+                    raise Exception("Expect constant count to be length")
+                elif functionPrototypes.getParam(wincount):
+                    var_dependency.insert(0, wincount)
+                    arrayCounts[variable] = wincount
+
+
+            var_Dependencies[variable] = var_dependency
+            functionParameter = FunctionParameter(wintype, variable, wincount, outType, winLength)
+            functionPrototypes.append(variable, functionParameter)
+
+        structNodes = getTopLevelElementsByTagName(templateNode, 'struct')
+
+        for structNode in structNodes:
+            structName = structNode.getAttribute('name')
+            countName  = structNode.getAttribute('count')
+
+            assert(countName in functionPrototypes.paramList)
+
+            #childData = structNode.getElementsByTagName("data")
+            #names = [x.attributes['name'].value for x in childData]
+            #types = [x.attributes['inType'].value for x in childData]
+
+            structCounts[structName] = countName
+            var_Dependencies[structName] = [countName, structName]
+            functionParameterPointer = FunctionParameter("win:Struct", structName, "win:count", None, None)
+            functionPrototypes.append(structName, functionParameterPointer)
+
+        templates[templateName] = Template(templateName, functionPrototypes, var_Dependencies, structCounts, arrayCounts)
+
+    return templates
+            
+def shouldPackTemplate(template):
+    return template.num_params > MAX_LTTNG_ARGS or len(template.structCounts) > 0 or len(template.arrayCounts) > 0
+
+def generateArgList(template):
+    # Construct a TP_ARGS macro call, as defined in another macro, e.g.
+    #
+    # TP_ARGS(                \
+    #    int, my_integer_arg, \
+    #    char*, my_string_arg \
+    # )
+    header = "TP_ARGS( \\\n"
+    footer = "\\\n)"
+
+    args = []
+
+    if shouldPackTemplate(template):
+        args.append("        const unsigned int, length")
+        args.append("        const char *, __data__")
+    else:
+        signature = template.signature
+        for param in signature.paramList:
+            functionParam = signature.getParam(param)
+            wintypeName   = functionParam.winType
+            mappedType    = lttngDataTypeMapping[wintypeName]
+            winCount      = functionParam.count
+            mappedCount   = lttngDataTypeMapping[winCount]
+
+            arg = "        " + mappedType
+            if mappedCount != " ":
+                arg += mappedCount
+            elif functionParam.length:
+                arg += "*"
+            arg += ", " + functionParam.name
+            
+            args.append(arg)
+        
+    return header + ", \\\n".join(args) + footer
+
+def generateFieldList(template):
+    # Construct a TP_FIELDS macro call, e.g.
+    # TP_FIELDS(
+    #     ctf_string(my_string_field, my_string_arg)
+    #     ctf_integer(int, my_integer_field, my_integer_arg)
+    # )
+    header = "    " + " TP_FIELDS(\n"
+    footer = "\n    )"
+
+    fieldList = []
+    
+    if shouldPackTemplate(template):
+        fieldList.append("      ctf_integer(unsigned long, length, length)")
+        fieldList.append("      ctf_sequence(char, __data__, __data__, unsigned long, length)")
+    else:
+        signature = template.signature
+        for param in signature.paramList:
+            functionParam = signature.getParam(param)
+            wintypeName   = functionParam.winType
+            winCount      = functionParam.count
+            mappedCount   = lttngDataTypeMapping[winCount]
+            mappedType    = lttngDataTypeMapping[wintypeName].replace("const ", "")
+
+            if functionParam.outType:
+                wintypeName = functionParam.outType
+
+            ctf_type = None
+            field_body = None
+            varname = functionParam.name
+
+            if param in template.structCounts or param in template.arrayCounts:
+                # This is a struct, treat as a sequence
+                countVar = template.structCounts.get(param, template.arrayCounts.get(param))
+                ctf_type = "ctf_sequence"
+                field_body = ", ".join((mappedType, varname, varname, "size_t", functionParam.prop))
+            elif functionParam.length:
+                ctf_type = "ctf_sequence"
+                field_body = ", ".join((mappedType, varname, varname, "size_t", functionParam.length))
+            else:
+                ctf_type = ctfDataTypeMapping[wintypeName]
+                if ctf_type == "ctf_string":
+                    field_body = ", ".join((varname, varname))
+                elif ctf_type == "ctf_integer" or ctf_type == "ctf_integer_hex" or ctf_type == "ctf_float":
+                    field_body = ", ".join((mappedType, varname, varname))
+                elif ctf_type == "ctf_sequence":
+                    raise Exception("ctf_sequence needs special handling: " + template.name + " " + param)
+                else:
+                    raise Exception("Unhandled ctf intrinsic: " + ctf_type)
+
+#            fieldList.append("//    " + wintypeName)
+            fieldList.append("      %s(%s)" % (ctf_type, field_body))
+    
+    return header + "\n".join(fieldList) + footer
+
+def generateLttngHeader(providerName, lttngEventHeaderShortName, templates, events):
+    headerLines = []
+
+    headerLines.append("")
+    headerLines.append("#ifdef __int64")
+    headerLines.append("#if TARGET_64")
+    headerLines.append("#undef __int64")
+    headerLines.append("#else")
+    headerLines.append("#error \"Linux and OSX builds only support 64bit platforms\"")
+    headerLines.append("#endif // TARGET_64")
+    headerLines.append("#endif // __int64")
+    headerLines.append("#undef TRACEPOINT_PROVIDER")
+    headerLines.append("#undef TRACEPOINT_INCLUDE")
+    headerLines.append("")
+    headerLines.append("#define TRACEPOINT_PROVIDER " + providerName + "\n")
+    headerLines.append("#define TRACEPOINT_INCLUDE \"./" + lttngEventHeaderShortName + "\"\n\n")
+
+    headerLines.append("#if !defined(LTTNG_CHAKRA_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n")
+    headerLines.append("#define LTTNG_CHAKRA_H" + providerName +"\n")
+
+    headerLines.append("\n#include <lttng/tracepoint.h>\n\n")
+
+    
+    for templateName in templates:
+        template = templates[templateName]
+        functionSignature = template.signature
+
+        headerLines.append("")
+        headerLines.append("#define " + templateName + "_TRACEPOINT_ARGS \\")
+
+        tracepointArgs = generateArgList(template)
+        headerLines.append(tracepointArgs)
+
+        headerLines.append("TRACEPOINT_EVENT_CLASS(")
+        headerLines.append("    " + providerName + ",")
+        headerLines.append("    " + templateName + ",")
+        headerLines.append("    " + templateName + "_TRACEPOINT_ARGS,")
+        tracepointFields = generateFieldList(template)
+        headerLines.append(tracepointFields)
+        headerLines.append(")")
+                        
+        headerLines.append("#define " + templateName + "T_TRACEPOINT_INSTANCE(name) \\")
+        headerLines.append("TRACEPOINT_EVENT_INSTANCE(\\")
+        headerLines.append("    " + providerName + ",\\")
+        headerLines.append("    " + templateName + ",\\")
+        headerLines.append("    name,\\")
+        headerLines.append("    " + templateName + "_TRACEPOINT_ARGS \\")
+        headerLines.append(")")
+
+    headerLines.append("")
+    headerLines.append("")
+    headerLines.append("TRACEPOINT_EVENT_CLASS(")
+    headerLines.append("    " + providerName + ",")
+    headerLines.append("    emptyTemplate,")
+    headerLines.append("    TP_ARGS(),")
+    headerLines.append("    TP_FIELDS()")
+    headerLines.append(")")
+    headerLines.append("#define T_TRACEPOINT_INSTANCE(name) \\")
+    headerLines.append("TRACEPOINT_EVENT_INSTANCE(\\")
+    headerLines.append("    " + providerName + ",\\")
+    headerLines.append("    emptyTemplate,\\")
+    headerLines.append("    name,\\")
+    headerLines.append("    TP_ARGS()\\")
+    headerLines.append(")")
+
+    headerLines.append("")
+
+    for eventNode in events:
+        eventName    = eventNode.getAttribute('symbol')
+        templateName = eventNode.getAttribute('template')
+
+        if not eventName:
+            raise Exception(eventNode + " event does not have a symbol")
+        if not templateName:
+            headerLines.append("T_TRACEPOINT_INSTANCE(" + eventName + ")")
+            continue
+
+        headerLines.append(templateName + "T_TRACEPOINT_INSTANCE(" + eventName + ")")
+
+    headerLines.append("#endif /* LTTNG_CHAKRA_H" + providerName + " */")
+    headerLines.append("#include <lttng/tracepoint-event.h>")
+
+    return "\n".join(headerLines)
+
+def generateMethodBody(template, providerName, eventName):
+    # Convert from ETW's windows types to LTTng compatiable types
+
+    methodBody = [""]
+    
+    functionSignature = template.signature
+
+    if not shouldPackTemplate(template):
+        invocation = ["do_tracepoint(" + providerName, eventName]
+
+        for paramName in functionSignature.paramList:
+            functionParam = functionSignature.getParam(paramName)
+            wintypeName   = functionParam.winType
+            winCount      = functionParam.count
+            
+            ctf_type      = None
+
+            if functionParam.outType:
+                ctf_type = ctfDataTypeMapping.get(functionParam.outType)
+            else:
+                ctf_Type = ctfDataTypeMapping.get(winCount)
+
+            if not ctf_type:
+                ctf_type = ctfDataTypeMapping[wintypeName]
+
+            if ctf_type == "ctf_string" and wintypeName == "win:UnicodeString":
+                # Convert wchar unicode string to utf8
+                if functionParam.length:
+                    methodBody.append("utf8::WideToNarrow " + paramName + "_converter(" + paramName + ", " + functionParam.length + ");")
+                else:
+                    methodBody.append("utf8::WideToNarrow " + paramName + "_converter(" + paramName + ");")
+                invocation.append(paramName + "_converter")
+#            elif ctf_type == "ctf_sequence" or wintypeName == "win:Pointer":
+            elif wintypeName == "win:Pointer":
+                invocation.append("(" + lttngDataTypeMapping[wintypeName] + lttngDataTypeMapping[winCount] + ")" + paramName)
+            else:
+                invocation.append(paramName)
+
+        methodBody.append(",\n        ".join(invocation) + ");")
+    else:
+        # Packing results into buffer
+        methodBody.append("char stackBuffer[" + str(template.estimatedSize) + "];")
+        methodBody.append("char *buffer = stackBuffer;")
+        methodBody.append("int offset = 0;")
+        methodBody.append("int size = " + str(template.estimatedSize) + ";")
+        methodBody.append("bool fixedBuffer = true;")
+        methodBody.append("bool success = true;")
+
+        for paramName in functionSignature.paramList:
+            functionParameter = functionSignature.getParam(paramName)
+
+            if paramName in template.structCounts:
+                size = "(unsigned int)" + paramName + "_ElementSize * (unsigned int)" + template.structCounts[paramName]
+                methodBody.append("success &= WriteToBuffer((const char *)" + paramName + ", " + size + ", buffer, offset, size, fixedBuffer);")
+            elif paramName in template.arrayCounts:
+                size = "sizeof(" + lttngDataTypeMapping[functionParameter.winType] + ") * (unsigned int)" + template.arrayCounts[paramName]
+                methodBody.append("success &= WriteToBuffer((const char *)" + paramName + ", " + size + ", buffer, offset, size, fixedBuffer);")
+            elif functionParameter.winType == "win:GUID":
+                methodBody.append("success &= WriteToBuffer(*" + paramName + ", buffer, offset, size, fixedBuffer);")
+            else:
+                methodBody.append("success &= WriteToBuffer(" + paramName + ", buffer, offset, size, fixedBuffer);")
+
+        methodBody.append("if (!success)")
+        methodBody.append("{")
+        methodBody.append("    if (!fixedBuffer) delete[] buffer;")
+        methodBody.append("    return ERROR_WRITE_FAULT;")
+        methodBody.append("}")
+        methodBody.append("do_tracepoint(" + providerName + ", " + eventName + ", offset, buffer);")
+        methodBody.append("if (!fixedBuffer) delete[] buffer;")
+
+    return "\n    ".join(methodBody) + "\n"
+
+def generateMethodSignature(template):
+    if not template:
+        return ""
+    
+    functionSignature = template.signature
+    lineFunctionPrototype = []
+    for paramName in functionSignature.paramList:
+        functionParameter = functionSignature.getParam(paramName)
+        wintypeName = functionParameter.winType
+        mappedType = palDataTypeMapping[wintypeName]
+        winCount = functionParameter.count
+        mappedCount = palDataTypeMapping[winCount]
+
+        if paramName in template.structCounts:
+            lineFunctionPrototype.append("    int " + paramName + "_ElementSize")
+        # lineFunctionPrototype.append("//    " + wintypeName + " " + str(functionParameter.length))
+        lineFunctionPrototype.append(
+            "    " + mappedType
+            + (mappedCount if mappedCount != " " else "*" if functionParameter.length and not wintypeName in ["win:UnicodeString", "win:AnsiString"] else "")
+            + " "
+            + functionParameter.name)
+    return ",\n".join(lineFunctionPrototype)
+
+
+def generateLttngTracepointProvider(providerName, lttngHeader, templates, events):
+    providerLines = [];
+
+    providerLines.append("#define TRACEPOINT_DEFINE")
+    providerLines.append("#ifndef CHAKRA_STATIC_LIBRARY")
+    providerLines.append("#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE")
+    providerLines.append("#endif")
+    providerLines.append("#include \"stdlib.h\"")
+    providerLines.append("#include \"Common.h\"")
+    providerLines.append("#include \"Codex/Utf8Helper.h\"")
+    
+    providerLines.append("#include \"" + lttngHeader + "\"\n\n")
+    providerLines.append("#ifndef tracepoint_enabled")
+    providerLines.append("#define tracepoint_enabled(provider, name) 1")
+    providerLines.append("#define do_tracepoint tracepoint")
+    providerLines.append("#endif")
+
+    providerLines.append("""
+bool ResizeBuffer(char *&buffer, int&size, int currentLength, int newSize, bool &fixedBuffer)
+{
+    newSize *= 1.5;
+    _ASSERTE(newSize > size); // Check for overflow
+
+    if (newSize < 32)
+    {
+        newSize = 32;
+    }
+
+    char *newBuffer = new char[newSize];
+    memcpy(newBuffer, buffer, currentLength);
+
+    if (!fixedBuffer)
+    {
+        delete[] buffer;
+    }
+
+    buffer = newBuffer;
+    size = newSize;
+    fixedBuffer = false;
+    return true;
+}
+
+bool WriteToBuffer(const char * src, int len, char *&buffer, int &offset, int &size, bool &fixedBuffer)
+{
+    if (!src)
+    {
+        return true;
+    }
+    if (offset + len > size)
+    {
+        if (!ResizeBuffer(buffer, size, offset, size+len, fixedBuffer))
+        {
+            return false;
+        }
+    }
+
+    memcpy(buffer + offset, src, len);
+    offset += len;
+    return true;
+}
+
+template <typename T>
+bool WriteToBuffer(const T &value, char *&buffer, int&offset, int&size, bool &fixedBuffer)
+{
+    if (sizeof(T) + offset > size)
+    {
+        if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
+        {
+            return false;
+        }
+    }
+
+    *(T *)(buffer + offset) = value;
+    offset += sizeof(T);
+    return true;
+}
+""")
+
+    for eventNode in events:
+        eventName    = eventNode.getAttribute('symbol')
+        templateName = eventNode.getAttribute('template')
+
+        providerLines.append("extern \"C\" bool EventXplatEnabled%s(){ return tracepoint_enabled(%s, %s);}"
+                             % (eventName, providerName, eventName))
+        providerLines.append("")
+
+        template = None
+        if templateName:
+            template = templates[templateName]
+
+        providerLines.append("extern \"C\" unsigned long FireEtXplat" + eventName + "(")
+        providerLines.append(generateMethodSignature(template))
+        providerLines.append(")")
+        providerLines.append("{")
+        providerLines.append("    if (!EventXplatEnabled" + eventName + "())")
+        providerLines.append("        return ERROR_SUCCESS;")
+
+        if template:
+            providerLines.append(generateMethodBody(template, providerName, eventName))
+        else:
+            providerLines.append("    do_tracepoint(" + providerName + ", " + eventName +");")
+
+        providerLines.append("")
+        providerLines.append("    return ERROR_SUCCESS;")
+        providerLines.append("}")
+        providerLines.append("")
+
+    return "\n".join(providerLines)
+
+def generateEtwHeader(templates, events):
+    headerLines = []
+
+    headerLines.append("#include \"pal.h\"")
+    headerLines.append("")
+    
+    for event in events:
+        eventName = event.getAttribute('symbol')
+        templateName = event.getAttribute('template')
+
+        template = None
+        if templateName:
+            template = templates[templateName]
+
+        callArgs = []
+        if template:
+            functionSignature = template.signature
+            for param in functionSignature.paramList:
+                if param in template.structCounts:
+                    callArgs.append(param + "_ElementSize")
+                callArgs.append(param)
+
+        headerLines.append("extern \"C\" bool EventXplatEnabled" + eventName +"();")
+        headerLines.append("inline bool EventEnabled" + eventName +"() { return EventXplatEnabled" + eventName + "();}")
+        headerLines.append("")
+        headerLines.append("extern \"C\" unsigned long FireEtXplat" + eventName +" (")
+        headerLines.append(generateMethodSignature(template))
+        headerLines.append(");")
+        headerLines.append("inline unsigned long EventWrite" + eventName + "(")
+        headerLines.append(generateMethodSignature(template))
+        headerLines.append(")")
+        headerLines.append("{")
+        headerLines.append("    return FireEtXplat" + eventName + "(" + ", ".join(callArgs) + ");")
+        headerLines.append("}")
+        headerLines.append("")
+        
+
+    return "\n".join(headerLines)
+
+def generateCmakeFile(providerName):
+    cmakeLines = []
+    cmakeLines.append("project(Chakra.LTTng)")
+    cmakeLines.append("")
+    cmakeLines.append("add_compile_options(-fPIC)")
+    cmakeLines.append("")
+    cmakeLines.append("add_library (Chakra.LTTng OBJECT")
+    cmakeLines.append("  eventprovider" + providerName + ".cpp")
+    cmakeLines.append("  tracepointprovider" + providerName + ".cpp")
+    cmakeLines.append(")")
+
+    return "\n".join(cmakeLines)
+
+def generateLttngFiles(manifest, providerDirectory):
+    import os
+    tree = DOM.parse(manifest)
+
+    if not os.path.exists(providerDirectory):
+        os.makedirs(providerDirectory)
+
+    if not os.path.exists(providerDirectory + "/lttng"):
+        os.makedirs(providerDirectory + "/lttng")
+
+    for providerNode in tree.getElementsByTagName("provider"):
+        providerName = providerNode.getAttribute("name")
+        providerName = providerName.replace("Microsoft-", "")
+
+        providerNameFile = providerName.lower()
+
+        lttngEventHeaderShortName = "tp" + providerNameFile + ".h"
+        lttngEventHeaderPath      = providerDirectory + "/lttng/" + lttngEventHeaderShortName
+        lttngEventProvider        = providerDirectory + "/lttng/eventprovider" + providerNameFile + ".cpp"
+        lttngEventProviderTrace   = providerDirectory + "/lttng/tracepointprovider" + providerNameFile + ".cpp"
+        lttngEtwHeaderFile        = providerDirectory + "/lttng/" + providerNameFile + "Etw.h"
+        lttngCmakeFile            = providerDirectory + "/lttng/CMakeLists.txt"
+
+        lttngHeader              = open(lttngEventHeaderPath, "w")
+        lttngImplementation      = open(lttngEventProvider, "w")
+        lttngTraceImplementation = open(lttngEventProviderTrace, "w")
+        lttngEtwHeader           = open(lttngEtwHeaderFile, "w")
+        lttngCmake               = open(lttngCmakeFile, "w")
+
+        # Create the lttng implementation
+        lttngTraceImplementation.write("#define TRACEPOINT_CREATE_PROBES\n")
+        lttngTraceImplementation.write("#include \"./"+lttngEventHeaderShortName+"\"\n")
+        lttngTraceImplementation.close()
+
+        # Create the lttng header
+
+        templateNodes = providerNode.getElementsByTagName('template')
+        eventNodes = providerNode.getElementsByTagName('event')
+
+        allTemplates = parseTemplateNodes(templateNodes)
+
+        lttngHeader.write(generateLttngHeader(providerName, lttngEventHeaderShortName, allTemplates, eventNodes))
+        lttngHeader.close();
+
+        lttngImplementation.write(generateLttngTracepointProvider(providerName, lttngEventHeaderShortName, allTemplates, eventNodes))
+        lttngImplementation.close();
+
+        lttngEtwHeader.write(generateEtwHeader(allTemplates, eventNodes))
+        lttngEtwHeader.close()
+
+        # Note: This in particular assumes that there is only one ETW provider
+        lttngCmake.write(generateCmakeFile(providerNameFile))
+        lttngCmake.close()
+
+if __name__ == '__main__':
+    import argparse
+    import sys
+
+    parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng logging mechanism")
+
+    required = parser.add_argument_group('required arguments')
+    required.add_argument('--man',  type=str, required=True,
+                                    help='full path to manifest containig the description of events')
+    required.add_argument('--intermediate', type=str, required=True,
+                                    help='full path to eventprovider intermediate directory')
+    args, unknown = parser.parse_known_args(sys.argv[1:])
+    if unknown:
+        print('Unknown argument(s): ', ', '.join(unknown))
+        sys.exit(1)
+
+    generateLttngFiles(args.man, args.intermediate)
+    sys.exit(0)