1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/symbolizer/symbolize_database.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <map>
20*6dbdd20aSAndroid Build Coastguard Worker #include <utility>
21*6dbdd20aSAndroid Build Coastguard Worker #include <vector>
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/scattered_heap_buffer.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/trace_processor/trace_processor.h"
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/trace.pbzero.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/trace_packet.pbzero.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "src/trace_processor/util/build_id.h"
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
34*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
35*6dbdd20aSAndroid Build Coastguard Worker
36*6dbdd20aSAndroid Build Coastguard Worker namespace {
37*6dbdd20aSAndroid Build Coastguard Worker using trace_processor::Iterator;
38*6dbdd20aSAndroid Build Coastguard Worker
39*6dbdd20aSAndroid Build Coastguard Worker constexpr const char* kQueryUnsymbolized =
40*6dbdd20aSAndroid Build Coastguard Worker "select spm.name, spm.build_id, spf.rel_pc, spm.load_bias "
41*6dbdd20aSAndroid Build Coastguard Worker "from stack_profile_frame spf "
42*6dbdd20aSAndroid Build Coastguard Worker "join stack_profile_mapping spm "
43*6dbdd20aSAndroid Build Coastguard Worker "on spf.mapping = spm.id "
44*6dbdd20aSAndroid Build Coastguard Worker "where spm.build_id != '' and spf.symbol_set_id IS NULL";
45*6dbdd20aSAndroid Build Coastguard Worker
46*6dbdd20aSAndroid Build Coastguard Worker using NameAndBuildIdPair = std::pair<std::string, std::string>;
47*6dbdd20aSAndroid Build Coastguard Worker
48*6dbdd20aSAndroid Build Coastguard Worker struct UnsymbolizedMapping {
49*6dbdd20aSAndroid Build Coastguard Worker std::string name;
50*6dbdd20aSAndroid Build Coastguard Worker std::string build_id;
51*6dbdd20aSAndroid Build Coastguard Worker uint64_t load_bias;
operator <perfetto::profiling::__anond5867af40111::UnsymbolizedMapping52*6dbdd20aSAndroid Build Coastguard Worker bool operator<(const UnsymbolizedMapping& o) const {
53*6dbdd20aSAndroid Build Coastguard Worker return std::tie(name, build_id, load_bias) <
54*6dbdd20aSAndroid Build Coastguard Worker std::tie(o.name, o.build_id, o.load_bias);
55*6dbdd20aSAndroid Build Coastguard Worker }
56*6dbdd20aSAndroid Build Coastguard Worker };
57*6dbdd20aSAndroid Build Coastguard Worker
GetUnsymbolizedFrames(trace_processor::TraceProcessor * tp)58*6dbdd20aSAndroid Build Coastguard Worker std::map<UnsymbolizedMapping, std::vector<uint64_t>> GetUnsymbolizedFrames(
59*6dbdd20aSAndroid Build Coastguard Worker trace_processor::TraceProcessor* tp) {
60*6dbdd20aSAndroid Build Coastguard Worker std::map<UnsymbolizedMapping, std::vector<uint64_t>> res;
61*6dbdd20aSAndroid Build Coastguard Worker Iterator it = tp->ExecuteQuery(kQueryUnsymbolized);
62*6dbdd20aSAndroid Build Coastguard Worker while (it.Next()) {
63*6dbdd20aSAndroid Build Coastguard Worker int64_t load_bias = it.Get(3).AsLong();
64*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(load_bias >= 0);
65*6dbdd20aSAndroid Build Coastguard Worker trace_processor::BuildId build_id =
66*6dbdd20aSAndroid Build Coastguard Worker trace_processor::BuildId::FromHex(it.Get(1).AsString());
67*6dbdd20aSAndroid Build Coastguard Worker UnsymbolizedMapping unsymbolized_mapping{
68*6dbdd20aSAndroid Build Coastguard Worker it.Get(0).AsString(), build_id.raw(), static_cast<uint64_t>(load_bias)};
69*6dbdd20aSAndroid Build Coastguard Worker int64_t rel_pc = it.Get(2).AsLong();
70*6dbdd20aSAndroid Build Coastguard Worker res[unsymbolized_mapping].emplace_back(rel_pc);
71*6dbdd20aSAndroid Build Coastguard Worker }
72*6dbdd20aSAndroid Build Coastguard Worker if (!it.Status().ok()) {
73*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
74*6dbdd20aSAndroid Build Coastguard Worker it.Status().message().c_str());
75*6dbdd20aSAndroid Build Coastguard Worker return {};
76*6dbdd20aSAndroid Build Coastguard Worker }
77*6dbdd20aSAndroid Build Coastguard Worker return res;
78*6dbdd20aSAndroid Build Coastguard Worker }
79*6dbdd20aSAndroid Build Coastguard Worker } // namespace
80*6dbdd20aSAndroid Build Coastguard Worker
SymbolizeDatabase(trace_processor::TraceProcessor * tp,Symbolizer * symbolizer,std::function<void (const std::string &)> callback)81*6dbdd20aSAndroid Build Coastguard Worker void SymbolizeDatabase(trace_processor::TraceProcessor* tp,
82*6dbdd20aSAndroid Build Coastguard Worker Symbolizer* symbolizer,
83*6dbdd20aSAndroid Build Coastguard Worker std::function<void(const std::string&)> callback) {
84*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_CHECK(symbolizer);
85*6dbdd20aSAndroid Build Coastguard Worker auto unsymbolized = GetUnsymbolizedFrames(tp);
86*6dbdd20aSAndroid Build Coastguard Worker for (auto it = unsymbolized.cbegin(); it != unsymbolized.cend(); ++it) {
87*6dbdd20aSAndroid Build Coastguard Worker const auto& unsymbolized_mapping = it->first;
88*6dbdd20aSAndroid Build Coastguard Worker const std::vector<uint64_t>& rel_pcs = it->second;
89*6dbdd20aSAndroid Build Coastguard Worker auto res = symbolizer->Symbolize(unsymbolized_mapping.name,
90*6dbdd20aSAndroid Build Coastguard Worker unsymbolized_mapping.build_id,
91*6dbdd20aSAndroid Build Coastguard Worker unsymbolized_mapping.load_bias, rel_pcs);
92*6dbdd20aSAndroid Build Coastguard Worker if (res.empty())
93*6dbdd20aSAndroid Build Coastguard Worker continue;
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Worker protozero::HeapBuffered<perfetto::protos::pbzero::Trace> trace;
96*6dbdd20aSAndroid Build Coastguard Worker auto* packet = trace->add_packet();
97*6dbdd20aSAndroid Build Coastguard Worker auto* module_symbols = packet->set_module_symbols();
98*6dbdd20aSAndroid Build Coastguard Worker module_symbols->set_path(unsymbolized_mapping.name);
99*6dbdd20aSAndroid Build Coastguard Worker module_symbols->set_build_id(unsymbolized_mapping.build_id);
100*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(res.size() == rel_pcs.size());
101*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < res.size(); ++i) {
102*6dbdd20aSAndroid Build Coastguard Worker auto* address_symbols = module_symbols->add_address_symbols();
103*6dbdd20aSAndroid Build Coastguard Worker address_symbols->set_address(rel_pcs[i]);
104*6dbdd20aSAndroid Build Coastguard Worker for (const SymbolizedFrame& frame : res[i]) {
105*6dbdd20aSAndroid Build Coastguard Worker auto* line = address_symbols->add_lines();
106*6dbdd20aSAndroid Build Coastguard Worker line->set_function_name(frame.function_name);
107*6dbdd20aSAndroid Build Coastguard Worker line->set_source_file_name(frame.file_name);
108*6dbdd20aSAndroid Build Coastguard Worker line->set_line_number(frame.line);
109*6dbdd20aSAndroid Build Coastguard Worker }
110*6dbdd20aSAndroid Build Coastguard Worker }
111*6dbdd20aSAndroid Build Coastguard Worker callback(trace.SerializeAsString());
112*6dbdd20aSAndroid Build Coastguard Worker }
113*6dbdd20aSAndroid Build Coastguard Worker }
114*6dbdd20aSAndroid Build Coastguard Worker
GetPerfettoBinaryPath()115*6dbdd20aSAndroid Build Coastguard Worker std::vector<std::string> GetPerfettoBinaryPath() {
116*6dbdd20aSAndroid Build Coastguard Worker const char* root = getenv("PERFETTO_BINARY_PATH");
117*6dbdd20aSAndroid Build Coastguard Worker if (root != nullptr) {
118*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
119*6dbdd20aSAndroid Build Coastguard Worker const char* delimiter = ";";
120*6dbdd20aSAndroid Build Coastguard Worker #else
121*6dbdd20aSAndroid Build Coastguard Worker const char* delimiter = ":";
122*6dbdd20aSAndroid Build Coastguard Worker #endif
123*6dbdd20aSAndroid Build Coastguard Worker return base::SplitString(root, delimiter);
124*6dbdd20aSAndroid Build Coastguard Worker }
125*6dbdd20aSAndroid Build Coastguard Worker return {};
126*6dbdd20aSAndroid Build Coastguard Worker }
127*6dbdd20aSAndroid Build Coastguard Worker
128*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling
129*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
130