From 1fa530511ca904654fff211f637254d9f3ce262a Mon Sep 17 00:00:00 2001 From: Jimmy Thomson Date: Wed, 22 Nov 2017 10:12:18 -0800 Subject: [PATCH] Enable support for ETW events on xplat via LTTng Running build.sh with the --lttng flag will generate ETW-like event emitting functions that produce LTTng events. This means that you can get improved diagnostics on non-windows platforms like so: ```bash ./build.sh --lttng # + whatever other flags lttng create mySession lttng enable-event -u "JScript:*" # or more specific events specified in the ETW manifest lttng start out/Release/ch script.js lttng stop lttng view ``` --- CMakeLists.txt | 16 + bin/GCStress/StubExternalApi.cpp | 2 +- build.sh | 15 +- lib/CMakeLists.txt | 12 + lib/Common/Core/EtwTraceCore.cpp | 4 +- lib/Common/Core/EtwTraceCore.h | 5 + lib/Common/Memory/Recycler.cpp | 6 +- lib/Jsrt/JsrtHelper.cpp | 2 +- lib/Runtime/Base/EtwTrace.cpp | 8 +- tools/lttng.py | 755 +++++++++++++++++++++++++++++++ 10 files changed, 817 insertions(+), 8 deletions(-) create mode 100644 tools/lttng.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d9a7191303..49c515e8e06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,5 +495,21 @@ add_definitions( -DNO_PAL_MINMAX -DPAL_STDCPP_COMPAT ) + +if (ENABLE_JS_LTTNG_SH) + unset(ENABLE_JS_LTTNG_SH CACHE) + include_directories ( + ${CMAKE_CURRENT_SOURCE_DIR}/out/lttng + ) + add_subdirectory (out/lttng) + + add_definitions( + -DENABLE_JS_ETW + -DENABLE_JS_LTTNG + ) + set(USE_LTTNG "1") +endif() + add_subdirectory (lib) + add_subdirectory (bin) diff --git a/bin/GCStress/StubExternalApi.cpp b/bin/GCStress/StubExternalApi.cpp index 78669cae0c1..cac9b97c7af 100644 --- a/bin/GCStress/StubExternalApi.cpp +++ b/bin/GCStress/StubExternalApi.cpp @@ -21,7 +21,7 @@ void ConfigParserAPI::DisplayInitialOutput(__in LPWSTR 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 */) { // Does nothing diff --git a/build.sh b/build.sh index 93946bcd38d..362c79cb8f9 100755 --- a/build.sh +++ b/build.sh @@ -52,6 +52,7 @@ PRINT_USAGE() { echo " --libs-only Do not build CH and GCStress" echo " --lto Enables LLVM Full LTO" 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 " --sanitize=CHECKS Build with clang -fsanitize checks," echo " e.g. undefined,signed-integer-overflow." @@ -104,6 +105,7 @@ OS_LINUX=0 OS_APT_GET=0 OS_UNIX=0 LTO="" +LTTNG="" TARGET_OS="" ENABLE_CC_XPLAT_TRACE="" WB_CHECK= @@ -230,6 +232,11 @@ while [[ $# -gt 0 ]]; do HAS_LTO=1 ;; + --lttng) + LTTNG="-DENABLE_JS_LTTNG_SH=1" + HAS_LTTNG=1 + ;; + -n | --ninja) CMAKE_GEN="-G Ninja" MAKE=ninja @@ -418,6 +425,12 @@ if [[ ${#_VERBOSE} > 0 ]]; then echo "" fi +if [[ $HAS_LTTNG == 1 ]]; then + python tools/lttng.py --man `pwd`/manifests/Microsoft-Scripting-Chakra-Instrumentation.man --intermediate `pwd`/out/intermediate + mkdir -p `pwd`/out/lttng + diff -q `pwd`/out/intermediate/lttng/jscriptEtw.h `pwd`/out/lttng/jscriptEtw.h || cp `pwd`/out/intermediate/lttng/* `pwd`/out/lttng/ +fi + # if LTO build is enabled and cc-toolchain/clang was compiled, use it instead if [[ $HAS_LTO == 1 ]]; then if [[ -f "${CHAKRACORE_DIR}/cc-toolchain/build/bin/clang++" ]]; then @@ -602,7 +615,7 @@ fi echo Generating $BUILD_TYPE makefiles 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 \ $WITHOUT_FEATURES $WB_FLAG $WB_ARGS $CMAKE_EXPORT_COMPILE_COMMANDS $LIBS_ONLY_BUILD\ $VALGRIND $BUILD_RELATIVE_DIRECTORY diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 089f4aa5e1e..ec8a3805f9f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -14,6 +14,10 @@ if(CAN_BUILD_WABT) set(wabt_includes ${CHAKRACORE_SOURCE_DIR}/lib/wabt) endif() +if (USE_LTTNG) + set(lttng_objects $) +endif() + add_library (ChakraCoreStatic STATIC ChakraCoreStatic.cpp $ @@ -38,8 +42,16 @@ add_library (ChakraCoreStatic STATIC $ ${wasm_objects} ${wabt_objects} + ${lttng_objects} ) +if(USE_LTTNG) + target_link_libraries(ChakraCoreStatic + -llttng-ust + -ldl + ) +endif() + if(CC_TARGET_OS_OSX) target_link_libraries(ChakraCoreStatic "-framework CoreFoundation" diff --git a/lib/Common/Core/EtwTraceCore.cpp b/lib/Common/Core/EtwTraceCore.cpp index d0ebb6aa543..a2e5f849d6f 100644 --- a/lib/Common/Core/EtwTraceCore.cpp +++ b/lib/Common/Core/EtwTraceCore.cpp @@ -6,6 +6,7 @@ #include "Core/EtwTraceCore.h" #ifdef ENABLE_JS_ETW +#ifndef ENABLE_JS_LTTNG extern "C" { ETW_INLINE VOID EtwCallback( @@ -64,4 +65,5 @@ void EtwTraceCore::UnRegister() } } -#endif +#endif // !ENABLE_JS_LTTNG +#endif // ENABLE_JS_ETW diff --git a/lib/Common/Core/EtwTraceCore.h b/lib/Common/Core/EtwTraceCore.h index 9f44040c2f6..ad9bc0c58d5 100644 --- a/lib/Common/Core/EtwTraceCore.h +++ b/lib/Common/Core/EtwTraceCore.h @@ -47,6 +47,10 @@ #define JS_ETW(s) s #define IS_JS_ETW(s) s +#ifdef ENABLE_JS_LTTNG +#include "jscriptEtw.h" + +#else // C-style callback extern "C" { void EtwCallback( @@ -87,6 +91,7 @@ class EtwTraceCore static bool s_registered; }; +#endif // ENABLE_JS_LTTNG #else #define GCETW(e, ...) diff --git a/lib/Common/Memory/Recycler.cpp b/lib/Common/Memory/Recycler.cpp index b6bcdd00814..fc985126aa3 100644 --- a/lib/Common/Memory/Recycler.cpp +++ b/lib/Common/Memory/Recycler.cpp @@ -5968,7 +5968,7 @@ Recycler::ThreadProc() } #endif -#ifdef ENABLE_JS_ETW +#if defined(ENABLE_JS_ETW) && ! defined(ENABLE_JS_LTTNG) // Create an ETW ActivityId for this thread, to help tools correlate ETW events we generate GUID activityId = { 0 }; auto eventActivityIdControlResult = EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &activityId); @@ -6536,7 +6536,7 @@ RecyclerParallelThread::StaticThreadProc(LPVOID lpParameter) dllHandle = NULL; } #endif -#ifdef ENABLE_JS_ETW +#if defined(ENABLE_JS_ETW) && ! defined(ENABLE_JS_LTTNG) // Create an ETW ActivityId for this thread, to help tools correlate ETW events we generate GUID activityId = { 0 }; auto eventActivityIdControlResult = EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_SET_ID, &activityId); @@ -8757,4 +8757,4 @@ template char* Recycler::AllocZeroWithAttributesInlined(size_t); template char* Recycler::AllocZeroWithAttributesInlined(size_t); template char* Recycler::AllocZeroWithAttributesInlined(size_t); -#endif \ No newline at end of file +#endif diff --git a/lib/Jsrt/JsrtHelper.cpp b/lib/Jsrt/JsrtHelper.cpp index 65203a66270..5f750d34046 100644 --- a/lib/Jsrt/JsrtHelper.cpp +++ b/lib/Jsrt/JsrtHelper.cpp @@ -143,7 +143,7 @@ void JsrtCallbackState::ObjectBeforeCallectCallbackWrapper(JsObjectBeforeCollect ConfigParser::ParseOnModuleLoad(parser, mod); } - #ifdef ENABLE_JS_ETW + #if defined(ENABLE_JS_ETW) && !defined(ENABLE_JS_LTTNG) EtwTrace::Register(); #endif #ifdef VTUNE_PROFILING diff --git a/lib/Runtime/Base/EtwTrace.cpp b/lib/Runtime/Base/EtwTrace.cpp index fddc82e1993..ce4b50cccad 100644 --- a/lib/Runtime/Base/EtwTrace.cpp +++ b/lib/Runtime/Base/EtwTrace.cpp @@ -10,6 +10,7 @@ using namespace Js; +#ifndef ENABLE_JS_LTTNG // // 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. @@ -47,6 +48,7 @@ void EtwCallbackApi::OnSessionChange(ULONG controlCode, PVOID callbackContext) } } } +#endif // // 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() { +#ifndef ENABLE_JS_LTTNG EtwTraceCore::Register(); +#endif #ifdef TEST_ETW_EVENTS TestEtwEventSink::Load(); @@ -66,8 +70,10 @@ void EtwTrace::Register() // void EtwTrace::UnRegister() { +#ifndef ENABLE_JS_LTTNG EtwTraceCore::UnRegister(); - +#endif + #ifdef TEST_ETW_EVENTS TestEtwEventSink::Unload(); #endif diff --git a/tools/lttng.py b/tools/lttng.py new file mode 100644 index 00000000000..5b75a0da6ad --- /dev/null +++ b/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 size_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 "