From e5df54a90ec655ec4c47b7d26b0de7a54c98d75f Mon Sep 17 00:00:00 2001 From: Lalit Maganti Date: Mon, 4 Mar 2024 15:37:23 +0000 Subject: [PATCH] Revert "Add MappingTracker" This reverts commit a861cf6ae529eee5b8bc01c1d0c5d5d5fa2d9428. Reason for revert: Likely cause of failure in https://fusion2.corp.google.com/presubmit/612433447/OCL:612433447:BASE:612441830:1709565845028:57aa4de8/targets/invocations/d4830aac-37df-467d-b243-e7542e951f39/targets/%2F%2Fgoogleclient%2Fchrome%2Fspeed%2Fbig_data%2Fchrometto%2Ftrace_aggregator:trace_aggregator_tests/tests Change-Id: I36d979477f4ee4031fc6833c6c86e113cf24bcde --- Android.bp | 26 ++- BUILD | 33 ++-- src/profiling/symbolizer/BUILD.gn | 2 +- .../symbolizer/symbolize_database.cc | 44 ++++- src/trace_processor/BUILD.gn | 1 + src/trace_processor/importers/common/BUILD.gn | 7 +- .../importers/common/create_mapping_params.h | 71 -------- .../importers/common/mapping_tracker.cc | 169 ------------------ .../importers/common/mapping_tracker.h | 168 ----------------- .../importers/common/stack_profile_tracker.cc | 102 +++++++++-- .../importers/common/stack_profile_tracker.h | 60 +++++-- .../common/virtual_memory_mapping.cc | 123 ------------- .../importers/common/virtual_memory_mapping.h | 152 ---------------- src/trace_processor/importers/perf/BUILD.gn | 3 - .../importers/perf/perf_data_parser.cc | 19 +- .../importers/perf/perf_data_tokenizer.cc | 22 --- .../importers/perf/perf_data_tracker.cc | 73 +++----- .../importers/perf/perf_data_tracker.h | 10 +- .../perf/perf_data_tracker_unittest.cc | 80 ++++----- .../importers/perf/perf_event.h | 11 -- src/trace_processor/importers/proto/BUILD.gn | 4 +- .../importers/proto/profile_module.cc | 26 ++- .../proto/profile_packet_sequence_state.cc | 27 ++- .../proto/profile_packet_sequence_state.h | 5 +- .../profile_packet_sequence_state_unittest.cc | 6 +- .../proto/proto_trace_parser_unittest.cc | 2 - .../proto/stack_profile_sequence_state.cc | 65 ++++--- .../proto/stack_profile_sequence_state.h | 5 +- .../trace_processor_context.cc | 1 - .../trace_processor_storage_impl.cc | 2 - .../types/trace_processor_context.h | 2 - src/trace_processor/util/BUILD.gn | 15 +- src/trace_processor/util/build_id.cc | 128 ------------- src/trace_processor/util/build_id.h | 84 --------- src/trace_processor/util/stack_traces_util.cc | 30 ++++ src/trace_processor/util/stack_traces_util.h | 36 ++++ 36 files changed, 414 insertions(+), 1200 deletions(-) delete mode 100644 src/trace_processor/importers/common/create_mapping_params.h delete mode 100644 src/trace_processor/importers/common/mapping_tracker.cc delete mode 100644 src/trace_processor/importers/common/mapping_tracker.h delete mode 100644 src/trace_processor/importers/common/virtual_memory_mapping.cc delete mode 100644 src/trace_processor/importers/common/virtual_memory_mapping.h delete mode 100644 src/trace_processor/util/build_id.cc delete mode 100644 src/trace_processor/util/build_id.h create mode 100644 src/trace_processor/util/stack_traces_util.cc create mode 100644 src/trace_processor/util/stack_traces_util.h diff --git a/Android.bp b/Android.bp index a2e1ed24da..4541d4c50a 100644 --- a/Android.bp +++ b/Android.bp @@ -2369,7 +2369,6 @@ cc_test { ":perfetto_src_trace_processor_storage_storage", ":perfetto_src_trace_processor_tables_tables", ":perfetto_src_trace_processor_types_types", - ":perfetto_src_trace_processor_util_build_id", ":perfetto_src_trace_processor_util_bump_allocator", ":perfetto_src_trace_processor_util_descriptors", ":perfetto_src_trace_processor_util_glob", @@ -2383,6 +2382,7 @@ cc_test { ":perfetto_src_trace_processor_util_protozero_to_text", ":perfetto_src_trace_processor_util_regex", ":perfetto_src_trace_processor_util_sql_argument", + ":perfetto_src_trace_processor_util_stack_traces_util", ":perfetto_src_trace_processor_util_stdlib", ":perfetto_src_trace_processor_util_util", ":perfetto_src_trace_processor_util_zip_reader", @@ -11098,7 +11098,6 @@ filegroup { "src/trace_processor/importers/common/event_tracker.cc", "src/trace_processor/importers/common/flow_tracker.cc", "src/trace_processor/importers/common/global_args_tracker.cc", - "src/trace_processor/importers/common/mapping_tracker.cc", "src/trace_processor/importers/common/metadata_tracker.cc", "src/trace_processor/importers/common/process_tracker.cc", "src/trace_processor/importers/common/slice_tracker.cc", @@ -11107,7 +11106,6 @@ filegroup { "src/trace_processor/importers/common/system_info_tracker.cc", "src/trace_processor/importers/common/trace_parser.cc", "src/trace_processor/importers/common/track_tracker.cc", - "src/trace_processor/importers/common/virtual_memory_mapping.cc", ], } @@ -12305,14 +12303,6 @@ filegroup { name: "perfetto_src_trace_processor_unittests", } -// GN: //src/trace_processor/util:build_id -filegroup { - name: "perfetto_src_trace_processor_util_build_id", - srcs: [ - "src/trace_processor/util/build_id.cc", - ], -} - // GN: //src/trace_processor/util:bump_allocator filegroup { name: "perfetto_src_trace_processor_util_bump_allocator", @@ -12413,6 +12403,14 @@ filegroup { ], } +// GN: //src/trace_processor/util:stack_traces_util +filegroup { + name: "perfetto_src_trace_processor_util_stack_traces_util", + srcs: [ + "src/trace_processor/util/stack_traces_util.cc", + ], +} + // GN: //src/trace_processor/util:stdlib filegroup { name: "perfetto_src_trace_processor_util_stdlib", @@ -13936,7 +13934,6 @@ cc_test { ":perfetto_src_trace_processor_types_types", ":perfetto_src_trace_processor_types_unittests", ":perfetto_src_trace_processor_unittests", - ":perfetto_src_trace_processor_util_build_id", ":perfetto_src_trace_processor_util_bump_allocator", ":perfetto_src_trace_processor_util_descriptors", ":perfetto_src_trace_processor_util_glob", @@ -13950,6 +13947,7 @@ cc_test { ":perfetto_src_trace_processor_util_protozero_to_text", ":perfetto_src_trace_processor_util_regex", ":perfetto_src_trace_processor_util_sql_argument", + ":perfetto_src_trace_processor_util_stack_traces_util", ":perfetto_src_trace_processor_util_stdlib", ":perfetto_src_trace_processor_util_unittests", ":perfetto_src_trace_processor_util_util", @@ -14637,7 +14635,6 @@ cc_binary { ":perfetto_src_trace_processor_storage_storage", ":perfetto_src_trace_processor_tables_tables", ":perfetto_src_trace_processor_types_types", - ":perfetto_src_trace_processor_util_build_id", ":perfetto_src_trace_processor_util_bump_allocator", ":perfetto_src_trace_processor_util_descriptors", ":perfetto_src_trace_processor_util_glob", @@ -14651,6 +14648,7 @@ cc_binary { ":perfetto_src_trace_processor_util_protozero_to_text", ":perfetto_src_trace_processor_util_regex", ":perfetto_src_trace_processor_util_sql_argument", + ":perfetto_src_trace_processor_util_stack_traces_util", ":perfetto_src_trace_processor_util_stdlib", ":perfetto_src_trace_processor_util_util", ":perfetto_src_trace_processor_util_zip_reader", @@ -14870,7 +14868,6 @@ cc_binary_host { ":perfetto_src_trace_processor_storage_storage", ":perfetto_src_trace_processor_tables_tables", ":perfetto_src_trace_processor_types_types", - ":perfetto_src_trace_processor_util_build_id", ":perfetto_src_trace_processor_util_bump_allocator", ":perfetto_src_trace_processor_util_descriptors", ":perfetto_src_trace_processor_util_glob", @@ -14884,6 +14881,7 @@ cc_binary_host { ":perfetto_src_trace_processor_util_protozero_to_text", ":perfetto_src_trace_processor_util_regex", ":perfetto_src_trace_processor_util_sql_argument", + ":perfetto_src_trace_processor_util_stack_traces_util", ":perfetto_src_trace_processor_util_stdlib", ":perfetto_src_trace_processor_util_util", ":perfetto_src_trace_processor_util_zip_reader", diff --git a/BUILD b/BUILD index a779d034f0..1e7c962e0a 100644 --- a/BUILD +++ b/BUILD @@ -266,7 +266,6 @@ perfetto_cc_library( ":src_trace_processor_tables_tables", ":src_trace_processor_tables_tables_python", ":src_trace_processor_types_types", - ":src_trace_processor_util_build_id", ":src_trace_processor_util_bump_allocator", ":src_trace_processor_util_descriptors", ":src_trace_processor_util_glob", @@ -280,6 +279,7 @@ perfetto_cc_library( ":src_trace_processor_util_protozero_to_text", ":src_trace_processor_util_regex", ":src_trace_processor_util_sql_argument", + ":src_trace_processor_util_stack_traces_util", ":src_trace_processor_util_stdlib", ":src_trace_processor_util_util", ":src_trace_processor_util_zip_reader", @@ -1459,7 +1459,6 @@ perfetto_filegroup( "src/trace_processor/importers/common/clock_converter.h", "src/trace_processor/importers/common/clock_tracker.cc", "src/trace_processor/importers/common/clock_tracker.h", - "src/trace_processor/importers/common/create_mapping_params.h", "src/trace_processor/importers/common/deobfuscation_mapping_table.cc", "src/trace_processor/importers/common/deobfuscation_mapping_table.h", "src/trace_processor/importers/common/event_tracker.cc", @@ -1468,8 +1467,6 @@ perfetto_filegroup( "src/trace_processor/importers/common/flow_tracker.h", "src/trace_processor/importers/common/global_args_tracker.cc", "src/trace_processor/importers/common/global_args_tracker.h", - "src/trace_processor/importers/common/mapping_tracker.cc", - "src/trace_processor/importers/common/mapping_tracker.h", "src/trace_processor/importers/common/metadata_tracker.cc", "src/trace_processor/importers/common/metadata_tracker.h", "src/trace_processor/importers/common/process_tracker.cc", @@ -1485,8 +1482,6 @@ perfetto_filegroup( "src/trace_processor/importers/common/trace_parser.cc", "src/trace_processor/importers/common/track_tracker.cc", "src/trace_processor/importers/common/track_tracker.h", - "src/trace_processor/importers/common/virtual_memory_mapping.cc", - "src/trace_processor/importers/common/virtual_memory_mapping.h", ], ) @@ -2678,15 +2673,6 @@ perfetto_filegroup( ], ) -# GN target: //src/trace_processor/util:build_id -perfetto_filegroup( - name = "src_trace_processor_util_build_id", - srcs = [ - "src/trace_processor/util/build_id.cc", - "src/trace_processor/util/build_id.h", - ], -) - # GN target: //src/trace_processor/util:bump_allocator perfetto_filegroup( name = "src_trace_processor_util_bump_allocator", @@ -2806,6 +2792,15 @@ perfetto_filegroup( ], ) +# GN target: //src/trace_processor/util:stack_traces_util +perfetto_filegroup( + name = "src_trace_processor_util_stack_traces_util", + srcs = [ + "src/trace_processor/util/stack_traces_util.cc", + "src/trace_processor/util/stack_traces_util.h", + ], +) + # GN target: //src/trace_processor/util:stdlib perfetto_filegroup( name = "src_trace_processor_util_stdlib", @@ -5622,7 +5617,6 @@ perfetto_cc_library( ":src_trace_processor_tables_tables", ":src_trace_processor_tables_tables_python", ":src_trace_processor_types_types", - ":src_trace_processor_util_build_id", ":src_trace_processor_util_bump_allocator", ":src_trace_processor_util_descriptors", ":src_trace_processor_util_glob", @@ -5636,6 +5630,7 @@ perfetto_cc_library( ":src_trace_processor_util_protozero_to_text", ":src_trace_processor_util_regex", ":src_trace_processor_util_sql_argument", + ":src_trace_processor_util_stack_traces_util", ":src_trace_processor_util_stdlib", ":src_trace_processor_util_util", ":src_trace_processor_util_zip_reader", @@ -5792,7 +5787,6 @@ perfetto_cc_binary( ":src_trace_processor_tables_tables", ":src_trace_processor_tables_tables_python", ":src_trace_processor_types_types", - ":src_trace_processor_util_build_id", ":src_trace_processor_util_bump_allocator", ":src_trace_processor_util_descriptors", ":src_trace_processor_util_glob", @@ -5806,6 +5800,7 @@ perfetto_cc_binary( ":src_trace_processor_util_protozero_to_text", ":src_trace_processor_util_regex", ":src_trace_processor_util_sql_argument", + ":src_trace_processor_util_stack_traces_util", ":src_trace_processor_util_stdlib", ":src_trace_processor_util_util", ":src_trace_processor_util_zip_reader", @@ -5883,7 +5878,7 @@ perfetto_cc_library( ":src_profiling_deobfuscator", ":src_profiling_symbolizer_symbolize_database", ":src_profiling_symbolizer_symbolizer", - ":src_trace_processor_util_build_id", + ":src_trace_processor_util_stack_traces_util", ":src_traceconv_pprofbuilder", ":src_traceconv_utils", ], @@ -6014,7 +6009,6 @@ perfetto_cc_binary( ":src_trace_processor_tables_tables", ":src_trace_processor_tables_tables_python", ":src_trace_processor_types_types", - ":src_trace_processor_util_build_id", ":src_trace_processor_util_bump_allocator", ":src_trace_processor_util_descriptors", ":src_trace_processor_util_glob", @@ -6028,6 +6022,7 @@ perfetto_cc_binary( ":src_trace_processor_util_protozero_to_text", ":src_trace_processor_util_regex", ":src_trace_processor_util_sql_argument", + ":src_trace_processor_util_stack_traces_util", ":src_trace_processor_util_stdlib", ":src_trace_processor_util_util", ":src_trace_processor_util_zip_reader", diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn index 082ec0f77f..c81dbb1338 100644 --- a/src/profiling/symbolizer/BUILD.gn +++ b/src/profiling/symbolizer/BUILD.gn @@ -52,7 +52,7 @@ if (enable_perfetto_trace_processor) { "../../../include/perfetto/trace_processor:trace_processor", "../../../protos/perfetto/trace:zero", "../../../protos/perfetto/trace/profiling:zero", - "../../trace_processor/util:build_id", + "../../trace_processor/util:stack_traces_util", ] sources = [ "symbolize_database.cc", diff --git a/src/profiling/symbolizer/symbolize_database.cc b/src/profiling/symbolizer/symbolize_database.cc index a008e1a2d5..224874bc30 100644 --- a/src/profiling/symbolizer/symbolize_database.cc +++ b/src/profiling/symbolizer/symbolize_database.cc @@ -28,7 +28,8 @@ #include "protos/perfetto/trace/profiling/profile_common.pbzero.h" #include "protos/perfetto/trace/trace.pbzero.h" #include "protos/perfetto/trace/trace_packet.pbzero.h" -#include "src/trace_processor/util/build_id.h" + +#include "src/trace_processor/util/stack_traces_util.h" namespace perfetto { namespace profiling { @@ -55,6 +56,32 @@ struct UnsymbolizedMapping { } }; +std::string FromHex(const char* str, size_t size) { + if (size % 2) { + PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str); + return ""; + } + std::string result(size / 2, '\0'); + for (size_t i = 0; i < size; i += 2) { + char hex_byte[3]; + hex_byte[0] = str[i]; + hex_byte[1] = str[i + 1]; + hex_byte[2] = '\0'; + char* end; + long int byte = strtol(hex_byte, &end, 16); + if (*end != '\0') { + PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str); + return ""; + } + result[i / 2] = static_cast(byte); + } + return result; +} + +std::string FromHex(const std::string& str) { + return FromHex(str.c_str(), str.size()); +} + std::map> GetUnsymbolizedFrames( trace_processor::TraceProcessor* tp) { std::map> res; @@ -62,10 +89,17 @@ std::map> GetUnsymbolizedFrames( while (it.Next()) { int64_t load_bias = it.Get(3).AsLong(); PERFETTO_CHECK(load_bias >= 0); - trace_processor::BuildId build_id = - trace_processor::BuildId::FromHex(it.Get(1).AsString()); - UnsymbolizedMapping unsymbolized_mapping{ - it.Get(0).AsString(), build_id.raw(), static_cast(load_bias)}; + std::string build_id; + // TODO(b/148109467): Remove workaround once all active Chrome versions + // write raw bytes instead of a string as build_id. + std::string raw_build_id = it.Get(1).AsString(); + if (!trace_processor::util::IsHexModuleId(base::StringView(raw_build_id))) { + build_id = FromHex(raw_build_id); + } else { + build_id = raw_build_id; + } + UnsymbolizedMapping unsymbolized_mapping{it.Get(0).AsString(), build_id, + static_cast(load_bias)}; int64_t rel_pc = it.Get(2).AsLong(); res[unsymbolized_mapping].emplace_back(rel_pc); } diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn index dfd202e8f3..694b51567b 100644 --- a/src/trace_processor/BUILD.gn +++ b/src/trace_processor/BUILD.gn @@ -132,6 +132,7 @@ source_set("storage_minimal") { "util:descriptors", "util:gzip", "util:proto_to_args_parser", + "util:stack_traces_util", ] public_deps = [ "../../include/perfetto/trace_processor:storage" ] } diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn index 8b66fb316d..823edd82ad 100644 --- a/src/trace_processor/importers/common/BUILD.gn +++ b/src/trace_processor/importers/common/BUILD.gn @@ -28,7 +28,6 @@ source_set("common") { "clock_converter.h", "clock_tracker.cc", "clock_tracker.h", - "create_mapping_params.h", "deobfuscation_mapping_table.cc", "deobfuscation_mapping_table.h", "event_tracker.cc", @@ -37,8 +36,6 @@ source_set("common") { "flow_tracker.h", "global_args_tracker.cc", "global_args_tracker.h", - "mapping_tracker.cc", - "mapping_tracker.h", "metadata_tracker.cc", "metadata_tracker.h", "process_tracker.cc", @@ -54,8 +51,6 @@ source_set("common") { "trace_parser.cc", "track_tracker.cc", "track_tracker.h", - "virtual_memory_mapping.cc", - "virtual_memory_mapping.h", ] public_deps = [ ":trace_parser_hdr", @@ -75,8 +70,8 @@ source_set("common") { "../../storage", "../../tables:tables", "../../types", - "../../util:build_id", "../../util:profiler_util", + "../../util:stack_traces_util", "../fuchsia:fuchsia_record", "../systrace:systrace_line", ] diff --git a/src/trace_processor/importers/common/create_mapping_params.h b/src/trace_processor/importers/common/create_mapping_params.h deleted file mode 100644 index 7aba456034..0000000000 --- a/src/trace_processor/importers/common/create_mapping_params.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CREATE_MAPPING_PARAMS_H_ -#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CREATE_MAPPING_PARAMS_H_ - -#include -#include -#include -#include -#include - -#include "perfetto/ext/base/hash.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/util/build_id.h" - -namespace perfetto { -namespace trace_processor { - -struct CreateMappingParams { - AddressRange memory_range; - // This is the offset into the file that has been mapped at - // memory_range.start() - uint64_t exact_offset = 0; - // This is the offset into the file where the ELF header starts. We assume - // all file mappings are ELF files an thus this offset is 0. - uint64_t start_offset = 0; - // This can only be read out of the actual ELF file. - uint64_t load_bias = 0; - std::string name; - std::optional build_id; - - auto ToTuple() const { - return std::tie(memory_range, exact_offset, start_offset, load_bias, name, - build_id); - } - - bool operator==(const CreateMappingParams& o) const { - return ToTuple() == o.ToTuple(); - } - - struct Hasher { - size_t operator()(const CreateMappingParams& p) const { - base::Hasher h; - h.UpdateAll(p.memory_range.start(), p.memory_range.end(), p.exact_offset, - p.start_offset, p.load_bias, p.name); - if (p.build_id) { - h.Update(*p.build_id); - } - return static_cast(h.digest()); - } - }; -}; - -} // namespace trace_processor -} // namespace perfetto - -#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CREATE_MAPPING_PARAMS_H_ diff --git a/src/trace_processor/importers/common/mapping_tracker.cc b/src/trace_processor/importers/common/mapping_tracker.cc deleted file mode 100644 index 13b8274aeb..0000000000 --- a/src/trace_processor/importers/common/mapping_tracker.cc +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "src/trace_processor/importers/common/mapping_tracker.h" - -#include -#include -#include -#include - -#include "perfetto/ext/base/string_view.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/storage/trace_storage.h" -#include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" - -namespace perfetto { -namespace trace_processor { -namespace { - -bool IsKernelModule(base::StringView name) { - return !name.StartsWith("[kernel.kallsyms]"); -} - -} // namespace - -JitDelegate::~JitDelegate() = default; - -template -MappingImpl& MappingTracker::AddMapping(std::unique_ptr mapping) { - auto ptr = mapping.get(); - PERFETTO_CHECK( - mappings_by_id_.Insert(ptr->mapping_id(), std::move(mapping)).second); - - mappings_by_name_and_build_id_[NameAndBuildId{base::StringView(ptr->name()), - ptr->build_id()}] - .push_back(ptr); - - return *ptr; -} - -KernelMemoryMapping& MappingTracker::CreateKernelMemoryMapping( - CreateMappingParams params) { - // TODO(carlscab): Guess build_id if not provided. Some tools like simpleperf - // add a mapping file_name ->build_id that we could use here - - const bool is_module = IsKernelModule(base::StringView(params.name)); - - if (!is_module && kernel_ != nullptr) { - PERFETTO_CHECK(params.memory_range == kernel_->memory_range()); - return *kernel_; - } - - std::unique_ptr mapping( - new KernelMemoryMapping(context_, std::move(params))); - - if (is_module) { - // TODO(carlscab): Overlaps not supported (for now?). Should be fine for - // kernel. - PERFETTO_CHECK( - kernel_modules_.Emplace(mapping->memory_range(), mapping.get())); - } else { - kernel_ = mapping.get(); - } - - return AddMapping(std::move(mapping)); -} - -UserMemoryMapping& MappingTracker::CreateUserMemoryMapping( - UniquePid upid, - CreateMappingParams params) { - // TODO(carlscab): Guess build_id if not provided. Some tools like simpleperf - // add a mapping file_name ->build_id that we could use here - - const AddressRange mapping_range = params.memory_range; - std::unique_ptr mapping( - new UserMemoryMapping(context_, upid, std::move(params))); - // TODO(carlscab): Overlaps not supported (for now?). - PERFETTO_CHECK(user_memory_[upid].Emplace(mapping_range, mapping.get())); - - jit_delegates_[upid].ForOverlaps( - mapping_range, [&](std::pair& entry) { - const auto& jit_range = entry.first; - JitDelegate* jit_delegate = entry.second; - PERFETTO_CHECK(jit_range.Contains(mapping_range)); - mapping->SetJitDelegate(jit_delegate); - }); - - return AddMapping(std::move(mapping)); -} - -KernelMemoryMapping* MappingTracker::FindKernelMappingForAddress( - uint64_t address) const { - if (auto it = kernel_modules_.Find(address); it != kernel_modules_.end()) { - return it->second; - } - if (kernel_ && kernel_->memory_range().Contains(address)) { - return kernel_; - } - return nullptr; -} - -UserMemoryMapping* MappingTracker::FindUserMappingForAddress( - UniquePid upid, - uint64_t address) const { - if (auto* vm = user_memory_.Find(upid); vm) { - if (auto it = vm->Find(address); it != vm->end()) { - return it->second; - } - } - - if (auto* delegates = jit_delegates_.Find(upid); delegates) { - if (auto it = delegates->Find(address); it != delegates->end()) { - return it->second->CreateMapping(); - } - } - - return nullptr; -} - -std::vector MappingTracker::FindMappings( - base::StringView name, - const BuildId& build_id) const { - if (auto res = mappings_by_name_and_build_id_.Find({name, build_id}); - res != nullptr) { - return *res; - } - return {}; -} - -VirtualMemoryMapping& MappingTracker::InternMemoryMapping( - CreateMappingParams params) { - if (auto* mapping = interned_mappings_.Find(params); mapping) { - return **mapping; - } - - std::unique_ptr mapping( - new VirtualMemoryMapping(context_, params)); - interned_mappings_.Insert(std::move(params), mapping.get()); - return AddMapping(std::move(mapping)); -} - -void MappingTracker::AddJitRange(UniquePid upid, - AddressRange jit_range, - JitDelegate* delegate) { - // TODO(carlscab): Deal with overlaps - jit_delegates_[upid].DeleteOverlapsAndEmplace(jit_range, delegate); - user_memory_[upid].ForOverlaps( - jit_range, [&](std::pair& entry) { - PERFETTO_CHECK(jit_range.Contains(entry.first)); - entry.second->SetJitDelegate(delegate); - }); -} - -} // namespace trace_processor -} // namespace perfetto diff --git a/src/trace_processor/importers/common/mapping_tracker.h b/src/trace_processor/importers/common/mapping_tracker.h deleted file mode 100644 index 95dc355a5b..0000000000 --- a/src/trace_processor/importers/common/mapping_tracker.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_ -#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_ - -#include -#include -#include -#include -#include - -#include "perfetto/ext/base/flat_hash_map.h" -#include "perfetto/ext/base/hash.h" -#include "perfetto/ext/base/string_view.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/virtual_memory_mapping.h" -#include "src/trace_processor/storage/trace_storage.h" -#include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" - -namespace perfetto { -namespace trace_processor { - -// Api used to forward frame interning requests for frames that fall in a -// jitted memory region. -// MappingTracker allows other trackers to register ranges of memory for -// which they need to control when a new frame is created. Jitted code can -// move in memory over time, so the same program counter might refer to -// different functions at different point in time. MappingTracker does -// not keep track of such moves but instead delegates the creation of jitted -// frames to a delegate. -class JitDelegate { - public: - virtual ~JitDelegate(); - // Forward frame interning request. - // Implementations are free to intern the frame as needed. - // Returns frame_id, and whether a new row as created or not. - virtual std::pair InternFrame( - VirtualMemoryMapping* mapping, - uint64_t rel_pc, - base::StringView function_name) = 0; - - // Simpleperf does not emit mmap events for jitted ranges (actually for non - // file backed executable mappings). So have a way to generate a mapping on - // the fly for FindMapping requests in a jitted region with no associated - // mapping. - virtual UserMemoryMapping* CreateMapping() = 0; -}; - -// Keeps track of all aspects relative to memory mappings. -// This class keeps track of 3 types of mappings: UserMemoryMapping, -// KernelMemoryMapping and others. The others are used to represent mapping -// where we do not have enough information to determine what type of -// mapping (user, kernel) we are dealing with. This is usually the case with -// data sources that do not provide enough information about the mappings. -// -// TODO(carlscab): Hopefully we can slowly get rid of cases where these other -// mappings are needed. The biggest blocker right now is determining the upid. -// we could infer this from the actual samples that use said mapping (those -// usually have a pid attached). So we would need to have a "fake" mapping that -// actually materializes when we see a sample with a pid. -// -// ATTENTION: No overlaps allowed (for now). Eventually the order in which -// mappings are create will matter as newer mappings will delete old ones. -// This is how tools like linux perf behave, mmap event have a timestamp -// associated and there are no "delete events" just new mmap events that -// overlap (to be deleted) mappings. -class MappingTracker { - public: - explicit MappingTracker(TraceProcessorContext* context) : context_(context) {} - - // Create a new kernel space mapping. Returned reference will be valid for the - // duration of this instance. - KernelMemoryMapping& CreateKernelMemoryMapping(CreateMappingParams params); - - // Create a new user space mapping. Returned reference will be valid for the - // duration of this instance. - UserMemoryMapping& CreateUserMemoryMapping(UniquePid upid, - CreateMappingParams params); - - // Create an "other" mapping. Returned reference will be valid for the - // duration of this instance. - VirtualMemoryMapping& InternMemoryMapping(CreateMappingParams params); - - // Given an absolute address find the kernel mapping where this address - // belongs to. Returns `nullptr` if none is found. - KernelMemoryMapping* FindKernelMappingForAddress(uint64_t address) const; - - // Given an absolute address find the user mapping where this address - // belongs to. Returns `nullptr` if none is found. - UserMemoryMapping* FindUserMappingForAddress(UniquePid upid, - uint64_t address) const; - - std::vector FindMappings( - base::StringView name, - const BuildId& build_id) const; - - // Marks a range of memory as containing jitted code. - // If the added region overlaps with other existing ranges the latter are all - // deleted. - // Jitted ranges will only be applied to UserMemoryMappings - void AddJitRange(UniquePid upid, AddressRange range, JitDelegate* delegate); - - private: - template - MappingImpl& AddMapping(std::unique_ptr mapping); - - TraceProcessorContext* const context_; - base::FlatHashMap> - mappings_by_id_; - - base::FlatHashMap - interned_mappings_; - - struct NameAndBuildId { - base::StringView name; - std::optional build_id; - - bool operator==(const NameAndBuildId& o) const { - return name == o.name && build_id == o.build_id; - } - - bool operator!=(const NameAndBuildId& o) const { return !(*this == o); } - - struct Hasher { - size_t operator()(const NameAndBuildId& o) const { - base::Hasher hasher; - hasher.Update(o.name); - if (o.build_id) { - hasher.Update(*o.build_id); - } - return static_cast(hasher.digest()); - } - }; - }; - base::FlatHashMap, - NameAndBuildId::Hasher> - mappings_by_name_and_build_id_; - - base::FlatHashMap> - user_memory_; - AddressRangeMap kernel_modules_; - KernelMemoryMapping* kernel_ = nullptr; - - base::FlatHashMap> jit_delegates_; -}; - -} // namespace trace_processor -} // namespace perfetto - -#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_ diff --git a/src/trace_processor/importers/common/stack_profile_tracker.cc b/src/trace_processor/importers/common/stack_profile_tracker.cc index 799dc2964d..ad57523fed 100644 --- a/src/trace_processor/importers/common/stack_profile_tracker.cc +++ b/src/trace_processor/importers/common/stack_profile_tracker.cc @@ -16,18 +16,35 @@ #include "src/trace_processor/importers/common/stack_profile_tracker.h" -#include -#include - +#include "perfetto/ext/base/string_utils.h" #include "perfetto/ext/base/string_view.h" #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/tables/profiler_tables_py.h" #include "src/trace_processor/types/trace_processor_context.h" #include "src/trace_processor/util/profiler_util.h" +#include "src/trace_processor/util/stack_traces_util.h" namespace perfetto { namespace trace_processor { +namespace { +std::string CleanBuildId(base::StringView build_id) { + if (build_id.empty()) { + return build_id.ToStdString(); + } + // If the build_id is 33 characters long, we assume it's a Breakpad debug + // identifier which is already in Hex and doesn't need conversion. + // TODO(b/148109467): Remove workaround once all active Chrome versions + // write raw bytes instead of a string as build_id. + if (util::IsHexModuleId(build_id)) { + return build_id.ToStdString(); + } + + return base::ToHex(build_id.data(), build_id.size()); +} + +} // namespace + std::vector StackProfileTracker::JavaFramesForName( NameInPackage name) const { if (const auto* frames = java_frames_for_name_.Find(name); frames) { @@ -36,6 +53,50 @@ std::vector StackProfileTracker::JavaFramesForName( return {}; } +std::vector StackProfileTracker::FindMappingRow( + StringId name, + StringId build_id) const { + if (const auto* mappings = + mappings_by_name_and_build_id_.Find(std::make_pair(name, build_id)); + mappings) { + return *mappings; + } + return {}; +} + +std::vector StackProfileTracker::FindFrameIds(MappingId mapping_id, + uint64_t rel_pc) const { + if (const auto* frames = + frame_by_mapping_and_rel_pc_.Find(std::make_pair(mapping_id, rel_pc)); + frames) { + return *frames; + } + return {}; +} + +MappingId StackProfileTracker::InternMapping( + const CreateMappingParams& params) { + tables::StackProfileMappingTable::Row row; + row.build_id = InternBuildId(params.build_id); + row.exact_offset = static_cast(params.exact_offset); + row.start_offset = static_cast(params.start_offset); + row.start = static_cast(params.start); + row.end = static_cast(params.end); + row.load_bias = static_cast(params.load_bias); + row.name = context_->storage->InternString(params.name); + + if (MappingId* id = mapping_unique_row_index_.Find(row); id) { + return *id; + } + + MappingId mapping_id = + context_->storage->mutable_stack_profile_mapping_table()->Insert(row).id; + mapping_unique_row_index_.Insert(row, mapping_id); + mappings_by_name_and_build_id_[{row.name, row.build_id}].push_back( + mapping_id); + return mapping_id; +} + CallsiteId StackProfileTracker::InternCallsite( std::optional parent_callsite_id, FrameId frame_id, @@ -52,12 +113,22 @@ CallsiteId StackProfileTracker::InternCallsite( return callsite_id; } -void StackProfileTracker::OnFrameCreated(FrameId frame_id) { - auto frame = - *context_->storage->stack_profile_frame_table().FindById(frame_id); - const MappingId mapping_id = frame.mapping(); - const StringId name_id = frame.name(); - const auto function_name = context_->storage->GetString(name_id); +FrameId StackProfileTracker::InternFrame(MappingId mapping_id, + uint64_t rel_pc, + base::StringView function_name) { + tables::StackProfileFrameTable::Row row; + row.mapping = mapping_id; + row.rel_pc = static_cast(rel_pc); + row.name = context_->storage->InternString(function_name); + + if (FrameId* id = frame_unique_row_index_.Find(row); id) { + return *id; + } + + FrameId frame_id = + context_->storage->mutable_stack_profile_frame_table()->Insert(row).id; + frame_unique_row_index_.Insert(row, frame_id); + frame_by_mapping_and_rel_pc_[{mapping_id, rel_pc}].push_back(frame_id); if (function_name.find('.') != base::StringView::npos) { // Java frames always contain a '.' @@ -68,14 +139,21 @@ void StackProfileTracker::OnFrameCreated(FrameId frame_id) { std::optional package = PackageFromLocation(context_->storage.get(), mapping_name); if (package) { - NameInPackage nip{ - name_id, context_->storage->InternString(base::StringView(*package))}; + NameInPackage nip{row.name, context_->storage->InternString( + base::StringView(*package))}; java_frames_for_name_[nip].push_back(frame_id); } else if (mapping_name.find("/memfd:") == 0) { - NameInPackage nip{name_id, context_->storage->InternString("memfd")}; + NameInPackage nip{row.name, context_->storage->InternString("memfd")}; java_frames_for_name_[nip].push_back(frame_id); } } + + return frame_id; +} + +StringId StackProfileTracker::InternBuildId(base::StringView build_id) { + return context_->storage->InternString( + base::StringView(CleanBuildId(build_id))); } } // namespace trace_processor diff --git a/src/trace_processor/importers/common/stack_profile_tracker.h b/src/trace_processor/importers/common/stack_profile_tracker.h index b018f74ec5..a1067b8ac6 100644 --- a/src/trace_processor/importers/common/stack_profile_tracker.h +++ b/src/trace_processor/importers/common/stack_profile_tracker.h @@ -20,11 +20,12 @@ #include #include #include +#include #include #include "perfetto/ext/base/flat_hash_map.h" #include "perfetto/ext/base/hash.h" - +#include "perfetto/ext/base/string_view.h" #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/tables/profiler_tables_py.h" @@ -51,39 +52,64 @@ class TraceProcessorContext; class StackProfileTracker { public: + struct CreateMappingParams { + base::StringView build_id; + uint64_t exact_offset; + uint64_t start_offset; + uint64_t start; + uint64_t end; + uint64_t load_bias; + base::StringView name; + }; + explicit StackProfileTracker(TraceProcessorContext* context) : context_(context) {} std::vector JavaFramesForName(NameInPackage name) const; + std::vector FindMappingRow(StringId name, StringId build_id) const; + std::vector FindFrameIds(MappingId mapping_id, + uint64_t rel_pc) const; + MappingId InternMapping(const CreateMappingParams& params); CallsiteId InternCallsite(std::optional parent_callsite_id, FrameId frame_id, uint32_t depth); - - void OnFrameCreated(FrameId frame_id); + FrameId InternFrame(MappingId mapping_id, + uint64_t rel_pc, + base::StringView function_name); private: + StringId InternBuildId(base::StringView build_id); + TraceProcessorContext* const context_; + base::FlatHashMap + mapping_unique_row_index_; base::FlatHashMap callsite_unique_row_index_; + base::FlatHashMap + frame_unique_row_index_; - struct FrameKey { - MappingId mapping_id; - uint64_t rel_pc; - - bool operator==(const FrameKey& o) const { - return mapping_id == o.mapping_id && rel_pc == o.rel_pc; + struct MappingHasher { + size_t operator()(const std::pair& o) const { + return static_cast( + base::Hasher::Combine(o.first.raw_id(), o.second.raw_id())); } + }; + base::FlatHashMap, + std::vector, + MappingHasher> + mappings_by_name_and_build_id_; - bool operator!=(const FrameKey& o) const { return !(*this == o); } - - struct Hasher { - size_t operator()(const FrameKey& o) const { - return static_cast( - base::Hasher::Combine(o.mapping_id.value, o.rel_pc)); - } - }; + struct FrameHasher { + size_t operator()(const std::pair& o) const { + return static_cast( + base::Hasher::Combine(o.first.value, o.second)); + } }; + base::FlatHashMap, + std::vector, + FrameHasher> + frame_by_mapping_and_rel_pc_; base::FlatHashMap, NameInPackage::Hasher> java_frames_for_name_; diff --git a/src/trace_processor/importers/common/virtual_memory_mapping.cc b/src/trace_processor/importers/common/virtual_memory_mapping.cc deleted file mode 100644 index 60166f5957..0000000000 --- a/src/trace_processor/importers/common/virtual_memory_mapping.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "src/trace_processor/importers/common/virtual_memory_mapping.h" - -#include -#include -#include -#include -#include -#include - -#include "perfetto/ext/base/string_view.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" -#include "src/trace_processor/importers/common/stack_profile_tracker.h" -#include "src/trace_processor/storage/trace_storage.h" -#include "src/trace_processor/tables/profiler_tables_py.h" -#include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" - -namespace perfetto { -namespace trace_processor { -namespace { - -MappingId CreateMapping(TraceProcessorContext* context, - const CreateMappingParams& params) { - StringId build_id = context->storage->InternString(base::StringView( - params.build_id ? params.build_id->ToHex() : std::string())); - MappingId mapping_id = - context->storage->mutable_stack_profile_mapping_table() - ->Insert( - {build_id, static_cast(params.exact_offset), - static_cast(params.start_offset), - static_cast(params.memory_range.start()), - static_cast(params.memory_range.end()), - static_cast(params.load_bias), - context->storage->InternString(base::StringView(params.name))}) - .id; - - return mapping_id; -} - -} // namespace - -VirtualMemoryMapping::VirtualMemoryMapping(TraceProcessorContext* context, - CreateMappingParams params) - : context_(context), - mapping_id_(CreateMapping(context, params)), - memory_range_(params.memory_range), - offset_(params.exact_offset), - load_bias_(params.load_bias), - name_(std::move(params.name)), - build_id_(std::move(params.build_id)) {} - -VirtualMemoryMapping::~VirtualMemoryMapping() = default; - -KernelMemoryMapping::KernelMemoryMapping(TraceProcessorContext* context, - CreateMappingParams params) - : VirtualMemoryMapping(context, std::move(params)) {} - -KernelMemoryMapping::~KernelMemoryMapping() = default; - -UserMemoryMapping::UserMemoryMapping(TraceProcessorContext* context, - UniquePid upid, - CreateMappingParams params) - : VirtualMemoryMapping(context, std::move(params)), upid_(upid) {} - -UserMemoryMapping::~UserMemoryMapping() = default; - -FrameId VirtualMemoryMapping::InternFrame(uint64_t rel_pc, - base::StringView function_name) { - auto [frame_id, was_inserted] = - jit_delegate_ ? jit_delegate_->InternFrame(this, rel_pc, function_name) - : InternFrameImpl(rel_pc, function_name); - if (was_inserted) { - frames_by_rel_pc_[rel_pc].push_back(frame_id); - context_->stack_profile_tracker->OnFrameCreated(frame_id); - } - return frame_id; -} - -std::vector VirtualMemoryMapping::FindFrameIds(uint64_t rel_pc) const { - if (auto* res = frames_by_rel_pc_.Find(rel_pc); res != nullptr) { - return *res; - } - return {}; -} - -std::pair VirtualMemoryMapping::InternFrameImpl( - uint64_t rel_pc, - base::StringView function_name) { - const FrameKey frame_key{rel_pc, - context_->storage->InternString(function_name)}; - if (FrameId* id = interned_frames_.Find(frame_key); id) { - return {*id, false}; - } - - const FrameId frame_id = - context_->storage->mutable_stack_profile_frame_table() - ->Insert( - {frame_key.name_id, mapping_id_, static_cast(rel_pc)}) - .id; - interned_frames_.Insert(frame_key, frame_id); - - return {frame_id, true}; -} - -} // namespace trace_processor -} // namespace perfetto diff --git a/src/trace_processor/importers/common/virtual_memory_mapping.h b/src/trace_processor/importers/common/virtual_memory_mapping.h deleted file mode 100644 index 7b8ef58234..0000000000 --- a/src/trace_processor/importers/common/virtual_memory_mapping.h +++ /dev/null @@ -1,152 +0,0 @@ - -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_VIRTUAL_MEMORY_MAPPING_H_ -#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_VIRTUAL_MEMORY_MAPPING_H_ - -#include -#include -#include -#include -#include - -#include "perfetto/ext/base/flat_hash_map.h" -#include "perfetto/ext/base/hash.h" -#include "perfetto/ext/base/string_view.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/create_mapping_params.h" -#include "src/trace_processor/storage/trace_storage.h" -#include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" - -namespace perfetto { -namespace trace_processor { - -// TODO(carlscab): Reconsider whether jit is the best abstraction here. All we -// really care is about mapping a `rel_pc` to a symbol (aka symbolization) and -// whether is this is constant. -class JitDelegate; - -// Represents a mapping in virtual memory. -class VirtualMemoryMapping { - public: - virtual ~VirtualMemoryMapping(); - // Range of virtual memory this mapping covers. - AddressRange memory_range() const { return memory_range_; } - MappingId mapping_id() const { return mapping_id_; } - // This name could be the path of the underlying file mapped into memory. - const std::string& name() const { return name_; } - // For file mappings, this is the offset into the file for the first byte in - // the mapping - uint64_t offset() const { return offset_; } - // If the mapped file is an executable or shared library this will return the - // load bias, if known. Returns 0 otherwise. - uint64_t load_bias() const { return load_bias_; } - // If the mapped file is an executable or shared library this will return its - // build id, if known. - const std::optional& build_id() const { return build_id_; } - - // Whether this maps to a region that holds jitted code. - bool is_jitted() const { return jit_delegate_ != nullptr; } - - // Converts an absolute address into a relative one. - uint64_t ToRelativePc(uint64_t address) const { - return address - memory_range_.start() + offset_ + load_bias_; - } - - // Creates a frame for the given `rel_pc`. Note that if the mapping - // `is_jitted()` same `rel_pc` values can return different mappings (as jitted - // functions can be created and deleted over time.) So for such mappings the - // returned `FrameId` should not be cached. - FrameId InternFrame(uint64_t rel_pc, base::StringView function_name); - - // Returns all frames ever created in this mapping for the given `rel_pc`. - std::vector FindFrameIds(uint64_t rel_pc) const; - - protected: - VirtualMemoryMapping(TraceProcessorContext* context, - CreateMappingParams params); - - private: - friend class MappingTracker; - - std::pair InternFrameImpl(uint64_t rel_pc, - base::StringView function_name); - - void SetJitDelegate(JitDelegate* jit_delegate) { - jit_delegate_ = jit_delegate; - } - - TraceProcessorContext* const context_; - const MappingId mapping_id_; - const AddressRange memory_range_; - const uint64_t offset_; - const uint64_t load_bias_; - const std::string name_; - std::optional const build_id_; - JitDelegate* jit_delegate_ = nullptr; - - struct FrameKey { - uint64_t rel_pc; - // It doesn't seem to make too much sense to key on name, as for the same - // mapping and same rel_pc the name should always be the same. But who knows - // how producers behave. - StringId name_id; - - bool operator==(const FrameKey& o) const { - return rel_pc == o.rel_pc && name_id == o.name_id; - } - - struct Hasher { - size_t operator()(const FrameKey& k) const { - return static_cast( - base::Hasher::Combine(k.rel_pc, k.name_id.raw_id())); - } - }; - }; - base::FlatHashMap interned_frames_; - base::FlatHashMap> frames_by_rel_pc_; -}; - -class KernelMemoryMapping : public VirtualMemoryMapping { - public: - ~KernelMemoryMapping() override; - - private: - friend class MappingTracker; - KernelMemoryMapping(TraceProcessorContext* context, - CreateMappingParams params); -}; - -class UserMemoryMapping : public VirtualMemoryMapping { - public: - ~UserMemoryMapping() override; - UniquePid upid() const { return upid_; } - - private: - friend class MappingTracker; - UserMemoryMapping(TraceProcessorContext* context, - UniquePid upid, - CreateMappingParams params); - - const UniquePid upid_; -}; - -} // namespace trace_processor -} // namespace perfetto - -#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_VIRTUAL_MEMORY_MAPPING_H_ diff --git a/src/trace_processor/importers/perf/BUILD.gn b/src/trace_processor/importers/perf/BUILD.gn index 960cd276d2..387468fd70 100644 --- a/src/trace_processor/importers/perf/BUILD.gn +++ b/src/trace_processor/importers/perf/BUILD.gn @@ -28,7 +28,6 @@ source_set("perf") { ] deps = [ "../../../../gn:default_deps", - "../../../../protos/perfetto/trace/profiling:zero", "../../importers/common", "../../importers/common:parser_types", "../../sorter", @@ -48,8 +47,6 @@ perfetto_unittest_source_set("unittests") { ":perf", "../../../../gn:default_deps", "../../../../gn:gtest_and_gmock", - "../../../../protos/perfetto/trace/profiling:zero", "../../../base", - "../../importers/common", ] } diff --git a/src/trace_processor/importers/perf/perf_data_parser.cc b/src/trace_processor/importers/perf/perf_data_parser.cc index bb792099f5..11a5a13bd9 100644 --- a/src/trace_processor/importers/perf/perf_data_parser.cc +++ b/src/trace_processor/importers/perf/perf_data_parser.cc @@ -22,7 +22,6 @@ #include "perfetto/base/logging.h" #include "perfetto/ext/base/string_utils.h" #include "perfetto/trace_processor/trace_blob_view.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/perf/perf_data_reader.h" #include "src/trace_processor/importers/perf/perf_data_tracker.h" @@ -59,8 +58,7 @@ void PerfDataParser::ParseTraceBlobView(int64_t ts, TraceBlobView tbv) { // First instruction pointer in the callchain should be from kernel space, so // it shouldn't be available in mappings. - if (context_->mapping_tracker->FindUserMappingForAddress( - *sample.pid, sample.callchain.front())) { + if (tracker_->FindMapping(*sample.pid, sample.callchain.front()).ok()) { context_->storage->IncrementStats(stats::perf_samples_skipped); return; } @@ -72,22 +70,19 @@ void PerfDataParser::ParseTraceBlobView(int64_t ts, TraceBlobView tbv) { std::vector frame_rows; for (uint32_t i = 1; i < sample.callchain.size(); i++) { - UserMemoryMapping* mapping = - context_->mapping_tracker->FindUserMappingForAddress( - *sample.pid, sample.callchain[i]); - if (!mapping) { + auto mapping = tracker_->FindMapping(*sample.pid, sample.callchain[i]); + if (!mapping.ok()) { context_->storage->IncrementStats(stats::perf_samples_skipped); return; } FramesTable::Row new_row; std::string mock_name = - base::StackString<1024>( - "%" PRIu64, sample.callchain[i] - mapping->memory_range().start()) + base::StackString<1024>("%" PRIu64, + sample.callchain[i] - mapping->start) .ToStdString(); new_row.name = context_->storage->InternString(mock_name.c_str()); - new_row.mapping = mapping->mapping_id(); - new_row.rel_pc = - static_cast(mapping->ToRelativePc(sample.callchain[i])); + new_row.mapping = mapping->id; + new_row.rel_pc = static_cast(sample.callchain[i] - mapping->start); frame_rows.push_back(new_row); } diff --git a/src/trace_processor/importers/perf/perf_data_tokenizer.cc b/src/trace_processor/importers/perf/perf_data_tokenizer.cc index 334148a84c..be1ec02663 100644 --- a/src/trace_processor/importers/perf/perf_data_tokenizer.cc +++ b/src/trace_processor/importers/perf/perf_data_tokenizer.cc @@ -15,7 +15,6 @@ */ #include "src/trace_processor/importers/perf/perf_data_tokenizer.h" - #include #include #include @@ -32,29 +31,9 @@ #include "src/trace_processor/storage/stats.h" #include "src/trace_processor/util/status_macros.h" -#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h" - namespace perfetto { namespace trace_processor { namespace perf_importer { -namespace { -protos::pbzero::Profiling::CpuMode GetCpuMode(const perf_event_header& header) { - switch (header.misc & kPerfRecordMiscCpumodeMask) { - case PERF_RECORD_MISC_KERNEL: - return protos::pbzero::Profiling::MODE_KERNEL; - case PERF_RECORD_MISC_USER: - return protos::pbzero::Profiling::MODE_USER; - case PERF_RECORD_MISC_HYPERVISOR: - return protos::pbzero::Profiling::MODE_HYPERVISOR; - case PERF_RECORD_MISC_GUEST_KERNEL: - return protos::pbzero::Profiling::MODE_GUEST_KERNEL; - case PERF_RECORD_MISC_GUEST_USER: - return protos::pbzero::Profiling::MODE_GUEST_USER; - default: - return protos::pbzero::Profiling::MODE_UNKNOWN; - } -} -} // namespace PerfDataTokenizer::PerfDataTokenizer(TraceProcessorContext* ctx) : context_(ctx), @@ -145,7 +124,6 @@ base::Status PerfDataTokenizer::Parse(TraceBlobView blob) { sizeof(PerfDataTracker::Mmap2Record::Numeric)); auto record = ParseMmap2Record(record_size); RETURN_IF_ERROR(record.status()); - record->cpu_mode = GetCpuMode(ev_header); tracker_->PushMmap2Record(*record); break; } diff --git a/src/trace_processor/importers/perf/perf_data_tracker.cc b/src/trace_processor/importers/perf/perf_data_tracker.cc index c670258b3a..0c9b209e65 100644 --- a/src/trace_processor/importers/perf/perf_data_tracker.cc +++ b/src/trace_processor/importers/perf/perf_data_tracker.cc @@ -15,53 +15,12 @@ */ #include "src/trace_processor/importers/perf/perf_data_tracker.h" - -#include - #include "perfetto/base/status.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" -#include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/storage/stats.h" -#include "src/trace_processor/storage/trace_storage.h" - -#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h" namespace perfetto { namespace trace_processor { namespace perf_importer { -namespace { - -bool IsInKernel(protos::pbzero::Profiling::CpuMode cpu_mode) { - switch (cpu_mode) { - case protos::pbzero::Profiling::MODE_UNKNOWN: - PERFETTO_CHECK(false); - case protos::pbzero::Profiling::MODE_GUEST_KERNEL: - case protos::pbzero::Profiling::MODE_KERNEL: - return true; - case protos::pbzero::Profiling::MODE_USER: - case protos::pbzero::Profiling::MODE_HYPERVISOR: - case protos::pbzero::Profiling::MODE_GUEST_USER: - return false; - } - PERFETTO_CHECK(false); -} - -CreateMappingParams BuildCreateMappingParams( - PerfDataTracker::Mmap2Record record) { - return {AddressRange::FromStartAndSize(record.num.addr, record.num.len), - record.num.pgoff, - // start_offset: This is the offset into the file where the ELF header - // starts. We assume all file mappings are ELF files an thus this - // offset is 0. - 0, - // load_bias: This can only be read out of the actual ELF file, which - // we do not have here, so we set it to 0. When symbolizing we will - // hopefully have the real load bias and we can compensate there for a - // possible mismatch. - 0, record.filename, std::nullopt}; -} -} // namespace PerfDataTracker::~PerfDataTracker() = default; @@ -89,15 +48,31 @@ const perf_event_attr* PerfDataTracker::FindAttrWithId(uint64_t id) const { } void PerfDataTracker::PushMmap2Record(Mmap2Record record) { - if (IsInKernel(record.cpu_mode)) { - context_->mapping_tracker->CreateKernelMemoryMapping( - BuildCreateMappingParams(std::move(record))); - } else { - UniquePid upid = - context_->process_tracker->GetOrCreateProcess(record.num.pid); - context_->mapping_tracker->CreateUserMemoryMapping( - upid, BuildCreateMappingParams(std::move(record))); + const auto mappings = + context_->storage->mutable_stack_profile_mapping_table(); + MappingTable::Row row; + row.start = static_cast(record.num.addr); + row.end = static_cast(record.num.addr + record.num.len); + row.name = context_->storage->InternString(record.filename.c_str()); + MappingTable::Id id = mappings->Insert(row).id; + MmapRange mmap2_range{record.num.addr, record.num.addr + record.num.len, id}; + mmap2_ranges_[record.num.pid].push_back(mmap2_range); +} + +base::StatusOr PerfDataTracker::FindMapping( + uint32_t pid, + uint64_t ips) { + auto vec = mmap2_ranges_.Find(pid); + if (!vec) { + return base::ErrStatus("Sample pid not found in mappings."); + } + + for (const auto& range : *vec) { + if (ips >= range.start && ips < range.end) { + return range; + } } + return base::ErrStatus("No mapping for callstack frame instruction pointer"); } base::StatusOr PerfDataTracker::ParseSample( diff --git a/src/trace_processor/importers/perf/perf_data_tracker.h b/src/trace_processor/importers/perf/perf_data_tracker.h index 11258edd73..0ab99aa6b4 100644 --- a/src/trace_processor/importers/perf/perf_data_tracker.h +++ b/src/trace_processor/importers/perf/perf_data_tracker.h @@ -25,7 +25,6 @@ #include "perfetto/ext/base/flat_hash_map.h" #include "perfetto/ext/base/status_or.h" #include "perfetto/ext/base/string_utils.h" -#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h" #include "src/trace_processor/importers/perf/perf_data_reader.h" #include "src/trace_processor/importers/perf/perf_event.h" #include "src/trace_processor/storage/trace_storage.h" @@ -77,10 +76,14 @@ class PerfDataTracker : public Destructible { uint32_t prot; uint32_t flags; }; - protos::pbzero::Profiling::CpuMode cpu_mode; Numeric num; std::string filename; }; + struct MmapRange { + uint64_t start; + uint64_t end; + MappingTable::Id id; + }; PerfDataTracker(const PerfDataTracker&) = delete; PerfDataTracker& operator=(const PerfDataTracker&) = delete; @@ -100,11 +103,14 @@ class PerfDataTracker : public Destructible { base::StatusOr ParseSample( perfetto::trace_processor::perf_importer::Reader&); + base::StatusOr FindMapping(uint32_t pid, uint64_t ips); + private: const perf_event_attr* FindAttrWithId(uint64_t id) const; TraceProcessorContext* context_; std::vector attrs_; + base::FlatHashMap> mmap2_ranges_; uint64_t common_sample_type_; }; } // namespace perf_importer diff --git a/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc b/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc index 3cbdc801a3..6c59be6d65 100644 --- a/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc +++ b/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc @@ -22,35 +22,16 @@ #include #include "perfetto/base/build_config.h" -#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" -#include "src/trace_processor/importers/common/process_tracker.h" -#include "src/trace_processor/importers/common/stack_profile_tracker.h" #include "src/trace_processor/importers/perf/perf_event.h" #include "test/gtest_and_gmock.h" namespace perfetto { namespace trace_processor { namespace perf_importer { -namespace { -class PerfDataTrackerUnittest : public testing::Test { - public: - PerfDataTrackerUnittest() { - context_.storage = std::make_unique(); - context_.process_tracker = std::make_unique(&context_); - context_.stack_profile_tracker = - std::make_unique(&context_); - context_.mapping_tracker = std::make_unique(&context_); - } - - protected: - TraceProcessorContext context_; -}; - -TEST_F(PerfDataTrackerUnittest, ComputeCommonSampleType) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, ComputeCommonSampleType) { + TraceProcessorContext context; + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::AttrAndIds attr_and_ids; attr_and_ids.attr.sample_type = @@ -65,15 +46,16 @@ TEST_F(PerfDataTrackerUnittest, ComputeCommonSampleType) { EXPECT_FALSE(tracker->common_sample_type() & PERF_SAMPLE_CALLCHAIN); } -TEST_F(PerfDataTrackerUnittest, FindMapping) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, FindMapping) { + TraceProcessorContext context; + context.storage = std::make_unique(); + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::Mmap2Record rec; rec.filename = "file1"; rec.num.addr = 1000; rec.num.len = 100; rec.num.pid = 1; - rec.cpu_mode = protos::pbzero::Profiling::MODE_USER; tracker->PushMmap2Record(rec); rec.num.addr = 2000; @@ -82,33 +64,32 @@ TEST_F(PerfDataTrackerUnittest, FindMapping) { rec.num.addr = 3000; tracker->PushMmap2Record(rec); - UserMemoryMapping* mapping = - context_.mapping_tracker->FindUserMappingForAddress( - context_.process_tracker->GetOrCreateProcess(1), 2050); - ASSERT_NE(mapping, nullptr); - EXPECT_EQ(mapping->memory_range().start(), 2000u); - EXPECT_EQ(mapping->memory_range().end(), 2100u); + auto res_status = tracker->FindMapping(1, 2050); + EXPECT_TRUE(res_status.ok()); + EXPECT_EQ(res_status->start, 2000u); + EXPECT_EQ(res_status->end, 2100u); } -TEST_F(PerfDataTrackerUnittest, FindMappingFalse) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, FindMappingFalse) { + TraceProcessorContext context; + context.storage = std::make_unique(); + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::Mmap2Record rec; rec.filename = "file1"; rec.num.addr = 1000; rec.num.len = 100; rec.num.pid = 1; - rec.cpu_mode = protos::pbzero::Profiling::MODE_USER; tracker->PushMmap2Record(rec); - UserMemoryMapping* mapping = - context_.mapping_tracker->FindUserMappingForAddress( - context_.process_tracker->GetOrCreateProcess(2), 2050); - EXPECT_EQ(mapping, nullptr); + auto res_status = tracker->FindMapping(2, 2050); + EXPECT_FALSE(res_status.ok()); } -TEST_F(PerfDataTrackerUnittest, ParseSampleTrivial) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, ParseSampleTrivial) { + TraceProcessorContext context; + context.storage = std::make_unique(); + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::AttrAndIds attr_and_ids; attr_and_ids.attr.sample_type = PERF_SAMPLE_TIME; @@ -126,8 +107,10 @@ TEST_F(PerfDataTrackerUnittest, ParseSampleTrivial) { EXPECT_EQ(parsed_sample->ts, 100u); } -TEST_F(PerfDataTrackerUnittest, ParseSampleCallchain) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, ParseSampleCallchain) { + TraceProcessorContext context; + context.storage = std::make_unique(); + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::AttrAndIds attr_and_ids; attr_and_ids.attr.sample_type = PERF_SAMPLE_CALLCHAIN; @@ -154,8 +137,10 @@ TEST_F(PerfDataTrackerUnittest, ParseSampleCallchain) { EXPECT_EQ(parsed_sample->callchain.size(), 3u); } -TEST_F(PerfDataTrackerUnittest, ParseSampleWithoutId) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, ParseSampleWithoutId) { + TraceProcessorContext context; + context.storage = std::make_unique(); + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::AttrAndIds attr_and_ids; attr_and_ids.attr.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | @@ -192,8 +177,10 @@ TEST_F(PerfDataTrackerUnittest, ParseSampleWithoutId) { EXPECT_EQ(sample.ts, parsed_sample->ts); } -TEST_F(PerfDataTrackerUnittest, ParseSampleWithId) { - PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_); +TEST(PerfDataTrackerUnittest, ParseSampleWithId) { + TraceProcessorContext context; + context.storage = std::make_unique(); + PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context); PerfDataTracker::AttrAndIds attr_and_ids; attr_and_ids.attr.sample_type = PERF_SAMPLE_CPU | PERF_SAMPLE_TID | @@ -235,7 +222,6 @@ TEST_F(PerfDataTrackerUnittest, ParseSampleWithId) { EXPECT_EQ(100u, parsed_sample->ts); } -} // namespace } // namespace perf_importer } // namespace trace_processor } // namespace perfetto diff --git a/src/trace_processor/importers/perf/perf_event.h b/src/trace_processor/importers/perf/perf_event.h index c60709f8c1..53f5f05eab 100644 --- a/src/trace_processor/importers/perf/perf_event.h +++ b/src/trace_processor/importers/perf/perf_event.h @@ -223,15 +223,4 @@ enum perf_event_sample_format { PERF_SAMPLE_MAX = 1U << 25, /* non-ABI */ }; -constexpr auto kPerfRecordMiscCpumodeMask = 0x7; - -enum perf_record_misc { - PERF_RECORD_MISC_CPUMODE_UNKNOWN = 0, - PERF_RECORD_MISC_KERNEL = 1, - PERF_RECORD_MISC_USER = 2, - PERF_RECORD_MISC_HYPERVISOR = 3, - PERF_RECORD_MISC_GUEST_KERNEL = 4, - PERF_RECORD_MISC_GUEST_USER = 5, -}; - #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PERF_PERF_EVENT_H_ diff --git a/src/trace_processor/importers/proto/BUILD.gn b/src/trace_processor/importers/proto/BUILD.gn index 2e542d09c3..2eaa5feb17 100644 --- a/src/trace_processor/importers/proto/BUILD.gn +++ b/src/trace_processor/importers/proto/BUILD.gn @@ -91,9 +91,9 @@ source_set("minimal") { "../../storage", "../../tables", "../../types", - "../../util:build_id", "../../util:gzip", "../../util:profiler_util", + "../../util:stack_traces_util", "../common", "../common:parser_types", "../ftrace:minimal", @@ -181,6 +181,7 @@ source_set("full") { "../../util:profiler_util", "../../util:proto_profiler", "../../util:proto_to_args_parser", + "../../util:stack_traces_util", "../common", "../common:parser_types", "../etw:full", @@ -275,6 +276,7 @@ source_set("unittests") { "../../types", "../../util:descriptors", "../../util:profiler_util", + "../../util:stack_traces_util", "../common", "../ftrace:full", ] diff --git a/src/trace_processor/importers/proto/profile_module.cc b/src/trace_processor/importers/proto/profile_module.cc index b80cae71e9..61596d3bbb 100644 --- a/src/trace_processor/importers/proto/profile_module.cc +++ b/src/trace_processor/importers/proto/profile_module.cc @@ -24,7 +24,6 @@ #include "src/trace_processor/importers/common/clock_tracker.h" #include "src/trace_processor/importers/common/deobfuscation_mapping_table.h" #include "src/trace_processor/importers/common/event_tracker.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/common/stack_profile_tracker.h" #include "src/trace_processor/importers/proto/packet_sequence_state.h" @@ -37,8 +36,8 @@ #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/tables/profiler_tables_py.h" #include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" #include "src/trace_processor/util/profiler_util.h" +#include "src/trace_processor/util/stack_traces_util.h" #include "protos/perfetto/common/builtin_clock.pbzero.h" #include "protos/perfetto/common/perf_events.pbzero.h" @@ -429,11 +428,19 @@ void ProfileModule::ParseProfilePacket(int64_t ts, void ProfileModule::ParseModuleSymbols(ConstBytes blob) { protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size); - BuildId build_id = BuildId::FromRaw(module_symbols.build_id()); + StringId build_id; + // TODO(b/148109467): Remove workaround once all active Chrome versions + // write raw bytes instead of a string as build_id. + if (util::IsHexModuleId(module_symbols.build_id())) { + build_id = context_->storage->InternString(module_symbols.build_id()); + } else { + build_id = context_->storage->InternString(base::StringView(base::ToHex( + module_symbols.build_id().data, module_symbols.build_id().size))); + } - auto mappings = - context_->mapping_tracker->FindMappings(module_symbols.path(), build_id); - if (mappings.empty()) { + auto mapping_ids = context_->stack_profile_tracker->FindMappingRow( + context_->storage->InternString(module_symbols.path()), build_id); + if (mapping_ids.empty()) { context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id); return; } @@ -460,11 +467,12 @@ void ProfileModule::ParseModuleSymbols(ConstBytes blob) { continue; } bool frame_found = false; - for (VirtualMemoryMapping* mapping : mappings) { + for (MappingId mapping_id : mapping_ids) { context_->args_translation_table->AddNativeSymbolTranslationRule( - mapping->mapping_id(), address_symbols.address(), last_location); + mapping_id, address_symbols.address(), last_location); std::vector frame_ids = - mapping->FindFrameIds(address_symbols.address()); + context_->stack_profile_tracker->FindFrameIds( + mapping_id, address_symbols.address()); for (const FrameId frame_id : frame_ids) { auto* frames = context_->storage->mutable_stack_profile_frame_table(); diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state.cc b/src/trace_processor/importers/proto/profile_packet_sequence_state.cc index 31841fc0e5..9d889efbc7 100644 --- a/src/trace_processor/importers/proto/profile_packet_sequence_state.cc +++ b/src/trace_processor/importers/proto/profile_packet_sequence_state.cc @@ -19,8 +19,6 @@ #include "perfetto/base/flat_set.h" #include "perfetto/base/logging.h" #include "perfetto/ext/base/string_view.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/common/stack_profile_tracker.h" #include "src/trace_processor/importers/proto/packet_sequence_state.h" @@ -30,7 +28,6 @@ #include "src/trace_processor/storage/stats.h" #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" namespace perfetto { namespace trace_processor { @@ -71,16 +68,17 @@ void ProfilePacketSequenceState::AddString(SourceStringId id, void ProfilePacketSequenceState::AddMapping(SourceMappingId id, const SourceMapping& mapping) { - CreateMappingParams params; + StackProfileTracker::CreateMappingParams params; if (std::string* str = strings_.Find(mapping.build_id); str) { - params.build_id = BuildId::FromRaw(*str); + params.build_id = base::StringView(*str); } else { context_->storage->IncrementStats(stats::stackprofile_invalid_string_id); return; } params.exact_offset = mapping.exact_offset; params.start_offset = mapping.start_offset; - params.memory_range = AddressRange(mapping.start, mapping.end); + params.start = mapping.start; + params.end = mapping.end; params.load_bias = mapping.load_bias; std::vector path_components; @@ -95,16 +93,16 @@ void ProfilePacketSequenceState::AddMapping(SourceMappingId id, break; } } - - params.name = ProfilePacketUtils::MakeMappingName(path_components); - mappings_.Insert( - id, &context_->mapping_tracker->InternMemoryMapping(std::move(params))); + std::string path = ProfilePacketUtils::MakeMappingName(path_components); + params.name = base::StringView(path); + MappingId mapping_id = context_->stack_profile_tracker->InternMapping(params); + mappings_.Insert(id, mapping_id); } void ProfilePacketSequenceState::AddFrame(SourceFrameId id, const SourceFrame& frame) { - VirtualMemoryMapping** mapping = mappings_.Find(frame.mapping_id); - if (!mapping) { + MappingId* mapping_id = mappings_.Find(frame.mapping_id); + if (!mapping_id) { context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id); return; } @@ -115,8 +113,9 @@ void ProfilePacketSequenceState::AddFrame(SourceFrameId id, return; } - FrameId frame_id = - (*mapping)->InternFrame(frame.rel_pc, base::StringView(*function_name)); + FrameId frame_id = context_->stack_profile_tracker->InternFrame( + *mapping_id, frame.rel_pc, base::StringView(*function_name)); + frames_.Insert(id, frame_id); } diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state.h b/src/trace_processor/importers/proto/profile_packet_sequence_state.h index 99661da36c..678aab2c4c 100644 --- a/src/trace_processor/importers/proto/profile_packet_sequence_state.h +++ b/src/trace_processor/importers/proto/profile_packet_sequence_state.h @@ -23,6 +23,7 @@ #include "perfetto/ext/base/hash.h" #include "perfetto/ext/base/string_view.h" +#include "protos/perfetto/trace/profiling/profile_common.pbzero.h" #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h" #include "src/trace_processor/importers/proto/stack_profile_sequence_state.h" #include "src/trace_processor/storage/trace_storage.h" @@ -30,8 +31,6 @@ namespace perfetto { namespace trace_processor { -class VirtualMemoryMapping; - // Keeps sequence specific state for profile packets. class ProfilePacketSequenceState final : public PacketSequenceStateGeneration::InternedDataTracker { @@ -127,7 +126,7 @@ class ProfilePacketSequenceState final TraceProcessorContext* const context_; base::FlatHashMap strings_; - base::FlatHashMap mappings_; + base::FlatHashMap mappings_; base::FlatHashMap frames_; base::FlatHashMap callstacks_; diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc index c9cd6e365c..ab947fadda 100644 --- a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc +++ b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc @@ -18,9 +18,8 @@ #include -#include "src/trace_processor/importers/common/mapping_tracker.h" -#include "src/trace_processor/importers/common/stack_profile_tracker.h" #include "src/trace_processor/importers/proto/packet_sequence_state.h" +#include "src/trace_processor/importers/common/stack_profile_tracker.h" #include "src/trace_processor/types/trace_processor_context.h" #include "test/gtest_and_gmock.h" @@ -59,7 +58,6 @@ class HeapProfileTrackerDupTest : public ::testing::Test { public: HeapProfileTrackerDupTest() { context.storage.reset(new TraceStorage()); - context.mapping_tracker.reset(new MappingTracker(&context)); context.stack_profile_tracker.reset(new StackProfileTracker(&context)); packet_sequence_state.reset(new PacketSequenceState(&context)); @@ -198,7 +196,6 @@ std::optional FindCallstack(const TraceStorage& storage, TEST(HeapProfileTrackerTest, SourceMappingPath) { TraceProcessorContext context; context.storage.reset(new TraceStorage()); - context.mapping_tracker.reset(new MappingTracker(&context)); context.stack_profile_tracker.reset(new StackProfileTracker(&context)); PacketSequenceState pss(&context); ProfilePacketSequenceState& ppss = @@ -232,7 +229,6 @@ TEST(HeapProfileTrackerTest, SourceMappingPath) { TEST(HeapProfileTrackerTest, Functional) { TraceProcessorContext context; context.storage.reset(new TraceStorage()); - context.mapping_tracker.reset(new MappingTracker(&context)); context.stack_profile_tracker.reset(new StackProfileTracker(&context)); PacketSequenceState pss(&context); diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc index dc05d36c11..148bf60948 100644 --- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc +++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc @@ -25,7 +25,6 @@ #include "src/trace_processor/importers/common/clock_tracker.h" #include "src/trace_processor/importers/common/event_tracker.h" #include "src/trace_processor/importers/common/flow_tracker.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/metadata_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/common/slice_tracker.h" @@ -253,7 +252,6 @@ class ProtoTraceParserTest : public ::testing::Test { context_.track_tracker.reset(new TrackTracker(&context_)); context_.global_args_tracker.reset( new GlobalArgsTracker(context_.storage.get())); - context_.mapping_tracker.reset(new MappingTracker(&context_)); context_.stack_profile_tracker.reset(new StackProfileTracker(&context_)); context_.args_tracker.reset(new ArgsTracker(&context_)); context_.args_translation_table.reset(new ArgsTranslationTable(storage_)); diff --git a/src/trace_processor/importers/proto/stack_profile_sequence_state.cc b/src/trace_processor/importers/proto/stack_profile_sequence_state.cc index a469f920a6..e503a09acb 100644 --- a/src/trace_processor/importers/proto/stack_profile_sequence_state.cc +++ b/src/trace_processor/importers/proto/stack_profile_sequence_state.cc @@ -23,8 +23,6 @@ #include "perfetto/ext/base/string_view.h" #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h" #include "protos/perfetto/trace/profiling/profile_common.pbzero.h" -#include "src/trace_processor/importers/common/address_range.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/stack_profile_tracker.h" #include "src/trace_processor/importers/proto/packet_sequence_state.h" #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h" @@ -32,7 +30,6 @@ #include "src/trace_processor/storage/stats.h" #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/types/trace_processor_context.h" -#include "src/trace_processor/util/build_id.h" namespace perfetto { namespace trace_processor { @@ -51,23 +48,21 @@ StackProfileSequenceState::~StackProfileSequenceState() = default; std::optional StackProfileSequenceState::FindOrInsertMapping( uint64_t iid) { - if (VirtualMemoryMapping* mapping = FindOrInsertMappingImpl(iid); mapping) { - return mapping->mapping_id(); - } - return std::nullopt; -} - -VirtualMemoryMapping* StackProfileSequenceState::FindOrInsertMappingImpl( - uint64_t iid) { - if (auto ptr = cached_mappings_.Find(iid); ptr) { - return *ptr; + if (MappingId* id = cached_mappings_.Find(iid); id) { + return *id; } auto* decoder = LookupInternedMessage(iid); if (!decoder) { context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id); - return nullptr; + return std::nullopt; + } + + std::optional build_id = + LookupInternedBuildId(decoder->build_id()); + if (!build_id) { + return std::nullopt; } std::vector path_components; @@ -80,26 +75,19 @@ VirtualMemoryMapping* StackProfileSequenceState::FindOrInsertMappingImpl( } path_components.push_back(*str); } + std::string path = ProfilePacketUtils::MakeMappingName(path_components); - CreateMappingParams params; - std::optional build_id = - LookupInternedBuildId(decoder->build_id()); - if (!build_id) { - return nullptr; - } - params.build_id = BuildId::FromRaw(*build_id); - - params.memory_range = AddressRange(decoder->start(), decoder->end()); + StackProfileTracker::CreateMappingParams params; + params.build_id = *build_id; params.exact_offset = decoder->exact_offset(); params.start_offset = decoder->start_offset(); + params.start = decoder->start(); + params.end = decoder->end(); params.load_bias = decoder->load_bias(); - params.name = ProfilePacketUtils::MakeMappingName(path_components); - - VirtualMemoryMapping& mapping = - context_->mapping_tracker->InternMemoryMapping(std::move(params)); - - cached_mappings_.Insert(iid, &mapping); - return &mapping; + params.name = base::StringView(path); + MappingId mapping_id = context_->stack_profile_tracker->InternMapping(params); + cached_mappings_.Insert(iid, mapping_id); + return mapping_id; } std::optional @@ -122,6 +110,11 @@ StackProfileSequenceState::LookupInternedBuildId(uint64_t iid) { std::optional StackProfileSequenceState::LookupInternedMappingPath(uint64_t iid) { + // This should really be an error (value not set) or at the very least return + // a null string, but for backward compatibility use an empty string instead. + if (iid == 0) { + return ""; + } auto* decoder = LookupInternedMessage< protos::pbzero::InternedData::kMappingPathsFieldNumber, protos::pbzero::InternedString>(iid); @@ -165,7 +158,7 @@ std::optional StackProfileSequenceState::FindOrInsertCallstack( cached_callstacks_.Insert(iid, *parent_callsite_id); - return parent_callsite_id; + return *parent_callsite_id; } std::optional StackProfileSequenceState::FindOrInsertFrame( @@ -181,9 +174,9 @@ std::optional StackProfileSequenceState::FindOrInsertFrame( return std::nullopt; } - VirtualMemoryMapping* mapping = - FindOrInsertMappingImpl(decoder->mapping_id()); - if (!mapping) { + std::optional mapping_id = + FindOrInsertMapping(decoder->mapping_id()); + if (!mapping_id) { return std::nullopt; } @@ -197,7 +190,9 @@ std::optional StackProfileSequenceState::FindOrInsertFrame( function_name = *func; } - FrameId frame_id = mapping->InternFrame(decoder->rel_pc(), function_name); + FrameId frame_id = context_->stack_profile_tracker->InternFrame( + *mapping_id, decoder->rel_pc(), function_name); + cached_frames_.Insert(iid, frame_id); return frame_id; diff --git a/src/trace_processor/importers/proto/stack_profile_sequence_state.h b/src/trace_processor/importers/proto/stack_profile_sequence_state.h index 82de785edd..7a7879a7b1 100644 --- a/src/trace_processor/importers/proto/stack_profile_sequence_state.h +++ b/src/trace_processor/importers/proto/stack_profile_sequence_state.h @@ -30,7 +30,6 @@ namespace perfetto { namespace trace_processor { class TraceProcessorContext; -class VirtualMemoryMapping; class StackProfileSequenceState final : public PacketSequenceStateGeneration::InternedDataTracker { @@ -45,15 +44,13 @@ class StackProfileSequenceState final std::optional FindOrInsertCallstack(uint64_t iid); private: - // Returns `nullptr`if non could be found. - VirtualMemoryMapping* FindOrInsertMappingImpl(uint64_t iid); std::optional LookupInternedBuildId(uint64_t iid); std::optional LookupInternedMappingPath(uint64_t iid); std::optional LookupInternedFunctionName(uint64_t iid); std::optional FindOrInsertFrame(uint64_t iid); TraceProcessorContext* const context_; - base::FlatHashMap cached_mappings_; + base::FlatHashMap cached_mappings_; base::FlatHashMap cached_callstacks_; base::FlatHashMap cached_frames_; }; diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc index f4f6c48572..c7cea38520 100644 --- a/src/trace_processor/trace_processor_context.cc +++ b/src/trace_processor/trace_processor_context.cc @@ -27,7 +27,6 @@ #include "src/trace_processor/importers/common/event_tracker.h" #include "src/trace_processor/importers/common/flow_tracker.h" #include "src/trace_processor/importers/common/global_args_tracker.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/metadata_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/common/slice_tracker.h" diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc index 4b47d52b99..05b88c0c64 100644 --- a/src/trace_processor/trace_processor_storage_impl.cc +++ b/src/trace_processor/trace_processor_storage_impl.cc @@ -26,7 +26,6 @@ #include "src/trace_processor/importers/common/clock_tracker.h" #include "src/trace_processor/importers/common/event_tracker.h" #include "src/trace_processor/importers/common/flow_tracker.h" -#include "src/trace_processor/importers/common/mapping_tracker.h" #include "src/trace_processor/importers/common/metadata_tracker.h" #include "src/trace_processor/importers/common/process_tracker.h" #include "src/trace_processor/importers/common/slice_tracker.h" @@ -63,7 +62,6 @@ TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) { context_.process_tracker.reset(new ProcessTracker(&context_)); context_.clock_tracker.reset(new ClockTracker(&context_)); context_.clock_converter.reset(new ClockConverter(&context_)); - context_.mapping_tracker.reset(new MappingTracker(&context_)); context_.perf_sample_tracker.reset(new PerfSampleTracker(&context_)); context_.stack_profile_tracker.reset(new StackProfileTracker(&context_)); context_.metadata_tracker.reset(new MetadataTracker(context_.storage.get())); diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h index 769ca0e064..ad4e148a25 100644 --- a/src/trace_processor/types/trace_processor_context.h +++ b/src/trace_processor/types/trace_processor_context.h @@ -55,7 +55,6 @@ class GlobalArgsTracker; class StackProfileTracker; class HeapGraphTracker; class PerfSampleTracker; -class MappingTracker; class MetadataTracker; class PacketAnalyzer; class ProtoImporterModule; @@ -101,7 +100,6 @@ class TraceProcessorContext { std::unique_ptr event_tracker; std::unique_ptr clock_tracker; std::unique_ptr clock_converter; - std::unique_ptr mapping_tracker; std::unique_ptr perf_sample_tracker; std::unique_ptr stack_profile_tracker; std::unique_ptr metadata_tracker; diff --git a/src/trace_processor/util/BUILD.gn b/src/trace_processor/util/BUILD.gn index 13aefe5e15..8420a067b5 100644 --- a/src/trace_processor/util/BUILD.gn +++ b/src/trace_processor/util/BUILD.gn @@ -61,27 +61,28 @@ source_set("gzip") { } } -source_set("build_id") { +source_set("profiler_util") { sources = [ - "build_id.cc", - "build_id.h", + "profiler_util.cc", + "profiler_util.h", ] deps = [ "../../../gn:default_deps", "../../../include/perfetto/ext/base:base", + "../../../protos/perfetto/trace/profiling:zero", + "../storage:storage", ] } -source_set("profiler_util") { +source_set("stack_traces_util") { sources = [ - "profiler_util.cc", - "profiler_util.h", + "stack_traces_util.cc", + "stack_traces_util.h", ] deps = [ "../../../gn:default_deps", "../../../include/perfetto/ext/base:base", "../../../protos/perfetto/trace/profiling:zero", - "../storage:storage", ] } diff --git a/src/trace_processor/util/build_id.cc b/src/trace_processor/util/build_id.cc deleted file mode 100644 index 889291ddd9..0000000000 --- a/src/trace_processor/util/build_id.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "src/trace_processor/util/build_id.h" - -#include -#include -#include - -#include "perfetto/base/logging.h" -#include "perfetto/ext/base/string_utils.h" -#include "perfetto/ext/base/string_view.h" - -namespace perfetto { -namespace trace_processor { -namespace { -uint8_t HexToBinary(char c) { - switch (c) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - case 'a': - case 'A': - return 10; - case 'b': - case 'B': - return 11; - case 'c': - case 'C': - return 12; - case 'd': - case 'D': - return 13; - case 'e': - case 'E': - return 14; - case 'f': - case 'F': - return 15; - default: - PERFETTO_CHECK(false); - } -} - -std::string HexToBinary(base::StringView hex) { - std::string res; - res.reserve((hex.size() + 1) / 2); - auto it = hex.begin(); - - if (hex.size() % 2 != 0) { - res.push_back(static_cast(HexToBinary(*it))); - ++it; - } - - while (it != hex.end()) { - int v = (HexToBinary(*it++) << 4); - v += HexToBinary(*it++); - res.push_back(static_cast(v)); - } - return res; -} - -bool IsHex(base::StringView module) { - for (char c : module) { - if (!std::isxdigit(c)) { - return false; - } - } - return true; -} - -// Returns whether this string is of a hex chrome module or not to decide -// whether to convert the module to/from hex. -// TODO(b/148109467): Remove workaround once all active Chrome versions -// write raw bytes instead of a string as build_id. -bool IsHexModuleId(base::StringView module) { - return module.size() == 33 && IsHex(module); -} - -} // namespace - -// static -BuildId BuildId::FromHex(base::StringView data) { - if (IsHexModuleId(data)) { - return BuildId(data.ToStdString()); - } - return BuildId(HexToBinary(data)); -} - -std::string BuildId::ToHex() const { - if (IsHexModuleId(base::StringView(raw_))) { - return raw_; - } - return base::ToHex(raw_.data(), raw_.size()); -} - -} // namespace trace_processor -} // namespace perfetto diff --git a/src/trace_processor/util/build_id.h b/src/trace_processor/util/build_id.h deleted file mode 100644 index 64ec9acb62..0000000000 --- a/src/trace_processor/util/build_id.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SRC_TRACE_PROCESSOR_UTIL_BUILD_ID_H_ -#define SRC_TRACE_PROCESSOR_UTIL_BUILD_ID_H_ - -#include -#include - -#include "perfetto/ext/base/hash.h" -#include "perfetto/ext/base/string_view.h" - -namespace perfetto { -namespace trace_processor { - -// Represents the unique identifier of an executable, shared library, or module. -// For example for ELF files this is the id stored in the .note.gnu.build-id -// section. Sometimes a breakpad module id is used. -// This class abstracts away the details of where this id comes from and how it -// is converted to a StringId which is the representation used by tables in -// trace_processor. -class BuildId { - public: - // Allow hashing with base::Hash. - static constexpr bool kHashable = true; - size_t size() const { return raw_.size(); } - const char* data() const { return raw_.data(); } - - static BuildId FromHex(base::StringView data); - - static BuildId FromRaw(base::StringView data) { - return BuildId(data.ToStdString()); - } - static BuildId FromRaw(std::string data) { return BuildId(std::move(data)); } - static BuildId FromRaw(const uint8_t* data, size_t size) { - return BuildId(std::string(reinterpret_cast(data), size)); - } - - BuildId(const BuildId&) = default; - BuildId(BuildId&&) = default; - - BuildId& operator=(const BuildId&) = default; - BuildId& operator=(BuildId&&) = default; - - bool operator==(const BuildId& o) const { return raw_ == o.raw_; } - - bool operator!=(const BuildId& o) const { return !(*this == o); } - - bool operator<(const BuildId& o) const { return raw_ < o.raw_; } - - std::string ToHex() const; - - const std::string& raw() const { return raw_; } - - private: - explicit BuildId(std::string data) : raw_(std::move(data)) {} - std::string raw_; -}; - -} // namespace trace_processor -} // namespace perfetto - -template <> -struct std::hash { - std::size_t operator()( - const perfetto::trace_processor::BuildId& o) const noexcept { - return perfetto::base::Hasher::Combine(o); - } -}; - -#endif // SRC_TRACE_PROCESSOR_UTIL_BUILD_ID_H_ diff --git a/src/trace_processor/util/stack_traces_util.cc b/src/trace_processor/util/stack_traces_util.cc new file mode 100644 index 0000000000..a255560e77 --- /dev/null +++ b/src/trace_processor/util/stack_traces_util.cc @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "src/trace_processor/util/stack_traces_util.h" +#include "perfetto/ext/base/string_view.h" + +namespace perfetto { +namespace trace_processor { +namespace util { + +bool IsHexModuleId(base::StringView module) { + return module.size() == 33; +} + +} // namespace util +} // namespace trace_processor +} // namespace perfetto diff --git a/src/trace_processor/util/stack_traces_util.h b/src/trace_processor/util/stack_traces_util.h new file mode 100644 index 0000000000..117178690a --- /dev/null +++ b/src/trace_processor/util/stack_traces_util.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_TRACE_PROCESSOR_UTIL_STACK_TRACES_UTIL_H_ +#define SRC_TRACE_PROCESSOR_UTIL_STACK_TRACES_UTIL_H_ + +#include "perfetto/ext/base/string_view.h" + +namespace perfetto { +namespace trace_processor { +namespace util { + +// Returns whether this string is of a hex chrome module or not to decide +// whether to convert the module to/from hex. +// TODO(b/148109467): Remove workaround once all active Chrome versions +// write raw bytes instead of a string as build_id. +bool IsHexModuleId(base::StringView module); + +} // namespace util +} // namespace trace_processor +} // namespace perfetto + +#endif // SRC_TRACE_PROCESSOR_UTIL_STACK_TRACES_UTIL_H_