• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/importers/etm/virtual_address_space.h"
18 
19 #include <cstdint>
20 #include <limits>
21 #include <optional>
22 #include <set>
23 #include <utility>
24 #include <vector>
25 
26 #include "perfetto/base/logging.h"
27 #include "perfetto/trace_processor/trace_blob_view.h"
28 #include "src/trace_processor/importers/common/address_range.h"
29 #include "src/trace_processor/importers/etm/file_tracker.h"
30 #include "src/trace_processor/importers/etm/mapping_version.h"
31 #include "src/trace_processor/storage/trace_storage.h"
32 #include "src/trace_processor/tables/perf_tables_py.h"
33 #include "src/trace_processor/tables/profiler_tables_py.h"
34 #include "src/trace_processor/types/trace_processor_context.h"
35 
36 namespace perfetto::trace_processor::etm {
AddMapping(tables::MmapRecordTable::ConstRowReference mmap)37 void VirtualAddressSpace::Builder::AddMapping(
38     tables::MmapRecordTable::ConstRowReference mmap) {
39   const auto mapping =
40       *context_->storage->stack_profile_mapping_table().FindById(
41           mmap.mapping_id());
42   if (static_cast<uint64_t>(mapping.start()) >=
43       static_cast<uint64_t>(mapping.end())) {
44     return;
45   }
46 
47   AddressRange range(static_cast<uint64_t>(mapping.start()),
48                      static_cast<uint64_t>(mapping.end()));
49 
50   std::optional<TraceBlobView> content;
51   if (mmap.file_id()) {
52     content = FileTracker::GetOrCreate(context_)->GetContent(*mmap.file_id());
53     auto file_range = AddressRange::FromStartAndSize(0, content->size());
54     auto required_file_range = AddressRange::FromStartAndSize(
55         static_cast<uint64_t>(mapping.exact_offset()), range.size());
56 
57     PERFETTO_CHECK(file_range.Contains(required_file_range));
58 
59     content = content->slice_off(required_file_range.start(),
60                                  required_file_range.length());
61   }
62 
63   auto [it, success] = mappings_.insert(
64       MappingVersion(mmap.mapping_id(), mmap.ts(), range, std::move(content)));
65   PERFETTO_CHECK(success);
66   vertices_.insert(it->start());
67   vertices_.insert(it->end());
68 }
69 
Build()70 VirtualAddressSpace VirtualAddressSpace::Builder::Build() && {
71   std::vector<MappingVersion> slabs;
72   // Go over the mappins and process each vertex.
73   while (!mappings_.empty()) {
74     auto node = mappings_.extract(mappings_.begin());
75     auto end = vertices_.begin();
76     // Mapping starts at the vertex, noting to do.
77     while (*end <= node.value().start()) {
78       end = vertices_.erase(end);
79     }
80     // The mapping ends at this vertex, no need to split it.
81     if (node.value().end() == *end) {
82       slabs.push_back(std::move(node.value()));
83     }
84     // Split needed
85     else {
86       slabs.push_back(node.value().SplitFront(*end));
87       mappings_.insert(std::move(node));
88     }
89   }
90 
91   return VirtualAddressSpace(std::move(slabs));
92 }
93 
FindMapping(int64_t ts,uint64_t address) const94 const MappingVersion* VirtualAddressSpace::FindMapping(int64_t ts,
95                                                        uint64_t address) const {
96   if (address == std::numeric_limits<uint64_t>::max()) {
97     return nullptr;
98   }
99 
100   auto it = std::lower_bound(mappings_.begin(), mappings_.end(),
101                              LookupKey{address, ts}, Lookup());
102 
103   if (it == mappings_.end() || address < it->start()) {
104     return nullptr;
105   }
106   return &*it;
107 }
108 
109 }  // namespace perfetto::trace_processor::etm
110