1 /*
2 * Copyright (C) 2020 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 #include "src/trace_processor/importers/proto/perf_sample_tracker.h"
17
18 #include <vector>
19
20 #include <inttypes.h>
21
22 #include "perfetto/ext/base/optional.h"
23 #include "src/trace_processor/importers/common/process_tracker.h"
24 #include "src/trace_processor/importers/common/slice_tracker.h"
25 #include "src/trace_processor/importers/common/track_tracker.h"
26 #include "src/trace_processor/storage/trace_storage.h"
27 #include "src/trace_processor/types/trace_processor_context.h"
28
29 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
30 #include <cxxabi.h>
31 #endif
32
33 namespace perfetto {
34 namespace trace_processor {
35 namespace {
36 // TODO(rsavitski): consider using the sampling rate from the trace config.
37 constexpr int64_t kFixedStackSliceDurationNs = 1 * 1000 * 1000;
38 } // namespace
39
AddStackToSliceTrack(int64_t timestamp,CallsiteId leaf_id,uint32_t pid,uint32_t tid,uint32_t cpu)40 void PerfSampleTracker::AddStackToSliceTrack(int64_t timestamp,
41 CallsiteId leaf_id,
42 uint32_t pid,
43 uint32_t tid,
44 uint32_t cpu) {
45 UniquePid upid =
46 context_->process_tracker->GetOrCreateProcess(static_cast<uint32_t>(pid));
47
48 TrackId track_id = context_->track_tracker->InternPerfStackTrack(upid);
49 const auto& callsites = context_->storage->stack_profile_callsite_table();
50 const auto& frames = context_->storage->stack_profile_frame_table();
51 const auto& mappings = context_->storage->stack_profile_mapping_table();
52
53 // Synthetic frame for more context, as the track is process-wide.
54 char buf[128] = {};
55 snprintf(buf, sizeof(buf), "cpu: [%" PRIu32 "]; thread: [%" PRIi32 "]", cpu,
56 tid);
57 StringId synth = context_->storage->InternString(buf);
58 context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId, synth,
59 kFixedStackSliceDurationNs);
60
61 // The callstack id references the leaf frame, while we want the slice stack
62 // to have the root frame at the top in the UI, so walk the chain in reverse.
63 std::vector<uint32_t> callsite_rows;
64 callsite_rows.reserve(64);
65 base::Optional<CallsiteId> cs_id = leaf_id;
66 while (cs_id) {
67 uint32_t row = *callsites.id().IndexOf(*cs_id);
68 callsite_rows.push_back(row);
69 cs_id = callsites.parent_id()[row];
70 }
71
72 for (auto rit = callsite_rows.rbegin(); rit != callsite_rows.rend(); ++rit) {
73 uint32_t callsite_row = *rit;
74 FrameId frame_id = callsites.frame_id()[callsite_row];
75 uint32_t frame_row = *frames.id().IndexOf(frame_id);
76
77 MappingId mapping_id = frames.mapping()[frame_row];
78 uint32_t mapping_row = *mappings.id().IndexOf(mapping_id);
79
80 StringId mangled_fname = frames.name()[frame_row];
81 StringId mname = mappings.name()[mapping_row];
82
83 StringId fname = MaybeDemangle(mangled_fname);
84 context_->slice_tracker->Scoped(timestamp, track_id, mname, fname,
85 kFixedStackSliceDurationNs);
86 }
87 }
88
89 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
MaybeDemangle(StringId fname)90 StringId PerfSampleTracker::MaybeDemangle(StringId fname) {
91 StringId ret = fname;
92 const char* raw_fname = context_->storage->GetString(fname).c_str();
93 int ignored;
94 char* data = abi::__cxa_demangle(raw_fname, nullptr, nullptr, &ignored);
95 if (data) {
96 ret = context_->storage->InternString(data);
97 free(data);
98 }
99 return ret;
100 }
101 #else
MaybeDemangle(StringId fname)102 StringId PerfSampleTracker::MaybeDemangle(StringId fname) {
103 return fname;
104 }
105 #endif
106
107 } // namespace trace_processor
108 } // namespace perfetto
109