diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6f4118..c3e529f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,23 +146,35 @@ jobs: - name: Install run: | - cmake --install ${{ github.workspace }}/build/ci --component server --prefix ${{ github.workspace }}/install + cmake --install ${{ github.workspace }}/build/ci --component server --prefix ${{ github.workspace }}/install/server + cmake --install ${{ github.workspace }}/build/ci --component tools --prefix ${{ github.workspace }}/install/tools - - name: Add build info + - name: Create build info shell: pwsh run: | "ref: ${{ github.ref_name }}`n" + ` "commit: ${{ github.sha }}`n" + ` - "date: $(Get-Date -UFormat '%FT%T%Z' -AsUTC)" | Out-File -Path "${{ github.workspace }}/install/bin/info.txt" + "date: $(Get-Date -UFormat '%FT%T%Z' -AsUTC)" | Out-File -Path "${{ github.workspace }}/install/info.txt" + cp ${{ github.workspace }}/install/info.txt ${{ github.workspace }}/install/server/bin/ + cp ${{ github.workspace }}/install/info.txt ${{ github.workspace }}/install/tools/bin/ - - name: Upload binaries - uses: actions/upload-artifact@v3 + - name: Upload server binaries + uses: actions/upload-artifact@v4 if: runner.os != 'Linux' || matrix.compiler == 'gcc' with: name: snail-server-${{ matrix.arch }}-${{ matrix.platform }} path: | - ${{ github.workspace }}/install/bin/snail-server* - ${{ github.workspace }}/install/bin/info.txt + ${{ github.workspace }}/install/server/bin/snail-server* + ${{ github.workspace }}/install/server/bin/info.txt + + - name: Upload tool binaries + uses: actions/upload-artifact@v4 + if: runner.os != 'Linux' || matrix.compiler == 'gcc' + with: + name: snail-tools-${{ matrix.arch }}-${{ matrix.platform }} + path: | + ${{ github.workspace }}/install/tools/bin/app_* + ${{ github.workspace }}/install/tools/bin/info.txt deploy-head: name: "Deploy head" diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 3aab630..e5d8d40 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -16,7 +16,7 @@ jobs: - name: Run clang-format uses: DoozyX/clang-format-lint-action@v0.16.2 with: - source: './snail ./tests' + source: './snail ./tests ./apps' exclude: './snail/common/third_party' extensions: 'cpp,hpp' clangFormatVersion: 16 diff --git a/.github/workflows/test-data.yml b/.github/workflows/test-data.yml index c52b392..550905c 100644 --- a/.github/workflows/test-data.yml +++ b/.github/workflows/test-data.yml @@ -41,8 +41,8 @@ jobs: - name: Install Records run: ninja install-records - - name: Pack & Upload rests - uses: actions/upload-artifact@v3 + - name: Pack & Upload results + uses: actions/upload-artifact@v4 with: name: test-data-${{ matrix.run-on }} path: ${{ github.workspace }}/tests/apps/*/dist/** diff --git a/CMakeLists.txt b/CMakeLists.txt index d53e382..c391e3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ include(CodeCoverage) option(BUILD_TESTING "Whether to build unit & integration tests" ON) cmake_dependent_option(SNAIL_ENABLE_CODE_COVERAGE "Enable code coverage for tests" OFF BUILD_TESTING OFF) +option(SNAIL_BUILD_TOOLS "Whether to build some debugging tools" ON) + option(SNAIL_WITH_LLVM "Required to resolve symbols from PDB and DWARF files." ON) option(SNAIL_ENABLE_SYSTEMTESTS "Whether to enable system testing" ON) @@ -84,6 +86,11 @@ endif() add_subdirectory(snail) +if(SNAIL_BUILD_TOOLS) + # Just for testing/development + add_subdirectory(apps) +endif() + # ======= # Tests diff --git a/CMakePresets.json b/CMakePresets.json index d7df8ff..04ff0ec 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -37,6 +37,10 @@ "SNAIL_ENABLE_CODE_COVERAGE": { "type": "BOOL", "value": "ON" + }, + "SNAIL_BUILD_TOOLS": { + "type": "BOOL", + "value": "OFF" } } } diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 2320c74..32b9066 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -8,3 +8,13 @@ target_link_libraries(app_perf_data_file PRIVATE compile_options perf_data) add_executable(app_analysis analysis.cpp) target_link_libraries(app_analysis PRIVATE compile_options analysis) + +install( + TARGETS + app_etl_file + app_perf_data_file + app_analysis + COMPONENT + tools + RUNTIME DESTINATION bin +) diff --git a/apps/etl_file.cpp b/apps/etl_file.cpp index 99afee3..abaafbb 100644 --- a/apps/etl_file.cpp +++ b/apps/etl_file.cpp @@ -7,6 +7,7 @@ # include #endif +#include #include #include #include @@ -15,6 +16,8 @@ #include +#include + #include #include #include @@ -73,37 +76,6 @@ std::string_view group_to_string(etl::parser::event_trace_group group) return "UNKNOWN"; } -template - requires std::same_as || - std::same_as || - std::same_as -auto make_key(const T& trace_header) -{ - return etl::detail::group_handler_key{ - trace_header.packet().group(), - trace_header.packet().type(), - trace_header.version()}; -} - -template - requires std::same_as || - std::same_as -auto make_key(const T& trace_header) -{ - return etl::detail::guid_handler_key{ - trace_header.guid().instantiate(), - trace_header.trace_class().type(), - trace_header.trace_class().version()}; -} - -auto make_key(const etl::parser::event_header_trace_header_view& trace_header) -{ - return etl::detail::guid_handler_key{ - trace_header.provider_id().instantiate(), - trace_header.event_descriptor().id(), - trace_header.event_descriptor().version()}; -} - std::string extract_application_name(std::string_view application_path) { if(application_path.empty()) return "etl_file"; @@ -118,13 +90,16 @@ void print_usage(std::string_view application_path) << " Path to the *.etl file to be read.\n" << "Options:\n" << " --help, -h Show this help text.\n" - << " --unsupported Print unsupported events summary.\n" + << " --summary Print event count summary.\n" << " --dump-headers Dump event buffers.\n" << " --dump-events Dump event buffers.\n" << " --dump Dump event buffers.\n" + << " --buffers Print buffer headers.\n" << " --header Print header event.\n" << " --config Print kernel config events.\n" << " --perfinfo Print kernel perfinfo events (does not include samples).\n" + << " --samples Print kernel sample events.\n" + << " --stacks Print stack events.\n" << " --config-ex Print XPerf extended config events.\n" << " --vs-diag Print events from the VS Diagnostics Hub.\n" << " --pid Process ID of the process of interest. Pass 'any' to show\n" @@ -150,14 +125,17 @@ struct options { std::filesystem::path file_path; - bool show_unsupported_summary = false; + bool show_events_summary = false; bool dump_trace_headers = false; bool dump_events = false; + bool show_buffers = false; bool show_header = false; bool show_config = false; bool show_perfinfo = false; + bool show_samples = false; + bool show_stacks = false; bool show_config_ex = false; bool show_vs_diag = false; @@ -182,9 +160,9 @@ options parse_command_line(int argc, char* argv[]) // NOLINT(modernize-avoid-c-a { help = true; } - else if(current_arg == "--unsupported") + else if(current_arg == "--summary") { - result.show_unsupported_summary = true; + result.show_events_summary = true; } else if(current_arg == "--dump-headers") { @@ -199,6 +177,10 @@ options parse_command_line(int argc, char* argv[]) // NOLINT(modernize-avoid-c-a result.dump_trace_headers = true; result.dump_events = true; } + else if(current_arg == "--buffers") + { + result.show_buffers = true; + } else if(current_arg == "--header") { result.show_header = true; @@ -211,6 +193,14 @@ options parse_command_line(int argc, char* argv[]) // NOLINT(modernize-avoid-c-a { result.show_perfinfo = true; } + else if(current_arg == "--samples") + { + result.show_samples = true; + } + else if(current_arg == "--stacks") + { + result.show_stacks = true; + } else if(current_arg == "--config-ex") { result.show_config_ex = true; @@ -229,7 +219,9 @@ options parse_command_line(int argc, char* argv[]) // NOLINT(modernize-avoid-c-a } else { - result.process_of_interest = atoi(next_arg.data()); // We know that this is actually null-terminated + result.process_of_interest.emplace(); + auto chars_result = std::from_chars(next_arg.data(), next_arg.data() + next_arg.size(), result.process_of_interest.value()); + if(chars_result.ec != std::errc{}) print_error_and_exit(application_path, "Invalid argument for --pid."); } } else if(current_arg == "--only") @@ -303,6 +295,123 @@ bool should_ignore(const options& opts, std::string_view event_name) return false; } +constexpr std::string_view get_guid_provider_name(const common::guid& guid) +{ + if(guid == etl::parser::image_id_guid || + guid == etl::parser::system_config_ex_guid) return "XPerf"; + if(guid == etl::parser::vs_diagnostics_hub_guid) return "VS"; + return "Unknown"; +} + +template +void register_known_event_names(std::unordered_map& known_event_names) +{ + // static_assert(is_group_event); + for(const auto& event_identifier : EventType::event_types) + { + const auto key = etl::detail::group_handler_key{event_identifier.group, event_identifier.type, EventType::event_version}; + + if constexpr(EventType::event_types.size() == 1) + { + known_event_names[key] = std::format("Kernel:{}-V{}", EventType::event_name, EventType::event_version); + } + else + { + known_event_names[key] = std::format("Kernel:{}:{}-V{}", EventType::event_name, event_identifier.name, EventType::event_version); + } + } +} + +template +void register_known_event_names(std::unordered_map& known_event_names) +{ + // static_assert(!is_group_event); + for(const auto& event_identifier : EventType::event_types) + { + const auto key = etl::detail::guid_handler_key{event_identifier.guid, event_identifier.type, EventType::event_version}; + const auto provider_name = get_guid_provider_name(key.guid); + + if constexpr(EventType::event_types.size() == 1) + { + known_event_names[key] = std::format("{}:{}-V{}", provider_name, EventType::event_name, EventType::event_version); + } + else + { + known_event_names[key] = std::format("{}:{}:{}-V{}", provider_name, EventType::event_name, event_identifier.name, EventType::event_version); + } + } +} + +std::string try_get_known_event_name(const etl::detail::group_handler_key& key, + const std::unordered_map& known_event_names) +{ + const auto iter = known_event_names.find(key); + if(iter != known_event_names.end()) return iter->second; + + return std::format("Unknown event: group {} ; type {} ; version {}", group_to_string(key.group), (int)key.type, key.version); +} + +std::string try_get_known_event_name(const etl::detail::guid_handler_key& key, + const std::unordered_map& known_event_names) +{ + const auto iter = known_event_names.find(key); + if(iter != known_event_names.end()) return iter->second; + + return std::format("Unknown event: guid {} ; type {} ; version {}", key.guid.to_string(true), key.type, key.version); +} + +class counting_event_observer : public etl::dispatching_event_observer +{ +public: + std::function buffer_header_callback_; + + std::unordered_map handled_group_event_counts; + std::unordered_map handled_guid_event_counts; + std::unordered_map unknown_group_event_counts; + std::unordered_map unknown_guid_event_counts; + + std::unordered_map known_group_event_names; + std::unordered_map known_guid_event_names; + + std::string_view current_event_name; // hacky way to sneak the event name into the handler routines. + + virtual void handle_buffer(const etl::etl_file::header_data& file_header, + const etl::parser::wmi_buffer_header_view& buffer_header) override + { + if(!buffer_header_callback_) return; + buffer_header_callback_(file_header, buffer_header); + } + +protected: + virtual void pre_handle([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::detail::group_handler_key& key, + [[maybe_unused]] const etl::any_group_trace_header& trace_header, + [[maybe_unused]] std::span user_data, + bool has_known_handler) override + { + if(has_known_handler) + { + ++handled_group_event_counts[key]; + current_event_name = known_group_event_names.at(key); + } + else ++unknown_group_event_counts[key]; + } + + virtual void pre_handle([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::detail::guid_handler_key& key, + [[maybe_unused]] const etl::any_guid_trace_header& trace_header, + [[maybe_unused]] std::span user_data, + bool has_known_handler) override + { + if(has_known_handler) + { + ++handled_guid_event_counts[key]; + current_event_name = known_guid_event_names.at(key); + } + else ++unknown_guid_event_counts[key]; + } +}; + } // namespace int main(int argc, char* argv[]) @@ -326,84 +435,113 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } - etl::dispatching_event_observer observer; - - std::unordered_map unprocessed_guid_event_counts; - std::unordered_map unprocessed_group_event_counts; - std::size_t sample_count = 0; - std::size_t stack_count = 0; - - const std::unordered_map known_guid_event_names = { - {etl::detail::guid_handler_key{etl::parser::image_id_guid, 32, 2}, "XPerf:ImageIdV2-DbgIdNone" }, - {etl::detail::guid_handler_key{etl::parser::image_id_guid, 38, 2}, "XPerf:ImageIdV2-DbgIdPPdb" }, - {etl::detail::guid_handler_key{etl::parser::image_id_guid, 40, 1}, "XPerf:ImageIdV2-DbgIdDeterm" }, - {etl::detail::guid_handler_key{etl::parser::image_id_guid, 64, 0}, "XPerf:ImageIdV2-DbgIdFileVersion" }, - {etl::detail::guid_handler_key{etl::parser::system_config_ex_guid, 34, 0}, "XPerf:SysConfigExV0-UnknownVolume"} + counting_event_observer observer; + + std::size_t sample_count = 0; + std::size_t stack_count = 0; + + std::unordered_map thread_to_process; + + // Pre-populate with names of events that we know, but which we do not support (yet). + // Most of those events should not be important for the functionality of a performance profiler, + // so we will probably never implement them. + observer.known_group_event_names = std::unordered_map{ + {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 8, 2}, "Kernel:EventTrace-RDComplete-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 64, 2}, "Kernel:EventTrace-DbgIdRSDS-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 66, 2}, "Kernel:EventTrace-BuildInfo-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::process, 11, 2}, "Kernel:Process-Terminate-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::process, 39, 5}, "Kernel:Process-TypeGroup1:Defunct-V5" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::image, 33, 2}, "Kernel:Image-KernelImageBase-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::image, 34, 2}, "Kernel:Image-HypercallPage-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 13, 2}, "Kernel:SystemConfig-Nic-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 14, 2}, "Kernel:SystemConfig-Video-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 15, 3}, "Kernel:SystemConfig-Services-V3" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 16, 2}, "Kernel:SystemConfig-Power-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 21, 3}, "Kernel:SystemConfig-Irq-V3" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 23, 2}, "Kernel:SystemConfig-IDEChannel-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 24, 2}, "Kernel:SystemConfig-NumaNode-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 25, 2}, "Kernel:SystemConfig-Platform-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 26, 2}, "Kernel:SystemConfig-ProcGroup-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 27, 2}, "Kernel:SystemConfig-ProcNumber-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 28, 2}, "Kernel:SystemConfig-Dpi-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 29, 2}, "Kernel:SystemConfig-CodeIntegrity-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 30, 2}, "Kernel:SystemConfig-TelemetryInfo-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 31, 2}, "Kernel:SystemConfig-Defrag-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 33, 2}, "Kernel:SystemConfig-DeviceFamily-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 34, 2}, "Kernel:SystemConfig-FlightIds-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 35, 2}, "Kernel:SystemConfig-Processors-V2" }, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 36, 2}, "Kernel:SystemConfig-Virtualization-V2"}, + {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 37, 2}, "Kernel:SystemConfig-Boot-V2" }, }; - const std::unordered_map known_group_event_names = { - {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 5, 2}, "Kernel:EventTraceV2-ExtensionTypeGroup-5:Extension" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 32, 2}, "Kernel:EventTraceV2-ExtensionTypeGroup-32:EndExtension"}, - {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 8, 2}, "Kernel:EventTraceV2-RDComplete" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 64, 2}, "Kernel:EventTraceV2-DbgIdRSDS" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::header, 66, 2}, "Kernel:EventTraceV2-BuildInfo" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::process, 11, 2}, "Kernel:ProcessV2-Terminate" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::process, 39, 5}, "Kernel:ProcessV5-Defunct" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::image, 33, 2}, "Kernel:ImageV2-KernelImageBase" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::image, 34, 2}, "Kernel:ImageV2-HypercallPage" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 10, 3}, "Kernel:SysConfigV3-Cpu" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 13, 2}, "Kernel:SysConfigV2-Nic" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 14, 2}, "Kernel:SysConfigV2-Video" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 15, 3}, "Kernel:SysConfigV3-Services" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 16, 2}, "Kernel:SysConfigV2-Power" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 21, 3}, "Kernel:SysConfigV3-Irq" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 25, 2}, "Kernel:SysConfigV2-Platform" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 28, 2}, "Kernel:SysConfigV2-Dpi" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 29, 2}, "Kernel:SysConfigV2-CodeIntegrity" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 30, 2}, "Kernel:SysConfigV2-TelemetryInfo" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 31, 2}, "Kernel:SysConfigV2-Defrag" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 33, 2}, "Kernel:SysConfigV2-DeviceFamily" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 34, 2}, "Kernel:SysConfigV2-FlightIds" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 35, 2}, "Kernel:SysConfigV2-Processors" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 36, 2}, "Kernel:SysConfigV2-Virtualization" }, - {etl::detail::group_handler_key{etl::parser::event_trace_group::config, 37, 2}, "Kernel:SysConfigV2-Boot" } + observer.known_guid_event_names = std::unordered_map{ + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 32, 2}, "XPerf:ImageId-DbgIdNone-V2" }, + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 34, 2}, "XPerf:ImageId-34?-V2" }, + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 38, 2}, "XPerf:ImageId-DbgIdPPdb-V2" }, + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 39, 1}, "XPerf:ImageId-39?-V1" }, // Error / Embedded PDB? + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 40, 1}, "XPerf:ImageId-DbgIdDeterm-V1" }, + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 41, 1}, "XPerf:ImageId-41?-V1" }, // Error / Embedded PDB? + {etl::detail::guid_handler_key{etl::parser::image_id_guid, 64, 0}, "XPerf:ImageId-DbgIdFileVersion-V0" }, + {etl::detail::guid_handler_key{etl::parser::system_config_ex_guid, 34, 0}, "XPerf:SystemConfigEx-UnknownVolume-V0"}, + {etl::detail::guid_handler_key{etl::parser::system_config_ex_guid, 36, 0}, "XPerf:SystemConfigEx-36?-V0" }, // NetworkInterface? }; // Unknown events { observer.register_unknown_event( - [&unprocessed_guid_event_counts]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::any_guid_trace_header& header, - [[maybe_unused]] const std::span& event_data) + [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::any_guid_trace_header& header, + const std::span& event_data) { - const auto header_key = std::visit([](const auto& header) - { return make_key(header); }, - header); - ++unprocessed_guid_event_counts[header_key]; + if(options.dump_events) common::detail::dump_buffer(event_data, 0, event_data.size(), "event"); }); observer.register_unknown_event( - [&unprocessed_group_event_counts]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::any_group_trace_header& header, - [[maybe_unused]] const std::span& event_data) + [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::any_group_trace_header& header, + const std::span& event_data) { - const auto header_key = std::visit([](const auto& header) - { return make_key(header); }, - header); - ++unprocessed_group_event_counts[header_key]; + if(options.dump_events) common::detail::dump_buffer(event_data, 0, event_data.size(), "event"); }); } + // Buffer + observer.buffer_header_callback_ = [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::parser::wmi_buffer_header_view& buffer_header) + { + if(!options.show_buffers) return; + + std::cout << "Buffer Header:\n"; + + std::cout << std::format(" buffer_size: {}\n", buffer_header.wnode().buffer_size()); + std::cout << std::format(" saved_offset: {}\n", buffer_header.wnode().saved_offset()); + std::cout << std::format(" current_offset: {}\n", buffer_header.wnode().current_offset()); + std::cout << std::format(" reference_count: {}\n", buffer_header.wnode().reference_count()); + std::cout << std::format(" timestamp: {}\n", buffer_header.wnode().timestamp()); + std::cout << std::format(" sequence_number: {}\n", buffer_header.wnode().sequence_number()); + std::cout << std::format(" clock: {}\n", buffer_header.wnode().clock()); + std::cout << std::format(" processor_index: {}\n", buffer_header.wnode().client_context().processor_index()); + std::cout << std::format(" logger_id: {}\n", buffer_header.wnode().client_context().logger_id()); + std::cout << std::format(" state: {}\n", (int)buffer_header.wnode().state()); + std::cout << std::format(" offset: {}\n", buffer_header.offset()); + std::cout << std::format(" buffer_flag: {}\n", buffer_header.buffer_flag()); + std::cout << std::format(" buffer_type: {}\n", (int)buffer_header.buffer_type()); + std::cout << std::format(" start_time: {}\n", buffer_header.start_time()); + std::cout << std::format(" start_perf_clock: {}\n", buffer_header.start_perf_clock()); + }; + // Kernel: header { + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::event_trace_v2_header_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::event_trace_v2_header_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_header) return; - const auto event_name = "Kernel:EventTraceV2-Header"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}:\n", header.timestamp, event_name); + std::cout << std::format("@{} {:30}:\n", header.timestamp, observer.current_event_name); std::cout << std::format(" buffer_size: {}\n", event.buffer_size()); std::cout << std::format(" os_version_major: {}\n", event.os_version_major()); std::cout << std::format(" os_version_minor: {}\n", event.os_version_minor()); @@ -421,7 +559,7 @@ int main(int argc, char* argv[]) std::cout << std::format(" events_lost: {}\n", event.events_lost()); std::cout << std::format(" logger_name: {}\n", event.logger_name()); std::cout << std::format(" log_file_name: {}\n", event.log_file_name()); - // std::cout << std::format(" time_zone_information: {}\n", event.time_zone_information()); + std::cout << std::format(" time_zone.bias: {}\n", event.time_zone_information().bias()); std::cout << std::format(" boot_time: {}\n", event.boot_time()); std::cout << std::format(" perf_freq: {}\n", event.perf_freq()); std::cout << std::format(" start_time: {}\n", event.start_time()); @@ -437,58 +575,66 @@ int main(int argc, char* argv[]) // Kernel: config { + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::system_config_v3_cpu_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::system_config_v3_cpu_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config) return; - const auto event_name = "Kernel:SysConfigV3-CPU"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: computer_name '{}' architecture {}...\n", header.timestamp, event_name, utf8::utf16to8(event.computer_name()), event.processor_architecture()); + std::cout << std::format("@{} {:30}: computer_name '{}' architecture {}...\n", header.timestamp, observer.current_event_name, utf8::utf16to8(event.computer_name()), event.processor_architecture()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::system_config_v2_physical_disk_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::system_config_v2_physical_disk_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config) return; - const auto event_name = "Kernel:SysConfigV2-PhyDisk"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: disk_number {} partition_count {} ...\n", header.timestamp, event_name, event.disk_number(), event.partition_count()); + std::cout << std::format("@{} {:30}: disk_number {} partition_count {} ...\n", header.timestamp, observer.current_event_name, event.disk_number(), event.partition_count()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::system_config_v2_logical_disk_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::system_config_v2_logical_disk_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config) return; - const auto event_name = "Kernel:SysConfigV2-LogDisk"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: disk_number {} partition_number {} drive_letter {} ...\n", header.timestamp, event_name, event.disk_number(), event.partition_number(), utf8::utf16to8(event.drive_letter())); + std::cout << std::format("@{} {:30}: disk_number {} partition_number {} drive_letter {} ...\n", header.timestamp, observer.current_event_name, event.disk_number(), event.partition_number(), utf8::utf16to8(event.drive_letter())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::system_config_v5_pnp_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::system_config_v5_pnp_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config) return; - const auto event_name = "Kernel:SysConfigV5-PNP"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: device_description '{}' friendly_name '{}' ...\n", header.timestamp, event_name, utf8::utf16to8(event.device_description()), utf8::utf16to8(event.friendly_name())); + std::cout << std::format("@{} {:30}: device_description '{}' friendly_name '{}' ...\n", header.timestamp, observer.current_event_name, utf8::utf16to8(event.device_description()), utf8::utf16to8(event.friendly_name())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -497,38 +643,46 @@ int main(int argc, char* argv[]) // Kernel: perfinfo/stack { + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options, &stack_count]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::stackwalk_v2_stack_event_view& event) + [&options, &observer, &stack_count]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::stackwalk_v2_stack_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + const auto process_id = event.process_id(); if(!options.all_processes && process_id != options.process_of_interest) return; ++stack_count; + + if(!options.show_stacks) return; + + if(should_ignore(options, observer.current_event_name)) return; + + std::cout << std::format("@{} {:30}: event time {} pid {} tid {} count {}\n", header.timestamp, observer.current_event_name, event.event_timestamp(), event.process_id(), event.thread_id(), event.stack_size()); + + if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); + if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options, &sample_count]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::perfinfo_v2_sampled_profile_event_view& event) + [&options, &observer, &sample_count, &thread_to_process]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + [[maybe_unused]] const etl::parser::perfinfo_v2_sampled_profile_event_view& event) { - const auto thread_id = event.thread_id(); - const auto process_id = thread_id; // TODO: map thread to process - if(!options.all_processes && process_id != options.process_of_interest) return; + assert(event.dynamic_size() == event.buffer().size()); + + auto process_id = thread_to_process.find(event.thread_id()); + if(!options.all_processes && (process_id != thread_to_process.end() && process_id->second != options.process_of_interest)) return; ++sample_count; - }); - observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::perfinfo_v3_sampled_profile_interval_event_view& event) - { - if(!options.show_perfinfo) return; - const auto event_name = std::format("Kernel:PerfInfoV3-SampledProfileInterval-{}", header.type); - if(should_ignore(options, event_name)) return; + if(!options.show_samples) return; - std::cout << std::format("@{} {:30}: source {} new-interval {} old-interval {} source-name '{}'\n", header.timestamp, event_name, event.source(), event.new_interval(), event.old_interval(), utf8::utf16to8(event.source_name())); + if(should_ignore(options, observer.current_event_name)) return; + + std::cout << std::format("@{} {:30}: thread {} count {} ip {:#018x}\n", header.timestamp, observer.current_event_name, event.thread_id(), event.count(), event.instruction_pointer()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -537,66 +691,80 @@ int main(int argc, char* argv[]) // Kernel: process/thread { + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::process_v4_type_group1_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::process_v4_type_group1_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + + assert(event.dynamic_size() == event.buffer().size()); + const auto process_id = event.process_id(); if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = std::format("Kernel:ProcessV4-Group1-{}", header.type); - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} filename '{}' cmd '{}' unique {} flags {} ...\n", header.timestamp, event_name, process_id, event.image_filename(), utf8::utf16to8(event.command_line()), event.unique_process_key(), event.flags()); + std::cout << std::format("@{} {:30}: pid {} filename '{}' cmd '{}' unique {} flags {} ...\n", header.timestamp, observer.current_event_name, process_id, event.image_filename(), utf8::utf16to8(event.command_line()), event.unique_process_key(), event.flags()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::thread_v3_type_group1_event_view& event) + [&options, &observer, &thread_to_process]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::thread_v3_type_group1_event_view& event) { - const auto process_id = event.process_id(); + assert(event.dynamic_size() == event.buffer().size()); + + const auto process_id = event.process_id(); + thread_to_process[event.thread_id()] = process_id; + if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = std::format("Kernel:ThreadV3-Group1-{}", header.type); - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} tid {} ...\n", header.timestamp, event_name, process_id, event.thread_id()); + std::cout << std::format("@{} {:30}: pid {} tid {} ...\n", header.timestamp, observer.current_event_name, process_id, event.thread_id()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::thread_v4_type_group1_event_view& event) + [&options, &observer, &thread_to_process]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::thread_v4_type_group1_event_view& event) { - const auto process_id = event.process_id(); + assert(event.dynamic_size() == event.buffer().size()); + + const auto process_id = event.process_id(); + thread_to_process[event.thread_id()] = process_id; + if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = std::format("Kernel:ThreadV4-Group1-{}", header.type); - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} tid {} name {}...\n", header.timestamp, event_name, process_id, event.thread_id(), utf8::utf16to8(event.thread_name())); + std::cout << std::format("@{} {:30}: pid {} tid {} name {}...\n", header.timestamp, observer.current_event_name, process_id, event.thread_id(), utf8::utf16to8(event.thread_name())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::thread_v2_set_name_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::thread_v2_set_name_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + const auto process_id = event.process_id(); if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = "Kernel:ThreadV2-SetName"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} tid {} name '{}'\n", header.timestamp, event_name, process_id, event.thread_id(), utf8::utf16to8(event.thread_name())); + std::cout << std::format("@{} {:30}: pid {} tid {} name '{}'\n", header.timestamp, observer.current_event_name, process_id, event.thread_id(), utf8::utf16to8(event.thread_name())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -605,18 +773,20 @@ int main(int argc, char* argv[]) // Kernel: image { + register_known_event_names(observer.known_group_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::image_v3_load_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::image_v3_load_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + const auto process_id = event.process_id(); if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = std::format("Kernel:ImageV3-Load-{}", header.type); - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} name '{}' image-base {:#0x} checksum {} time-date-stamp {}\n", header.timestamp, event_name, process_id, utf8::utf16to8(event.file_name()), event.image_base(), event.image_checksum(), event.time_date_stamp()); + std::cout << std::format("@{} {:30}: pid {} name '{}' image-base {:#0x} checksum {} time-date-stamp {}\n", header.timestamp, observer.current_event_name, process_id, utf8::utf16to8(event.file_name()), event.image_base(), event.image_checksum(), event.time_date_stamp()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -625,34 +795,38 @@ int main(int argc, char* argv[]) // Kernel-trace-control (Xperf): image { + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::image_id_v2_info_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::image_id_v2_info_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + const auto process_id = event.process_id(); if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = "XPerf:ImageIdV2-Info"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} name '{}' image_base {:#0x} time_stamp {}\n", header.timestamp, event_name, process_id, utf8::utf16to8(event.original_file_name()), event.image_base(), event.time_date_stamp()); + std::cout << std::format("@{} {:30}: pid {} name '{}' image_base {:#0x} time_stamp {}\n", header.timestamp, observer.current_event_name, process_id, utf8::utf16to8(event.original_file_name()), event.image_base(), event.time_date_stamp()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::image_id_v2_dbg_id_pdb_info_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::image_id_v2_dbg_id_pdb_info_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + const auto process_id = event.process_id(); if(!options.all_processes && process_id != options.process_of_interest) return; - const auto event_name = "XPerf:ImageIdV2-DbgIdPdbInfo"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} image-base {:#0x} guid {} age {} pdb '{}'\n", header.timestamp, event_name, process_id, event.image_base(), event.guid().instantiate().to_string(), event.age(), event.pdb_file_name()); + std::cout << std::format("@{} {:30}: pid {} image-base {:#0x} guid {} age {} pdb '{}'\n", header.timestamp, observer.current_event_name, process_id, event.image_base(), event.guid().instantiate().to_string(), event.age(), event.pdb_file_name()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -661,44 +835,50 @@ int main(int argc, char* argv[]) // Kernel-trace-control (Xperf): system-config-ex { + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::system_config_ex_v0_build_info_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::system_config_ex_v0_build_info_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config_ex) return; - const auto event_name = "XPerf:SysConfigExV0-BuildInfo"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: install-date {} build-lab '{}' product-name '{}'\n", header.timestamp, event_name, event.install_date(), utf8::utf16to8(event.build_lab()), utf8::utf16to8(event.product_name())); + std::cout << std::format("@{} {:30}: install-date {} build-lab '{}' product-name '{}'\n", header.timestamp, observer.current_event_name, event.install_date(), utf8::utf16to8(event.build_lab()), utf8::utf16to8(event.product_name())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::system_config_ex_v0_system_paths_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::system_config_ex_v0_system_paths_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config_ex) return; - const auto event_name = "XPerf:SysConfigExV0-SysPaths"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: sys-dir '{}' sys-win-dir '{}'\n", header.timestamp, event_name, utf8::utf16to8(event.system_directory()), utf8::utf16to8(event.system_windows_directory())); + std::cout << std::format("@{} {:30}: sys-dir '{}' sys-win-dir '{}'\n", header.timestamp, observer.current_event_name, utf8::utf16to8(event.system_directory()), utf8::utf16to8(event.system_windows_directory())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::system_config_ex_v0_volume_mapping_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::system_config_ex_v0_volume_mapping_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_config_ex) return; - const auto event_name = "XPerf:SysConfigExV0-VolumeMapping"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: nt-path '{}' dos-path '{}'\n", header.timestamp, event_name, utf8::utf16to8(event.nt_path()), utf8::utf16to8(event.dos_path())); + std::cout << std::format("@{} {:30}: nt-path '{}' dos-path '{}'\n", header.timestamp, observer.current_event_name, utf8::utf16to8(event.nt_path()), utf8::utf16to8(event.dos_path())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -707,58 +887,66 @@ int main(int argc, char* argv[]) // VS-Diagnostics-Hub { + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::vs_diagnostics_hub_target_profiling_started_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::vs_diagnostics_hub_target_profiling_started_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_vs_diag) return; - const auto event_name = "VsDiagHub:TargetProfilingStarted"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} timestamp {}\n", header.timestamp, event_name, event.process_id(), event.timestamp()); + std::cout << std::format("@{} {:30}: pid {} timestamp {}\n", header.timestamp, observer.current_event_name, event.process_id(), event.timestamp()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - const etl::common_trace_header& header, - const etl::parser::vs_diagnostics_hub_target_profiling_stopped_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + const etl::common_trace_header& header, + const etl::parser::vs_diagnostics_hub_target_profiling_stopped_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_vs_diag) return; - const auto event_name = "VsDiagHub:TargetProfilingStopped"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: pid {} timestamp {}\n", header.timestamp, event_name, event.process_id(), event.timestamp()); + std::cout << std::format("@{} {:30}: pid {} timestamp {}\n", header.timestamp, observer.current_event_name, event.process_id(), event.timestamp()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::vs_diagnostics_hub_machine_info_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::vs_diagnostics_hub_machine_info_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_vs_diag) return; - const auto event_name = "VsDiagHub:MachineInfo"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: architecture {} os '{}' name '{}'\n", header.timestamp, event_name, (int)event.architecture(), utf8::utf16to8(event.os_description()), utf8::utf16to8(event.name())); + std::cout << std::format("@{} {:30}: architecture {} os '{}' name '{}'\n", header.timestamp, observer.current_event_name, (int)event.architecture(), utf8::utf16to8(event.os_description()), utf8::utf16to8(event.name())); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); }); + register_known_event_names(observer.known_guid_event_names); observer.register_event( - [&options]([[maybe_unused]] const etl::etl_file::header_data& file_header, - [[maybe_unused]] const etl::common_trace_header& header, - const etl::parser::vs_diagnostics_hub_counter_info_event_view& event) + [&options, &observer]([[maybe_unused]] const etl::etl_file::header_data& file_header, + [[maybe_unused]] const etl::common_trace_header& header, + const etl::parser::vs_diagnostics_hub_counter_info_event_view& event) { + assert(event.dynamic_size() == event.buffer().size()); + if(!options.show_vs_diag) return; - const auto event_name = "VsDiagHub:CounterInfo"; - if(should_ignore(options, event_name)) return; + if(should_ignore(options, observer.current_event_name)) return; - std::cout << std::format("@{} {:30}: Count {} timestamp {} value {}\n", header.timestamp, event_name, (int)event.counter(), event.timestamp(), event.value()); + std::cout << std::format("@{} {:30}: Count {} timestamp {} value {}\n", header.timestamp, observer.current_event_name, (int)event.counter(), event.timestamp(), event.value()); if(options.dump_trace_headers) common::detail::dump_buffer(header.buffer, 0, header.buffer.size(), "header"); if(options.dump_events) common::detail::dump_buffer(event.buffer(), 0, event.buffer().size(), "event"); @@ -769,34 +957,42 @@ int main(int argc, char* argv[]) file.process(observer); std::cout << "\n"; - std::cout << std::format("Number of samples: {}\n", sample_count); + std::cout << "Number of samples:\n"; + std::cout << std::format(" Regular Profile: {}\n", sample_count); std::cout << std::format("Number of stacks: {}\n", stack_count); - if(options.show_unsupported_summary) + if(options.show_events_summary) { std::cout << "\n"; - std::cout << "Unsupported events:\n"; - for(const auto& [key, count] : unprocessed_group_event_counts) + std::cout << "Supported Events:\n"; + std::vector> event_counts; + for(const auto& [key, count] : observer.handled_group_event_counts) { - if(known_group_event_names.contains(key)) - { - std::cout << std::format(" Unsupported: '{}' | count {}\n", known_group_event_names.at(key), count); - } - else - { - std::cout << std::format(" Unknown : GROUP {} ; type {} ; version {} | count {}\n", group_to_string(key.group), (int)key.type, key.version, count); - } + event_counts.emplace_back(try_get_known_event_name(key, observer.known_group_event_names), count); } - for(const auto& [key, count] : unprocessed_guid_event_counts) + for(const auto& [key, count] : observer.handled_guid_event_counts) { - if(known_guid_event_names.contains(key)) - { - std::cout << std::format(" Unsupported: '{}' | count {}\n", known_guid_event_names.at(key), count); - } - else - { - std::cout << std::format(" Unknown : GUID {} ; type {} ; version {} | count {}\n", key.guid.to_string(true), key.type, key.version, count); - } + event_counts.emplace_back(try_get_known_event_name(key, observer.known_guid_event_names), count); + } + std::ranges::sort(event_counts); + for(const auto& [name, count] : event_counts) + { + std::cout << std::format(" {:60} : {}\n", name, count); + } + std::cout << "Unsupported Events:\n"; + event_counts.clear(); + for(const auto& [key, count] : observer.unknown_group_event_counts) + { + event_counts.emplace_back(try_get_known_event_name(key, observer.known_group_event_names), count); + } + for(const auto& [key, count] : observer.unknown_guid_event_counts) + { + event_counts.emplace_back(try_get_known_event_name(key, observer.known_guid_event_names), count); + } + std::ranges::sort(event_counts); + for(const auto& [name, count] : event_counts) + { + std::cout << std::format(" {:60} : {}\n", name, count); } } } diff --git a/snail/common/guid.hpp b/snail/common/guid.hpp index 973f71d..80ec46a 100644 --- a/snail/common/guid.hpp +++ b/snail/common/guid.hpp @@ -20,7 +20,7 @@ struct guid std::string to_string(bool insert_hyphen = false) const; - [[nodiscard]] friend bool operator==(const guid& lhs, const guid& rhs) noexcept + [[nodiscard]] constexpr friend bool operator==(const guid& lhs, const guid& rhs) noexcept { return lhs.data_1 == rhs.data_1 && lhs.data_2 == rhs.data_2 && diff --git a/snail/etl/dispatching_event_observer.cpp b/snail/etl/dispatching_event_observer.cpp index 499d99b..d41f45f 100644 --- a/snail/etl/dispatching_event_observer.cpp +++ b/snail/etl/dispatching_event_observer.cpp @@ -56,39 +56,9 @@ auto make_header_variant(const T& trace_header) return any_guid_trace_header{trace_header}; } -template -void handle_impl(const etl_file::header_data& file_header, - const HeaderType& trace_header, - std::span user_data, - const HandlersType& handlers, - const UnknownHandlersType& unknown_handlers) -{ - const auto key = make_key(trace_header); - - auto iter = handlers.find(key); - if(iter == handlers.end()) - { - if(!unknown_handlers.empty()) - { - const auto trace_header_variant = make_header_variant(trace_header); - for(const auto& handler : unknown_handlers) - { - handler(file_header, trace_header_variant, user_data); - } - } - return; - } - - const auto trace_header_variant = make_header_variant(trace_header); - for(const auto& handler : iter->second) - { - handler(file_header, trace_header_variant, user_data); - } -} - } // namespace -common_trace_header dispatching_event_observer::make_common_trace_header(const any_group_trace_header& trace_header_variant) +common_trace_header snail::etl::make_common_trace_header(const any_group_trace_header& trace_header_variant) { return std::visit( [](const auto& trace_header) @@ -101,7 +71,7 @@ common_trace_header dispatching_event_observer::make_common_trace_header(const a trace_header_variant); } -common_trace_header dispatching_event_observer::make_common_trace_header(const any_guid_trace_header& trace_header_variant) +common_trace_header snail::etl::make_common_trace_header(const any_guid_trace_header& trace_header_variant) { return std::visit( [](const T& trace_header) @@ -124,6 +94,38 @@ common_trace_header dispatching_event_observer::make_common_trace_header(const a trace_header_variant); } +template +void dispatching_event_observer::handle_impl(const etl_file::header_data& file_header, + const HeaderType& trace_header, + std::span user_data, + const HandlersType& handlers, + const UnknownHandlersType& unknown_handlers) +{ + const auto key = make_key(trace_header); + + auto iter = handlers.find(key); + if(iter == handlers.end()) + { + if(!unknown_handlers.empty()) + { + const auto trace_header_variant = make_header_variant(trace_header); + pre_handle(file_header, key, trace_header_variant, user_data, false); + for(const auto& handler : unknown_handlers) + { + handler(file_header, trace_header_variant, user_data); + } + } + return; + } + + const auto trace_header_variant = make_header_variant(trace_header); + pre_handle(file_header, key, trace_header_variant, user_data, true); + for(const auto& handler : iter->second) + { + handler(file_header, trace_header_variant, user_data); + } +} + void dispatching_event_observer::handle(const etl_file::header_data& file_header, const parser::system_trace_header_view& trace_header, std::span user_data) diff --git a/snail/etl/dispatching_event_observer.hpp b/snail/etl/dispatching_event_observer.hpp index 44ef22b..75ef48e 100644 --- a/snail/etl/dispatching_event_observer.hpp +++ b/snail/etl/dispatching_event_observer.hpp @@ -98,6 +98,9 @@ struct common_trace_header std::span buffer; }; +common_trace_header make_common_trace_header(const any_group_trace_header& trace_header_variant); +common_trace_header make_common_trace_header(const any_guid_trace_header& trace_header_variant); + template concept event_record_view = std::constructible_from, std::uint32_t>; @@ -156,6 +159,18 @@ class dispatching_event_observer : public event_observer requires unknown_event_handler inline void register_unknown_event(HandlerType&& handler); +protected: + virtual void pre_handle([[maybe_unused]] const etl_file::header_data& file_header, + [[maybe_unused]] const detail::group_handler_key& key, + [[maybe_unused]] const any_group_trace_header& trace_header, + [[maybe_unused]] std::span user_data, + [[maybe_unused]] bool has_known_handler) {} + virtual void pre_handle([[maybe_unused]] const etl_file::header_data& file_header, + [[maybe_unused]] const detail::guid_handler_key& key, + [[maybe_unused]] const any_guid_trace_header& trace_header, + [[maybe_unused]] std::span user_data, + [[maybe_unused]] bool has_known_handler) {} + private: using group_handler_dispatch_type = std::function)>; using guid_handler_dispatch_type = std::function)>; @@ -166,8 +181,12 @@ class dispatching_event_observer : public event_observer std::vector unknown_group_handlers_; std::vector unknown_guid_handlers_; - static common_trace_header make_common_trace_header(const any_group_trace_header& trace_header_variant); - static common_trace_header make_common_trace_header(const any_guid_trace_header& trace_header_variant); + template + void handle_impl(const etl_file::header_data& file_header, + const HeaderType& trace_header, + std::span user_data, + const HandlersType& handlers, + const UnknownHandlersType& unknown_handlers); }; template diff --git a/snail/etl/etl_file.cpp b/snail/etl/etl_file.cpp index ac99083..d9935ce 100644 --- a/snail/etl/etl_file.cpp +++ b/snail/etl/etl_file.cpp @@ -434,7 +434,7 @@ void etl_file::process(event_observer& callbacks) const auto buffer_exhausted = buffer_info.current_payload_offset >= buffer_info.payload_buffer.size(); if(buffer_exhausted) { - callbacks.handle(header_, parser::wmi_buffer_header_view(buffer_info.header_buffer)); + callbacks.handle_buffer(header_, parser::wmi_buffer_header_view(buffer_info.header_buffer)); auto& remaining_buffers = processor_data.remaining_buffers; diff --git a/snail/etl/etl_file.hpp b/snail/etl/etl_file.hpp index 806a191..aaeb035 100644 --- a/snail/etl/etl_file.hpp +++ b/snail/etl/etl_file.hpp @@ -59,7 +59,7 @@ class event_observer public: virtual ~event_observer() = default; - virtual void handle(const etl_file::header_data& /*file_header*/, const parser::wmi_buffer_header_view& /*buffer_header*/) {} + virtual void handle_buffer(const etl_file::header_data& /*file_header*/, const parser::wmi_buffer_header_view& /*buffer_header*/) {} virtual void handle(const etl_file::header_data& /*file_header*/, const parser::system_trace_header_view& /*trace_header*/, std::span /*user_data*/) {} virtual void handle(const etl_file::header_data& /*file_header*/, const parser::compact_trace_header_view& /*trace_header*/, std::span /*user_data*/) {} diff --git a/snail/etl/parser/records/kernel/config.hpp b/snail/etl/parser/records/kernel/config.hpp index 6f73896..68e7575 100644 --- a/snail/etl/parser/records/kernel/config.hpp +++ b/snail/etl/parser/records/kernel/config.hpp @@ -27,9 +27,10 @@ enum class drive_type : std::uint32_t // or `SystemConfig_V3_CPU:SystemConfig_V3` from wmicore.mof in WDK 10.0.22621.0 struct system_config_v3_cpu_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 3; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::config, 10, "cpu"}, + static inline constexpr std::string_view event_name = "SystemConfig-Cpu"; + static inline constexpr std::uint16_t event_version = 3; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::config, 10, "Cpu"}, }; using extract_view_dynamic_base::buffer; @@ -62,9 +63,10 @@ struct system_config_v3_cpu_event_view : private extract_view_dynamic_base // or `SystemConfig_V2_PhyDisk:SystemConfig_V2` from wmicore.mof in WDK 10.0.22621.0 struct system_config_v2_physical_disk_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::config, 11, "physical disk"}, + static inline constexpr std::string_view event_name = "SystemConfig-PhyDisk"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::config, 11, "PhyDisk"}, }; using extract_view_dynamic_base::buffer; @@ -100,9 +102,10 @@ struct system_config_v2_physical_disk_event_view : private extract_view_dynamic_ // or `SystemConfig_V2_LogDisk:SystemConfig_V2` from wmicore.mof in WDK 10.0.22621.0 struct system_config_v2_logical_disk_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::config, 12, "logical disk"}, + static inline constexpr std::string_view event_name = "SystemConfig-LogDisk"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::config, 12, "LogDisk"}, }; using extract_view_dynamic_base::buffer; @@ -137,9 +140,10 @@ struct system_config_v2_logical_disk_event_view : private extract_view_dynamic_b // or `SystemConfig_PnP:SystemConfig` from wmicore.mof in WDK 10.0.22621.0 struct system_config_v5_pnp_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 5; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::config, 22, "pnp"}, + static inline constexpr std::string_view event_name = "SystemConfig-Pnp"; + static inline constexpr std::uint16_t event_version = 5; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::config, 22, "Pnp"}, }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel/header.hpp b/snail/etl/parser/records/kernel/header.hpp index 1c36743..4b7e6d0 100644 --- a/snail/etl/parser/records/kernel/header.hpp +++ b/snail/etl/parser/records/kernel/header.hpp @@ -20,9 +20,10 @@ namespace snail::etl::parser { // `EventTrace_Header:EventTraceEvent` from wmicore.mof in WDK 10.0.22621.0 struct event_trace_v2_header_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::header, 0, "header"} + static inline constexpr std::string_view event_name = "EventTrace-Header"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::header, 0, "Header"} }; inline explicit event_trace_v2_header_event_view(std::span buffer) : diff --git a/snail/etl/parser/records/kernel/image.hpp b/snail/etl/parser/records/kernel/image.hpp index 75ae70f..12e57c6 100644 --- a/snail/etl/parser/records/kernel/image.hpp +++ b/snail/etl/parser/records/kernel/image.hpp @@ -21,12 +21,13 @@ namespace snail::etl::parser { // or `Image_Load:Image` from wmicore.mof in WDK 10.0.22621.0 struct image_v3_load_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 3; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::process, 10, "load" }, // For an unknown reason, this is reported as in the process group - event_identifier_group{event_trace_group::image, 2, "unload" }, - event_identifier_group{event_trace_group::image, 3, "dc_start"}, - event_identifier_group{event_trace_group::image, 4, "dc_end" } + static inline constexpr std::string_view event_name = "Image-Load"; + static inline constexpr std::uint16_t event_version = 3; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::process, 10, "Load" }, // For an unknown reason, this is reported as in the process group + event_identifier_group{event_trace_group::image, 2, "Unload" }, + event_identifier_group{event_trace_group::image, 3, "DcStart"}, + event_identifier_group{event_trace_group::image, 4, "DcEnd" } }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel/perfinfo.hpp b/snail/etl/parser/records/kernel/perfinfo.hpp index dfb7305..f5437dd 100644 --- a/snail/etl/parser/records/kernel/perfinfo.hpp +++ b/snail/etl/parser/records/kernel/perfinfo.hpp @@ -20,9 +20,10 @@ namespace snail::etl::parser { // or `SampledProfile:PerfInfo_V2` from wmicore.mof in WDK 10.0.22621.0 struct perfinfo_v2_sampled_profile_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::perfinfo, 46, "sample prof"} + static inline constexpr std::string_view event_name = "PerfInfo-SampledProfile"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::perfinfo, 46, "SampledProfile"} }; using extract_view_dynamic_base::buffer; @@ -39,10 +40,11 @@ struct perfinfo_v2_sampled_profile_event_view : private extract_view_dynamic_bas // `SampledProfileInterval_V3:PerfInfo` from wmicore.mof in WDK 10.0.22621.0 struct perfinfo_v3_sampled_profile_interval_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 3; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::perfinfo, 73, "collection start"}, - event_identifier_group{event_trace_group::perfinfo, 74, "collection end" } + static inline constexpr std::string_view event_name = "PerfInfo-SampledProfileInterval"; + static inline constexpr std::uint16_t event_version = 3; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::perfinfo, 73, "CollectionStart"}, + event_identifier_group{event_trace_group::perfinfo, 74, "CollectionEnd" } }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel/process.hpp b/snail/etl/parser/records/kernel/process.hpp index 43ccc8b..cdd527c 100644 --- a/snail/etl/parser/records/kernel/process.hpp +++ b/snail/etl/parser/records/kernel/process.hpp @@ -21,13 +21,14 @@ namespace snail::etl::parser { // or `Process_V4_TypeGroup1:Process_V4` from wmicore.mof in WDK 10.0.22621.0 struct process_v4_type_group1_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 4; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::process, 1, "load" }, - event_identifier_group{event_trace_group::process, 2, "unload" }, - event_identifier_group{event_trace_group::process, 3, "dc_start"}, - event_identifier_group{event_trace_group::process, 4, "dc_end" }, - event_identifier_group{event_trace_group::process, 39, "defunct" } + static inline constexpr std::string_view event_name = "Process-TypeGroup1"; + static inline constexpr std::uint16_t event_version = 4; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::process, 1, "Load" }, + event_identifier_group{event_trace_group::process, 2, "Unload" }, + event_identifier_group{event_trace_group::process, 3, "DcStart"}, + event_identifier_group{event_trace_group::process, 4, "DcEnd" }, + event_identifier_group{event_trace_group::process, 39, "Defunct"} }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel/stackwalk.hpp b/snail/etl/parser/records/kernel/stackwalk.hpp index afe8587..1c1c307 100644 --- a/snail/etl/parser/records/kernel/stackwalk.hpp +++ b/snail/etl/parser/records/kernel/stackwalk.hpp @@ -20,9 +20,10 @@ namespace snail::etl::parser { // `StackWalk_Event:StackWalk` from wmicore.mof in WDK 10.0.22621.0 struct stackwalk_v2_stack_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::stackwalk, 32, "stack"} + static inline constexpr std::string_view event_name = "StackWalk-Stack"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::stackwalk, 32, "Stack"} }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel/thread.hpp b/snail/etl/parser/records/kernel/thread.hpp index 4e064a7..e987bfa 100644 --- a/snail/etl/parser/records/kernel/thread.hpp +++ b/snail/etl/parser/records/kernel/thread.hpp @@ -20,9 +20,10 @@ namespace snail::etl::parser { // `ThreadSetName:Thread_V2` from wmicore.mof in WDK 10.0.22621.0 struct thread_v2_set_name_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::thread, 72, "set name"}, + static inline constexpr std::string_view event_name = "Thread-SetName"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::thread, 72, "SetName"}, }; using extract_view_dynamic_base::buffer; @@ -42,12 +43,13 @@ struct thread_v2_set_name_event_view : private extract_view_dynamic_base // `Thread_V3_TypeGroup1:Thread_V3` from wmicore.mof in WDK 10.0.22621.0 struct thread_v3_type_group1_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 3; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::thread, 1, "start" }, - event_identifier_group{event_trace_group::thread, 2, "end" }, - event_identifier_group{event_trace_group::thread, 3, "dc_start"}, - event_identifier_group{event_trace_group::thread, 4, "dc_end" } + static inline constexpr std::string_view event_name = "Thread-TypeGroup1"; + static inline constexpr std::uint16_t event_version = 3; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::thread, 1, "Start" }, + event_identifier_group{event_trace_group::thread, 2, "End" }, + event_identifier_group{event_trace_group::thread, 3, "DcStart"}, + event_identifier_group{event_trace_group::thread, 4, "DcEnd" } }; using extract_view_dynamic_base::buffer; @@ -90,12 +92,13 @@ struct thread_v3_type_group1_event_view : private extract_view_dynamic_base // `Thread_TypeGroup1:Thread_V4` from wmicore.mof in WDK 10.0.22621.0 struct thread_v4_type_group1_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 4; - static inline constexpr auto event_types = std::array{ - event_identifier_group{event_trace_group::thread, 1, "start" }, - event_identifier_group{event_trace_group::thread, 2, "end" }, - event_identifier_group{event_trace_group::thread, 3, "dc_start"}, - event_identifier_group{event_trace_group::thread, 4, "dc_end" } + static inline constexpr std::string_view event_name = "Thread-TypeGroup1"; + static inline constexpr std::uint16_t event_version = 4; + static inline constexpr auto event_types = std::array{ + event_identifier_group{event_trace_group::thread, 1, "Start" }, + event_identifier_group{event_trace_group::thread, 2, "End" }, + event_identifier_group{event_trace_group::thread, 3, "DcStart"}, + event_identifier_group{event_trace_group::thread, 4, "DcEnd" } }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel_trace_control/image_id.hpp b/snail/etl/parser/records/kernel_trace_control/image_id.hpp index 5f6b2e6..0cac7ab 100644 --- a/snail/etl/parser/records/kernel_trace_control/image_id.hpp +++ b/snail/etl/parser/records/kernel_trace_control/image_id.hpp @@ -21,9 +21,10 @@ constexpr inline auto image_id_guid = common::guid{ struct image_id_v2_info_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{image_id_guid, 0, "info"} + static inline constexpr std::string_view event_name = "ImageId-Info"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{image_id_guid, 0, "Info"} }; using extract_view_dynamic_base::buffer; @@ -46,10 +47,11 @@ struct image_id_v2_info_event_view : private extract_view_dynamic_base struct image_id_v2_dbg_id_pdb_info_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{image_id_guid, 36, "rsds" }, - event_identifier_guid{image_id_guid, 37, "il rsds"} + static inline constexpr std::string_view event_name = "ImageId-DbgIdPdbInfo"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{image_id_guid, 36, "Rsds" }, + event_identifier_guid{image_id_guid, 37, "IlRsds"} // "Il" == "inline" }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/kernel_trace_control/system_config_ex.hpp b/snail/etl/parser/records/kernel_trace_control/system_config_ex.hpp index 7ef00a8..1e190b2 100644 --- a/snail/etl/parser/records/kernel_trace_control/system_config_ex.hpp +++ b/snail/etl/parser/records/kernel_trace_control/system_config_ex.hpp @@ -19,9 +19,10 @@ constexpr inline auto system_config_ex_guid = common::guid{ struct system_config_ex_v0_build_info_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 0; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{system_config_ex_guid, 32, "build_info"} + static inline constexpr std::string_view event_name = "SystemConfigEx-BuildInfo"; + static inline constexpr std::uint16_t event_version = 0; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{system_config_ex_guid, 32, "BuildInfo"} }; using extract_view_dynamic_base::buffer; @@ -42,9 +43,10 @@ struct system_config_ex_v0_build_info_event_view : private extract_view_dynamic_ struct system_config_ex_v0_system_paths_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 0; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{system_config_ex_guid, 33, "system_paths"} + static inline constexpr std::string_view event_name = "SystemConfigEx-SystemPaths"; + static inline constexpr std::uint16_t event_version = 0; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{system_config_ex_guid, 33, "SystemPaths"} }; using extract_view_dynamic_base::buffer; @@ -63,9 +65,10 @@ struct system_config_ex_v0_system_paths_event_view : private extract_view_dynami struct system_config_ex_v0_volume_mapping_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 0; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{system_config_ex_guid, 35, "volume_mapping"} + static inline constexpr std::string_view event_name = "SystemConfigEx-VolumeMapping"; + static inline constexpr std::uint16_t event_version = 0; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{system_config_ex_guid, 35, "VolumeMapping"} }; using extract_view_dynamic_base::buffer; diff --git a/snail/etl/parser/records/visual_studio/diagnostics_hub.hpp b/snail/etl/parser/records/visual_studio/diagnostics_hub.hpp index eec046e..b30c2f3 100644 --- a/snail/etl/parser/records/visual_studio/diagnostics_hub.hpp +++ b/snail/etl/parser/records/visual_studio/diagnostics_hub.hpp @@ -48,9 +48,10 @@ enum class machine_architecture : std::uint32_t struct vs_diagnostics_hub_target_profiling_started_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 2; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{vs_diagnostics_hub_guid, 1, "target profiling started"} + static inline constexpr std::string_view event_name = "DiagHub-TargetProfStarted"; + static inline constexpr std::uint16_t event_version = 2; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{vs_diagnostics_hub_guid, 1, "TargetProfStarted"} }; using extract_view_dynamic_base::buffer; @@ -67,9 +68,10 @@ struct vs_diagnostics_hub_target_profiling_started_event_view : private extract_ struct vs_diagnostics_hub_target_profiling_stopped_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 1; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{vs_diagnostics_hub_guid, 2, "target profiling stopped"} + static inline constexpr std::string_view event_name = "DiagHub-TargetProfStopped"; + static inline constexpr std::uint16_t event_version = 1; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{vs_diagnostics_hub_guid, 2, "TargetProfStopped"} }; using extract_view_dynamic_base::buffer; @@ -85,9 +87,10 @@ struct vs_diagnostics_hub_target_profiling_stopped_event_view : private extract_ struct vs_diagnostics_hub_machine_info_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 0; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{vs_diagnostics_hub_guid, 5, "machine info"} + static inline constexpr std::string_view event_name = "DiagHub-MachineInfo"; + static inline constexpr std::uint16_t event_version = 0; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{vs_diagnostics_hub_guid, 5, "MachineInfo"} }; using extract_view_dynamic_base::buffer; @@ -106,9 +109,10 @@ struct vs_diagnostics_hub_machine_info_event_view : private extract_view_dynamic struct vs_diagnostics_hub_counter_info_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 0; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{vs_diagnostics_hub_guid, 6, "counter info"} + static inline constexpr std::string_view event_name = "DiagHub-CounterInfo"; + static inline constexpr std::uint16_t event_version = 0; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{vs_diagnostics_hub_guid, 6, "CounterInfo"} }; using extract_view_dynamic_base::buffer; @@ -125,9 +129,10 @@ struct vs_diagnostics_hub_counter_info_event_view : private extract_view_dynamic struct vs_diagnostics_hub_mark_info_event_view : private extract_view_dynamic_base { - static inline constexpr std::uint16_t event_version = 0; - static inline constexpr auto event_types = std::array{ - event_identifier_guid{vs_diagnostics_hub_guid, 7, "mark info"} + static inline constexpr std::string_view event_name = "DiagHub-MarkInfo"; + static inline constexpr std::uint16_t event_version = 0; + static inline constexpr auto event_types = std::array{ + event_identifier_guid{vs_diagnostics_hub_guid, 7, "MarkInfo"} }; using extract_view_dynamic_base::buffer;