1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include "dso.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
20*288bf522SAndroid Build Coastguard Worker #include <string.h>
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker #include <algorithm>
23*288bf522SAndroid Build Coastguard Worker #include <limits>
24*288bf522SAndroid Build Coastguard Worker #include <memory>
25*288bf522SAndroid Build Coastguard Worker #include <optional>
26*288bf522SAndroid Build Coastguard Worker #include <string_view>
27*288bf522SAndroid Build Coastguard Worker #include <vector>
28*288bf522SAndroid Build Coastguard Worker
29*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
30*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
31*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker #include "JITDebugReader.h"
34*288bf522SAndroid Build Coastguard Worker #include "environment.h"
35*288bf522SAndroid Build Coastguard Worker #include "kallsyms.h"
36*288bf522SAndroid Build Coastguard Worker #include "read_apk.h"
37*288bf522SAndroid Build Coastguard Worker #include "read_dex_file.h"
38*288bf522SAndroid Build Coastguard Worker #include "read_elf.h"
39*288bf522SAndroid Build Coastguard Worker #include "utils.h"
40*288bf522SAndroid Build Coastguard Worker
41*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
42*288bf522SAndroid Build Coastguard Worker
43*288bf522SAndroid Build Coastguard Worker using android::base::EndsWith;
44*288bf522SAndroid Build Coastguard Worker using android::base::StartsWith;
45*288bf522SAndroid Build Coastguard Worker
46*288bf522SAndroid Build Coastguard Worker namespace simpleperf_dso_impl {
47*288bf522SAndroid Build Coastguard Worker
RemovePathSeparatorSuffix(const std::string & path)48*288bf522SAndroid Build Coastguard Worker std::string RemovePathSeparatorSuffix(const std::string& path) {
49*288bf522SAndroid Build Coastguard Worker // Don't remove path separator suffix for '/'.
50*288bf522SAndroid Build Coastguard Worker if (EndsWith(path, OS_PATH_SEPARATOR) && path.size() > 1u) {
51*288bf522SAndroid Build Coastguard Worker return path.substr(0, path.size() - 1);
52*288bf522SAndroid Build Coastguard Worker }
53*288bf522SAndroid Build Coastguard Worker return path;
54*288bf522SAndroid Build Coastguard Worker }
55*288bf522SAndroid Build Coastguard Worker
Reset()56*288bf522SAndroid Build Coastguard Worker void DebugElfFileFinder::Reset() {
57*288bf522SAndroid Build Coastguard Worker allow_mismatched_build_id_ = false;
58*288bf522SAndroid Build Coastguard Worker vdso_64bit_.clear();
59*288bf522SAndroid Build Coastguard Worker vdso_32bit_.clear();
60*288bf522SAndroid Build Coastguard Worker symfs_dir_.clear();
61*288bf522SAndroid Build Coastguard Worker build_id_to_file_map_.clear();
62*288bf522SAndroid Build Coastguard Worker }
63*288bf522SAndroid Build Coastguard Worker
SetSymFsDir(const std::string & symfs_dir)64*288bf522SAndroid Build Coastguard Worker bool DebugElfFileFinder::SetSymFsDir(const std::string& symfs_dir) {
65*288bf522SAndroid Build Coastguard Worker symfs_dir_ = RemovePathSeparatorSuffix(symfs_dir);
66*288bf522SAndroid Build Coastguard Worker if (!IsDir(symfs_dir_)) {
67*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid symfs_dir '" << symfs_dir_ << "'";
68*288bf522SAndroid Build Coastguard Worker return false;
69*288bf522SAndroid Build Coastguard Worker }
70*288bf522SAndroid Build Coastguard Worker std::string build_id_list_file = symfs_dir_ + OS_PATH_SEPARATOR + "build_id_list";
71*288bf522SAndroid Build Coastguard Worker std::string build_id_list;
72*288bf522SAndroid Build Coastguard Worker if (android::base::ReadFileToString(build_id_list_file, &build_id_list)) {
73*288bf522SAndroid Build Coastguard Worker for (auto& line : android::base::Split(build_id_list, "\n")) {
74*288bf522SAndroid Build Coastguard Worker std::vector<std::string> items = android::base::Split(line, "=");
75*288bf522SAndroid Build Coastguard Worker if (items.size() == 2u) {
76*288bf522SAndroid Build Coastguard Worker build_id_to_file_map_[items[0]] = symfs_dir_ + OS_PATH_SEPARATOR + items[1];
77*288bf522SAndroid Build Coastguard Worker }
78*288bf522SAndroid Build Coastguard Worker }
79*288bf522SAndroid Build Coastguard Worker }
80*288bf522SAndroid Build Coastguard Worker return true;
81*288bf522SAndroid Build Coastguard Worker }
82*288bf522SAndroid Build Coastguard Worker
AddSymbolDir(const std::string & symbol_dir)83*288bf522SAndroid Build Coastguard Worker bool DebugElfFileFinder::AddSymbolDir(const std::string& symbol_dir) {
84*288bf522SAndroid Build Coastguard Worker if (!IsDir(symbol_dir)) {
85*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid symbol dir " << symbol_dir;
86*288bf522SAndroid Build Coastguard Worker return false;
87*288bf522SAndroid Build Coastguard Worker }
88*288bf522SAndroid Build Coastguard Worker std::string dir = RemovePathSeparatorSuffix(symbol_dir);
89*288bf522SAndroid Build Coastguard Worker CollectBuildIdInDir(dir);
90*288bf522SAndroid Build Coastguard Worker return true;
91*288bf522SAndroid Build Coastguard Worker }
92*288bf522SAndroid Build Coastguard Worker
CollectBuildIdInDir(const std::string & dir)93*288bf522SAndroid Build Coastguard Worker void DebugElfFileFinder::CollectBuildIdInDir(const std::string& dir) {
94*288bf522SAndroid Build Coastguard Worker for (const std::string& entry : GetEntriesInDir(dir)) {
95*288bf522SAndroid Build Coastguard Worker std::string path = dir + OS_PATH_SEPARATOR + entry;
96*288bf522SAndroid Build Coastguard Worker if (IsDir(path)) {
97*288bf522SAndroid Build Coastguard Worker CollectBuildIdInDir(path);
98*288bf522SAndroid Build Coastguard Worker } else {
99*288bf522SAndroid Build Coastguard Worker BuildId build_id;
100*288bf522SAndroid Build Coastguard Worker ElfStatus status;
101*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(path, &status);
102*288bf522SAndroid Build Coastguard Worker if (status == ElfStatus::NO_ERROR) {
103*288bf522SAndroid Build Coastguard Worker if (elf->GetBuildId(&build_id) == ElfStatus::NO_ERROR) {
104*288bf522SAndroid Build Coastguard Worker build_id_to_file_map_[build_id.ToString()] = path;
105*288bf522SAndroid Build Coastguard Worker } else {
106*288bf522SAndroid Build Coastguard Worker no_build_id_files_.emplace_back(std::move(path));
107*288bf522SAndroid Build Coastguard Worker }
108*288bf522SAndroid Build Coastguard Worker }
109*288bf522SAndroid Build Coastguard Worker }
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker }
112*288bf522SAndroid Build Coastguard Worker
SetVdsoFile(const std::string & vdso_file,bool is_64bit)113*288bf522SAndroid Build Coastguard Worker void DebugElfFileFinder::SetVdsoFile(const std::string& vdso_file, bool is_64bit) {
114*288bf522SAndroid Build Coastguard Worker if (is_64bit) {
115*288bf522SAndroid Build Coastguard Worker vdso_64bit_ = vdso_file;
116*288bf522SAndroid Build Coastguard Worker } else {
117*288bf522SAndroid Build Coastguard Worker vdso_32bit_ = vdso_file;
118*288bf522SAndroid Build Coastguard Worker }
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker
CheckDebugFilePath(const std::string & path,BuildId & build_id,bool report_build_id_mismatch)121*288bf522SAndroid Build Coastguard Worker bool DebugElfFileFinder::CheckDebugFilePath(const std::string& path, BuildId& build_id,
122*288bf522SAndroid Build Coastguard Worker bool report_build_id_mismatch) {
123*288bf522SAndroid Build Coastguard Worker ElfStatus status;
124*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(path, &status);
125*288bf522SAndroid Build Coastguard Worker if (!elf) {
126*288bf522SAndroid Build Coastguard Worker return false;
127*288bf522SAndroid Build Coastguard Worker }
128*288bf522SAndroid Build Coastguard Worker BuildId debug_build_id;
129*288bf522SAndroid Build Coastguard Worker status = elf->GetBuildId(&debug_build_id);
130*288bf522SAndroid Build Coastguard Worker if (status != ElfStatus::NO_ERROR && status != ElfStatus::NO_BUILD_ID) {
131*288bf522SAndroid Build Coastguard Worker return false;
132*288bf522SAndroid Build Coastguard Worker }
133*288bf522SAndroid Build Coastguard Worker
134*288bf522SAndroid Build Coastguard Worker if (allow_mismatched_build_id_) {
135*288bf522SAndroid Build Coastguard Worker return true;
136*288bf522SAndroid Build Coastguard Worker }
137*288bf522SAndroid Build Coastguard Worker
138*288bf522SAndroid Build Coastguard Worker // Native libraries in apks and kernel modules may not have build ids.
139*288bf522SAndroid Build Coastguard Worker // So build_id and debug_build_id can either be empty, or have the same value.
140*288bf522SAndroid Build Coastguard Worker bool match = build_id == debug_build_id;
141*288bf522SAndroid Build Coastguard Worker if (!match && report_build_id_mismatch) {
142*288bf522SAndroid Build Coastguard Worker LOG(WARNING) << path << " isn't used because of build id mismatch: expected " << build_id
143*288bf522SAndroid Build Coastguard Worker << ", real " << debug_build_id;
144*288bf522SAndroid Build Coastguard Worker }
145*288bf522SAndroid Build Coastguard Worker return match;
146*288bf522SAndroid Build Coastguard Worker }
147*288bf522SAndroid Build Coastguard Worker
FindDebugFile(const std::string & dso_path,bool force_64bit,BuildId & build_id)148*288bf522SAndroid Build Coastguard Worker std::string DebugElfFileFinder::FindDebugFile(const std::string& dso_path, bool force_64bit,
149*288bf522SAndroid Build Coastguard Worker BuildId& build_id) {
150*288bf522SAndroid Build Coastguard Worker if (dso_path == "[vdso]") {
151*288bf522SAndroid Build Coastguard Worker if (force_64bit && !vdso_64bit_.empty()) {
152*288bf522SAndroid Build Coastguard Worker return vdso_64bit_;
153*288bf522SAndroid Build Coastguard Worker } else if (!force_64bit && !vdso_32bit_.empty()) {
154*288bf522SAndroid Build Coastguard Worker return vdso_32bit_;
155*288bf522SAndroid Build Coastguard Worker }
156*288bf522SAndroid Build Coastguard Worker }
157*288bf522SAndroid Build Coastguard Worker if (build_id.IsEmpty()) {
158*288bf522SAndroid Build Coastguard Worker // Try reading build id from file if we don't already have one.
159*288bf522SAndroid Build Coastguard Worker GetBuildIdFromDsoPath(dso_path, &build_id);
160*288bf522SAndroid Build Coastguard Worker }
161*288bf522SAndroid Build Coastguard Worker
162*288bf522SAndroid Build Coastguard Worker // 1. Try build_id_to_file_map.
163*288bf522SAndroid Build Coastguard Worker if (!build_id_to_file_map_.empty()) {
164*288bf522SAndroid Build Coastguard Worker if (!build_id.IsEmpty()) {
165*288bf522SAndroid Build Coastguard Worker auto it = build_id_to_file_map_.find(build_id.ToString());
166*288bf522SAndroid Build Coastguard Worker if (it != build_id_to_file_map_.end() && CheckDebugFilePath(it->second, build_id, false)) {
167*288bf522SAndroid Build Coastguard Worker return it->second;
168*288bf522SAndroid Build Coastguard Worker }
169*288bf522SAndroid Build Coastguard Worker }
170*288bf522SAndroid Build Coastguard Worker }
171*288bf522SAndroid Build Coastguard Worker if (allow_mismatched_build_id_) {
172*288bf522SAndroid Build Coastguard Worker std::optional<std::string> s = SearchFileMapByPath(dso_path);
173*288bf522SAndroid Build Coastguard Worker if (s.has_value()) {
174*288bf522SAndroid Build Coastguard Worker return s.value();
175*288bf522SAndroid Build Coastguard Worker }
176*288bf522SAndroid Build Coastguard Worker }
177*288bf522SAndroid Build Coastguard Worker if (!symfs_dir_.empty()) {
178*288bf522SAndroid Build Coastguard Worker // 2. Try concatenating symfs_dir and dso_path.
179*288bf522SAndroid Build Coastguard Worker std::string path = GetPathInSymFsDir(dso_path);
180*288bf522SAndroid Build Coastguard Worker if (CheckDebugFilePath(path, build_id, true)) {
181*288bf522SAndroid Build Coastguard Worker return path;
182*288bf522SAndroid Build Coastguard Worker }
183*288bf522SAndroid Build Coastguard Worker if (EndsWith(dso_path, ".apk") && IsRegularFile(path)) {
184*288bf522SAndroid Build Coastguard Worker return path;
185*288bf522SAndroid Build Coastguard Worker }
186*288bf522SAndroid Build Coastguard Worker // 3. Try concatenating symfs_dir and basename of dso_path.
187*288bf522SAndroid Build Coastguard Worker path = symfs_dir_ + OS_PATH_SEPARATOR + android::base::Basename(dso_path);
188*288bf522SAndroid Build Coastguard Worker if (CheckDebugFilePath(path, build_id, false)) {
189*288bf522SAndroid Build Coastguard Worker return path;
190*288bf522SAndroid Build Coastguard Worker }
191*288bf522SAndroid Build Coastguard Worker }
192*288bf522SAndroid Build Coastguard Worker // 4. Try concatenating /usr/lib/debug and dso_path.
193*288bf522SAndroid Build Coastguard Worker // Linux host can store debug shared libraries in /usr/lib/debug.
194*288bf522SAndroid Build Coastguard Worker if (CheckDebugFilePath("/usr/lib/debug" + dso_path, build_id, false)) {
195*288bf522SAndroid Build Coastguard Worker return "/usr/lib/debug" + dso_path;
196*288bf522SAndroid Build Coastguard Worker }
197*288bf522SAndroid Build Coastguard Worker return dso_path;
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker
GetPathInSymFsDir(const std::string & path)200*288bf522SAndroid Build Coastguard Worker std::string DebugElfFileFinder::GetPathInSymFsDir(const std::string& path) {
201*288bf522SAndroid Build Coastguard Worker auto add_symfs_prefix = [&](const std::string& path) {
202*288bf522SAndroid Build Coastguard Worker if (StartsWith(path, OS_PATH_SEPARATOR)) {
203*288bf522SAndroid Build Coastguard Worker return symfs_dir_ + path;
204*288bf522SAndroid Build Coastguard Worker }
205*288bf522SAndroid Build Coastguard Worker return symfs_dir_ + OS_PATH_SEPARATOR + path;
206*288bf522SAndroid Build Coastguard Worker };
207*288bf522SAndroid Build Coastguard Worker if (OS_PATH_SEPARATOR == '/') {
208*288bf522SAndroid Build Coastguard Worker return add_symfs_prefix(path);
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker // Paths in recorded perf.data uses '/' as path separator. When reporting on Windows, it needs
211*288bf522SAndroid Build Coastguard Worker // to be converted to '\\'.
212*288bf522SAndroid Build Coastguard Worker auto tuple = SplitUrlInApk(path);
213*288bf522SAndroid Build Coastguard Worker if (std::get<0>(tuple)) {
214*288bf522SAndroid Build Coastguard Worker std::string apk_path = std::get<1>(tuple);
215*288bf522SAndroid Build Coastguard Worker std::string entry_path = std::get<2>(tuple);
216*288bf522SAndroid Build Coastguard Worker std::replace(apk_path.begin(), apk_path.end(), '/', OS_PATH_SEPARATOR);
217*288bf522SAndroid Build Coastguard Worker return GetUrlInApk(add_symfs_prefix(apk_path), entry_path);
218*288bf522SAndroid Build Coastguard Worker }
219*288bf522SAndroid Build Coastguard Worker std::string elf_path = path;
220*288bf522SAndroid Build Coastguard Worker std::replace(elf_path.begin(), elf_path.end(), '/', OS_PATH_SEPARATOR);
221*288bf522SAndroid Build Coastguard Worker return add_symfs_prefix(elf_path);
222*288bf522SAndroid Build Coastguard Worker }
223*288bf522SAndroid Build Coastguard Worker
SearchFileMapByPath(std::string_view path)224*288bf522SAndroid Build Coastguard Worker std::optional<std::string> DebugElfFileFinder::SearchFileMapByPath(std::string_view path) {
225*288bf522SAndroid Build Coastguard Worker if (path == "[kernel.kallsyms]") {
226*288bf522SAndroid Build Coastguard Worker path = "vmlinux";
227*288bf522SAndroid Build Coastguard Worker }
228*288bf522SAndroid Build Coastguard Worker std::string_view filename;
229*288bf522SAndroid Build Coastguard Worker if (size_t pos = path.rfind('/'); pos != path.npos) {
230*288bf522SAndroid Build Coastguard Worker filename = path.substr(pos + 1);
231*288bf522SAndroid Build Coastguard Worker } else {
232*288bf522SAndroid Build Coastguard Worker filename = path;
233*288bf522SAndroid Build Coastguard Worker }
234*288bf522SAndroid Build Coastguard Worker std::string best_elf_file;
235*288bf522SAndroid Build Coastguard Worker size_t best_match_length = 0;
236*288bf522SAndroid Build Coastguard Worker auto check_file = [&](const std::string& elf_file) {
237*288bf522SAndroid Build Coastguard Worker if (EndsWith(elf_file, filename)) {
238*288bf522SAndroid Build Coastguard Worker size_t i = elf_file.size();
239*288bf522SAndroid Build Coastguard Worker size_t j = path.size();
240*288bf522SAndroid Build Coastguard Worker while (i > 0 && j > 0 && elf_file[i - 1] == path[j - 1]) {
241*288bf522SAndroid Build Coastguard Worker i--;
242*288bf522SAndroid Build Coastguard Worker j--;
243*288bf522SAndroid Build Coastguard Worker }
244*288bf522SAndroid Build Coastguard Worker size_t match_length = elf_file.size() - i;
245*288bf522SAndroid Build Coastguard Worker if (match_length > best_match_length) {
246*288bf522SAndroid Build Coastguard Worker best_elf_file = elf_file;
247*288bf522SAndroid Build Coastguard Worker best_match_length = match_length;
248*288bf522SAndroid Build Coastguard Worker }
249*288bf522SAndroid Build Coastguard Worker }
250*288bf522SAndroid Build Coastguard Worker };
251*288bf522SAndroid Build Coastguard Worker
252*288bf522SAndroid Build Coastguard Worker for (const auto& p : build_id_to_file_map_) {
253*288bf522SAndroid Build Coastguard Worker check_file(p.second);
254*288bf522SAndroid Build Coastguard Worker }
255*288bf522SAndroid Build Coastguard Worker for (const auto& elf_file : no_build_id_files_) {
256*288bf522SAndroid Build Coastguard Worker check_file(elf_file);
257*288bf522SAndroid Build Coastguard Worker }
258*288bf522SAndroid Build Coastguard Worker if (!best_elf_file.empty()) {
259*288bf522SAndroid Build Coastguard Worker LOG(INFO) << "Found " << best_elf_file << " for " << path << " by filename";
260*288bf522SAndroid Build Coastguard Worker return best_elf_file;
261*288bf522SAndroid Build Coastguard Worker }
262*288bf522SAndroid Build Coastguard Worker return std::nullopt;
263*288bf522SAndroid Build Coastguard Worker }
264*288bf522SAndroid Build Coastguard Worker
265*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf_dso_impl
266*288bf522SAndroid Build Coastguard Worker
267*288bf522SAndroid Build Coastguard Worker static OneTimeFreeAllocator symbol_name_allocator;
268*288bf522SAndroid Build Coastguard Worker
Symbol(std::string_view name,uint64_t addr,uint64_t len)269*288bf522SAndroid Build Coastguard Worker Symbol::Symbol(std::string_view name, uint64_t addr, uint64_t len)
270*288bf522SAndroid Build Coastguard Worker : addr(addr),
271*288bf522SAndroid Build Coastguard Worker len(len),
272*288bf522SAndroid Build Coastguard Worker name_(symbol_name_allocator.AllocateString(name)),
273*288bf522SAndroid Build Coastguard Worker demangled_name_(nullptr),
274*288bf522SAndroid Build Coastguard Worker dump_id_(UINT_MAX) {}
275*288bf522SAndroid Build Coastguard Worker
DemangledName() const276*288bf522SAndroid Build Coastguard Worker const char* Symbol::DemangledName() const {
277*288bf522SAndroid Build Coastguard Worker if (demangled_name_ == nullptr) {
278*288bf522SAndroid Build Coastguard Worker const std::string s = Dso::Demangle(name_);
279*288bf522SAndroid Build Coastguard Worker SetDemangledName(s);
280*288bf522SAndroid Build Coastguard Worker }
281*288bf522SAndroid Build Coastguard Worker return demangled_name_;
282*288bf522SAndroid Build Coastguard Worker }
283*288bf522SAndroid Build Coastguard Worker
SetDemangledName(std::string_view name) const284*288bf522SAndroid Build Coastguard Worker void Symbol::SetDemangledName(std::string_view name) const {
285*288bf522SAndroid Build Coastguard Worker if (name == name_) {
286*288bf522SAndroid Build Coastguard Worker demangled_name_ = name_;
287*288bf522SAndroid Build Coastguard Worker } else {
288*288bf522SAndroid Build Coastguard Worker demangled_name_ = symbol_name_allocator.AllocateString(name);
289*288bf522SAndroid Build Coastguard Worker }
290*288bf522SAndroid Build Coastguard Worker }
291*288bf522SAndroid Build Coastguard Worker
FunctionName() const292*288bf522SAndroid Build Coastguard Worker std::string_view Symbol::FunctionName() const {
293*288bf522SAndroid Build Coastguard Worker // Name with signature is like "void ctep.v(cteo, ctgc, ctbn)".
294*288bf522SAndroid Build Coastguard Worker std::string_view name = DemangledName();
295*288bf522SAndroid Build Coastguard Worker auto brace_pos = name.find('(');
296*288bf522SAndroid Build Coastguard Worker if (brace_pos != name.npos) {
297*288bf522SAndroid Build Coastguard Worker name = name.substr(0, brace_pos);
298*288bf522SAndroid Build Coastguard Worker auto space_pos = name.rfind(' ');
299*288bf522SAndroid Build Coastguard Worker if (space_pos != name.npos) {
300*288bf522SAndroid Build Coastguard Worker name = name.substr(space_pos + 1);
301*288bf522SAndroid Build Coastguard Worker }
302*288bf522SAndroid Build Coastguard Worker }
303*288bf522SAndroid Build Coastguard Worker return name;
304*288bf522SAndroid Build Coastguard Worker }
305*288bf522SAndroid Build Coastguard Worker
CompareSymbolToAddr(const Symbol & s,uint64_t addr)306*288bf522SAndroid Build Coastguard Worker static bool CompareSymbolToAddr(const Symbol& s, uint64_t addr) {
307*288bf522SAndroid Build Coastguard Worker return s.addr < addr;
308*288bf522SAndroid Build Coastguard Worker }
309*288bf522SAndroid Build Coastguard Worker
CompareAddrToSymbol(uint64_t addr,const Symbol & s)310*288bf522SAndroid Build Coastguard Worker static bool CompareAddrToSymbol(uint64_t addr, const Symbol& s) {
311*288bf522SAndroid Build Coastguard Worker return addr < s.addr;
312*288bf522SAndroid Build Coastguard Worker }
313*288bf522SAndroid Build Coastguard Worker
314*288bf522SAndroid Build Coastguard Worker bool Dso::demangle_ = true;
315*288bf522SAndroid Build Coastguard Worker std::string Dso::vmlinux_;
316*288bf522SAndroid Build Coastguard Worker std::string Dso::kallsyms_;
317*288bf522SAndroid Build Coastguard Worker std::unordered_map<std::string, BuildId> Dso::build_id_map_;
318*288bf522SAndroid Build Coastguard Worker size_t Dso::dso_count_;
319*288bf522SAndroid Build Coastguard Worker uint32_t Dso::g_dump_id_;
320*288bf522SAndroid Build Coastguard Worker simpleperf_dso_impl::DebugElfFileFinder Dso::debug_elf_file_finder_;
321*288bf522SAndroid Build Coastguard Worker
SetDemangle(bool demangle)322*288bf522SAndroid Build Coastguard Worker void Dso::SetDemangle(bool demangle) {
323*288bf522SAndroid Build Coastguard Worker demangle_ = demangle;
324*288bf522SAndroid Build Coastguard Worker }
325*288bf522SAndroid Build Coastguard Worker
326*288bf522SAndroid Build Coastguard Worker extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status);
327*288bf522SAndroid Build Coastguard Worker #if defined(__linux__) || defined(__darwin__)
328*288bf522SAndroid Build Coastguard Worker extern "C" char* rustc_demangle(const char* mangled, char* out, size_t* len, int* status);
329*288bf522SAndroid Build Coastguard Worker #endif
330*288bf522SAndroid Build Coastguard Worker
Demangle(const std::string & name)331*288bf522SAndroid Build Coastguard Worker std::string Dso::Demangle(const std::string& name) {
332*288bf522SAndroid Build Coastguard Worker if (!demangle_) {
333*288bf522SAndroid Build Coastguard Worker return name;
334*288bf522SAndroid Build Coastguard Worker }
335*288bf522SAndroid Build Coastguard Worker int status;
336*288bf522SAndroid Build Coastguard Worker bool is_linker_symbol = (name.find(linker_prefix) == 0);
337*288bf522SAndroid Build Coastguard Worker const char* mangled_str = name.c_str();
338*288bf522SAndroid Build Coastguard Worker if (is_linker_symbol) {
339*288bf522SAndroid Build Coastguard Worker mangled_str += linker_prefix.size();
340*288bf522SAndroid Build Coastguard Worker }
341*288bf522SAndroid Build Coastguard Worker
342*288bf522SAndroid Build Coastguard Worker if (mangled_str[0] == '_') {
343*288bf522SAndroid Build Coastguard Worker char* demangled_name = nullptr;
344*288bf522SAndroid Build Coastguard Worker int status = -2; // -2 means name didn't demangle.
345*288bf522SAndroid Build Coastguard Worker if (mangled_str[1] == 'Z') {
346*288bf522SAndroid Build Coastguard Worker demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status);
347*288bf522SAndroid Build Coastguard Worker #if defined(__linux__) || defined(__darwin__)
348*288bf522SAndroid Build Coastguard Worker } else if (mangled_str[1] == 'R') {
349*288bf522SAndroid Build Coastguard Worker demangled_name = rustc_demangle(mangled_str, nullptr, nullptr, &status);
350*288bf522SAndroid Build Coastguard Worker #endif
351*288bf522SAndroid Build Coastguard Worker }
352*288bf522SAndroid Build Coastguard Worker if (status == 0) {
353*288bf522SAndroid Build Coastguard Worker // demangled successfully
354*288bf522SAndroid Build Coastguard Worker std::string result;
355*288bf522SAndroid Build Coastguard Worker if (is_linker_symbol) {
356*288bf522SAndroid Build Coastguard Worker result = std::string("[linker]") + demangled_name;
357*288bf522SAndroid Build Coastguard Worker } else {
358*288bf522SAndroid Build Coastguard Worker result = demangled_name;
359*288bf522SAndroid Build Coastguard Worker }
360*288bf522SAndroid Build Coastguard Worker free(demangled_name);
361*288bf522SAndroid Build Coastguard Worker return result;
362*288bf522SAndroid Build Coastguard Worker }
363*288bf522SAndroid Build Coastguard Worker }
364*288bf522SAndroid Build Coastguard Worker
365*288bf522SAndroid Build Coastguard Worker // failed to demangle
366*288bf522SAndroid Build Coastguard Worker if (is_linker_symbol) {
367*288bf522SAndroid Build Coastguard Worker return std::string("[linker]") + mangled_str;
368*288bf522SAndroid Build Coastguard Worker }
369*288bf522SAndroid Build Coastguard Worker return name;
370*288bf522SAndroid Build Coastguard Worker }
371*288bf522SAndroid Build Coastguard Worker
SetSymFsDir(const std::string & symfs_dir)372*288bf522SAndroid Build Coastguard Worker bool Dso::SetSymFsDir(const std::string& symfs_dir) {
373*288bf522SAndroid Build Coastguard Worker return debug_elf_file_finder_.SetSymFsDir(symfs_dir);
374*288bf522SAndroid Build Coastguard Worker }
375*288bf522SAndroid Build Coastguard Worker
AddSymbolDir(const std::string & symbol_dir)376*288bf522SAndroid Build Coastguard Worker bool Dso::AddSymbolDir(const std::string& symbol_dir) {
377*288bf522SAndroid Build Coastguard Worker return debug_elf_file_finder_.AddSymbolDir(symbol_dir);
378*288bf522SAndroid Build Coastguard Worker }
379*288bf522SAndroid Build Coastguard Worker
AllowMismatchedBuildId()380*288bf522SAndroid Build Coastguard Worker void Dso::AllowMismatchedBuildId() {
381*288bf522SAndroid Build Coastguard Worker return debug_elf_file_finder_.AllowMismatchedBuildId();
382*288bf522SAndroid Build Coastguard Worker }
383*288bf522SAndroid Build Coastguard Worker
SetVmlinux(const std::string & vmlinux)384*288bf522SAndroid Build Coastguard Worker void Dso::SetVmlinux(const std::string& vmlinux) {
385*288bf522SAndroid Build Coastguard Worker vmlinux_ = vmlinux;
386*288bf522SAndroid Build Coastguard Worker }
387*288bf522SAndroid Build Coastguard Worker
SetBuildIds(const std::vector<std::pair<std::string,BuildId>> & build_ids)388*288bf522SAndroid Build Coastguard Worker void Dso::SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids) {
389*288bf522SAndroid Build Coastguard Worker std::unordered_map<std::string, BuildId> map;
390*288bf522SAndroid Build Coastguard Worker for (auto& pair : build_ids) {
391*288bf522SAndroid Build Coastguard Worker LOG(DEBUG) << "build_id_map: " << pair.first << ", " << pair.second.ToString();
392*288bf522SAndroid Build Coastguard Worker map.insert(pair);
393*288bf522SAndroid Build Coastguard Worker }
394*288bf522SAndroid Build Coastguard Worker build_id_map_ = std::move(map);
395*288bf522SAndroid Build Coastguard Worker }
396*288bf522SAndroid Build Coastguard Worker
SetVdsoFile(const std::string & vdso_file,bool is_64bit)397*288bf522SAndroid Build Coastguard Worker void Dso::SetVdsoFile(const std::string& vdso_file, bool is_64bit) {
398*288bf522SAndroid Build Coastguard Worker debug_elf_file_finder_.SetVdsoFile(vdso_file, is_64bit);
399*288bf522SAndroid Build Coastguard Worker }
400*288bf522SAndroid Build Coastguard Worker
FindExpectedBuildIdForPath(const std::string & path)401*288bf522SAndroid Build Coastguard Worker BuildId Dso::FindExpectedBuildIdForPath(const std::string& path) {
402*288bf522SAndroid Build Coastguard Worker auto it = build_id_map_.find(path);
403*288bf522SAndroid Build Coastguard Worker if (it != build_id_map_.end()) {
404*288bf522SAndroid Build Coastguard Worker return it->second;
405*288bf522SAndroid Build Coastguard Worker }
406*288bf522SAndroid Build Coastguard Worker return BuildId();
407*288bf522SAndroid Build Coastguard Worker }
408*288bf522SAndroid Build Coastguard Worker
GetExpectedBuildId() const409*288bf522SAndroid Build Coastguard Worker BuildId Dso::GetExpectedBuildId() const {
410*288bf522SAndroid Build Coastguard Worker return FindExpectedBuildIdForPath(path_);
411*288bf522SAndroid Build Coastguard Worker }
412*288bf522SAndroid Build Coastguard Worker
Dso(DsoType type,const std::string & path)413*288bf522SAndroid Build Coastguard Worker Dso::Dso(DsoType type, const std::string& path)
414*288bf522SAndroid Build Coastguard Worker : type_(type),
415*288bf522SAndroid Build Coastguard Worker path_(path),
416*288bf522SAndroid Build Coastguard Worker is_loaded_(false),
417*288bf522SAndroid Build Coastguard Worker dump_id_(UINT_MAX),
418*288bf522SAndroid Build Coastguard Worker symbol_dump_id_(0),
419*288bf522SAndroid Build Coastguard Worker symbol_warning_loglevel_(android::base::WARNING) {
420*288bf522SAndroid Build Coastguard Worker size_t pos = path.find_last_of("/\\");
421*288bf522SAndroid Build Coastguard Worker if (pos != std::string::npos) {
422*288bf522SAndroid Build Coastguard Worker file_name_ = path.substr(pos + 1);
423*288bf522SAndroid Build Coastguard Worker } else {
424*288bf522SAndroid Build Coastguard Worker file_name_ = path;
425*288bf522SAndroid Build Coastguard Worker }
426*288bf522SAndroid Build Coastguard Worker dso_count_++;
427*288bf522SAndroid Build Coastguard Worker }
428*288bf522SAndroid Build Coastguard Worker
~Dso()429*288bf522SAndroid Build Coastguard Worker Dso::~Dso() {
430*288bf522SAndroid Build Coastguard Worker if (--dso_count_ == 0) {
431*288bf522SAndroid Build Coastguard Worker // Clean up global variables when no longer used.
432*288bf522SAndroid Build Coastguard Worker symbol_name_allocator.Clear();
433*288bf522SAndroid Build Coastguard Worker demangle_ = true;
434*288bf522SAndroid Build Coastguard Worker vmlinux_.clear();
435*288bf522SAndroid Build Coastguard Worker kallsyms_.clear();
436*288bf522SAndroid Build Coastguard Worker build_id_map_.clear();
437*288bf522SAndroid Build Coastguard Worker g_dump_id_ = 0;
438*288bf522SAndroid Build Coastguard Worker debug_elf_file_finder_.Reset();
439*288bf522SAndroid Build Coastguard Worker }
440*288bf522SAndroid Build Coastguard Worker }
441*288bf522SAndroid Build Coastguard Worker
CreateDumpId()442*288bf522SAndroid Build Coastguard Worker uint32_t Dso::CreateDumpId() {
443*288bf522SAndroid Build Coastguard Worker CHECK(!HasDumpId());
444*288bf522SAndroid Build Coastguard Worker return dump_id_ = g_dump_id_++;
445*288bf522SAndroid Build Coastguard Worker }
446*288bf522SAndroid Build Coastguard Worker
CreateSymbolDumpId(const Symbol * symbol)447*288bf522SAndroid Build Coastguard Worker uint32_t Dso::CreateSymbolDumpId(const Symbol* symbol) {
448*288bf522SAndroid Build Coastguard Worker CHECK(!symbol->HasDumpId());
449*288bf522SAndroid Build Coastguard Worker symbol->dump_id_ = symbol_dump_id_++;
450*288bf522SAndroid Build Coastguard Worker return symbol->dump_id_;
451*288bf522SAndroid Build Coastguard Worker }
452*288bf522SAndroid Build Coastguard Worker
IpToFileOffset(uint64_t ip,uint64_t map_start,uint64_t map_pgoff)453*288bf522SAndroid Build Coastguard Worker std::optional<uint64_t> Dso::IpToFileOffset(uint64_t ip, uint64_t map_start, uint64_t map_pgoff) {
454*288bf522SAndroid Build Coastguard Worker return ip - map_start + map_pgoff;
455*288bf522SAndroid Build Coastguard Worker }
456*288bf522SAndroid Build Coastguard Worker
FindSymbol(uint64_t vaddr_in_dso)457*288bf522SAndroid Build Coastguard Worker const Symbol* Dso::FindSymbol(uint64_t vaddr_in_dso) {
458*288bf522SAndroid Build Coastguard Worker if (!is_loaded_) {
459*288bf522SAndroid Build Coastguard Worker LoadSymbols();
460*288bf522SAndroid Build Coastguard Worker }
461*288bf522SAndroid Build Coastguard Worker auto it = std::upper_bound(symbols_.begin(), symbols_.end(), vaddr_in_dso, CompareAddrToSymbol);
462*288bf522SAndroid Build Coastguard Worker if (it != symbols_.begin()) {
463*288bf522SAndroid Build Coastguard Worker --it;
464*288bf522SAndroid Build Coastguard Worker if (it->addr <= vaddr_in_dso && (it->addr + it->len > vaddr_in_dso)) {
465*288bf522SAndroid Build Coastguard Worker return &*it;
466*288bf522SAndroid Build Coastguard Worker }
467*288bf522SAndroid Build Coastguard Worker }
468*288bf522SAndroid Build Coastguard Worker if (!unknown_symbols_.empty()) {
469*288bf522SAndroid Build Coastguard Worker auto it = unknown_symbols_.find(vaddr_in_dso);
470*288bf522SAndroid Build Coastguard Worker if (it != unknown_symbols_.end()) {
471*288bf522SAndroid Build Coastguard Worker return &it->second;
472*288bf522SAndroid Build Coastguard Worker }
473*288bf522SAndroid Build Coastguard Worker }
474*288bf522SAndroid Build Coastguard Worker return nullptr;
475*288bf522SAndroid Build Coastguard Worker }
476*288bf522SAndroid Build Coastguard Worker
SetSymbols(std::vector<Symbol> * symbols)477*288bf522SAndroid Build Coastguard Worker void Dso::SetSymbols(std::vector<Symbol>* symbols) {
478*288bf522SAndroid Build Coastguard Worker symbols_ = std::move(*symbols);
479*288bf522SAndroid Build Coastguard Worker symbols->clear();
480*288bf522SAndroid Build Coastguard Worker }
481*288bf522SAndroid Build Coastguard Worker
AddUnknownSymbol(uint64_t vaddr_in_dso,const std::string & name)482*288bf522SAndroid Build Coastguard Worker void Dso::AddUnknownSymbol(uint64_t vaddr_in_dso, const std::string& name) {
483*288bf522SAndroid Build Coastguard Worker unknown_symbols_.insert(std::make_pair(vaddr_in_dso, Symbol(name, vaddr_in_dso, 1)));
484*288bf522SAndroid Build Coastguard Worker }
485*288bf522SAndroid Build Coastguard Worker
IsForJavaMethod() const486*288bf522SAndroid Build Coastguard Worker bool Dso::IsForJavaMethod() const {
487*288bf522SAndroid Build Coastguard Worker if (type_ == DSO_DEX_FILE) {
488*288bf522SAndroid Build Coastguard Worker return true;
489*288bf522SAndroid Build Coastguard Worker }
490*288bf522SAndroid Build Coastguard Worker if (type_ == DSO_ELF_FILE) {
491*288bf522SAndroid Build Coastguard Worker if (JITDebugReader::IsPathInJITSymFile(path_)) {
492*288bf522SAndroid Build Coastguard Worker return true;
493*288bf522SAndroid Build Coastguard Worker }
494*288bf522SAndroid Build Coastguard Worker // JITDebugReader in old versions generates symfiles in 'TemporaryFile-XXXXXX'.
495*288bf522SAndroid Build Coastguard Worker size_t pos = path_.rfind('/');
496*288bf522SAndroid Build Coastguard Worker pos = (pos == std::string::npos) ? 0 : pos + 1;
497*288bf522SAndroid Build Coastguard Worker return StartsWith(std::string_view(&path_[pos], path_.size() - pos), "TemporaryFile");
498*288bf522SAndroid Build Coastguard Worker }
499*288bf522SAndroid Build Coastguard Worker return false;
500*288bf522SAndroid Build Coastguard Worker }
501*288bf522SAndroid Build Coastguard Worker
LoadSymbols()502*288bf522SAndroid Build Coastguard Worker void Dso::LoadSymbols() {
503*288bf522SAndroid Build Coastguard Worker if (!is_loaded_) {
504*288bf522SAndroid Build Coastguard Worker is_loaded_ = true;
505*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> symbols = LoadSymbolsImpl();
506*288bf522SAndroid Build Coastguard Worker if (symbols_.empty()) {
507*288bf522SAndroid Build Coastguard Worker symbols_ = std::move(symbols);
508*288bf522SAndroid Build Coastguard Worker } else {
509*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> merged_symbols;
510*288bf522SAndroid Build Coastguard Worker std::set_union(symbols_.begin(), symbols_.end(), symbols.begin(), symbols.end(),
511*288bf522SAndroid Build Coastguard Worker std::back_inserter(merged_symbols), Symbol::CompareValueByAddr);
512*288bf522SAndroid Build Coastguard Worker symbols_ = std::move(merged_symbols);
513*288bf522SAndroid Build Coastguard Worker }
514*288bf522SAndroid Build Coastguard Worker }
515*288bf522SAndroid Build Coastguard Worker }
516*288bf522SAndroid Build Coastguard Worker
ReportReadElfSymbolResult(ElfStatus result,const std::string & path,const std::string & debug_file_path,android::base::LogSeverity warning_loglevel=android::base::WARNING)517*288bf522SAndroid Build Coastguard Worker static void ReportReadElfSymbolResult(
518*288bf522SAndroid Build Coastguard Worker ElfStatus result, const std::string& path, const std::string& debug_file_path,
519*288bf522SAndroid Build Coastguard Worker android::base::LogSeverity warning_loglevel = android::base::WARNING) {
520*288bf522SAndroid Build Coastguard Worker if (result == ElfStatus::NO_ERROR) {
521*288bf522SAndroid Build Coastguard Worker LOG(VERBOSE) << "Read symbols from " << debug_file_path << " successfully";
522*288bf522SAndroid Build Coastguard Worker } else if (result == ElfStatus::NO_SYMBOL_TABLE) {
523*288bf522SAndroid Build Coastguard Worker if (path == "[vdso]") {
524*288bf522SAndroid Build Coastguard Worker // Vdso only contains dynamic symbol table, and we can't change that.
525*288bf522SAndroid Build Coastguard Worker return;
526*288bf522SAndroid Build Coastguard Worker }
527*288bf522SAndroid Build Coastguard Worker // Lacking symbol table isn't considered as an error but worth reporting.
528*288bf522SAndroid Build Coastguard Worker LOG(warning_loglevel) << debug_file_path << " doesn't contain symbol table";
529*288bf522SAndroid Build Coastguard Worker } else {
530*288bf522SAndroid Build Coastguard Worker LOG(warning_loglevel) << "failed to read symbols from " << debug_file_path << ": " << result;
531*288bf522SAndroid Build Coastguard Worker }
532*288bf522SAndroid Build Coastguard Worker }
533*288bf522SAndroid Build Coastguard Worker
SortAndFixSymbols(std::vector<Symbol> & symbols)534*288bf522SAndroid Build Coastguard Worker static void SortAndFixSymbols(std::vector<Symbol>& symbols) {
535*288bf522SAndroid Build Coastguard Worker std::sort(symbols.begin(), symbols.end(), Symbol::CompareValueByAddr);
536*288bf522SAndroid Build Coastguard Worker Symbol* prev_symbol = nullptr;
537*288bf522SAndroid Build Coastguard Worker for (auto& symbol : symbols) {
538*288bf522SAndroid Build Coastguard Worker if (prev_symbol != nullptr && prev_symbol->len == 0) {
539*288bf522SAndroid Build Coastguard Worker prev_symbol->len = symbol.addr - prev_symbol->addr;
540*288bf522SAndroid Build Coastguard Worker }
541*288bf522SAndroid Build Coastguard Worker prev_symbol = &symbol;
542*288bf522SAndroid Build Coastguard Worker }
543*288bf522SAndroid Build Coastguard Worker }
544*288bf522SAndroid Build Coastguard Worker
545*288bf522SAndroid Build Coastguard Worker class DexFileDso : public Dso {
546*288bf522SAndroid Build Coastguard Worker public:
DexFileDso(const std::string & path)547*288bf522SAndroid Build Coastguard Worker DexFileDso(const std::string& path) : Dso(DSO_DEX_FILE, path) {}
548*288bf522SAndroid Build Coastguard Worker
AddDexFileOffset(uint64_t dex_file_offset)549*288bf522SAndroid Build Coastguard Worker void AddDexFileOffset(uint64_t dex_file_offset) override {
550*288bf522SAndroid Build Coastguard Worker auto it = std::lower_bound(dex_file_offsets_.begin(), dex_file_offsets_.end(), dex_file_offset);
551*288bf522SAndroid Build Coastguard Worker if (it != dex_file_offsets_.end() && *it == dex_file_offset) {
552*288bf522SAndroid Build Coastguard Worker return;
553*288bf522SAndroid Build Coastguard Worker }
554*288bf522SAndroid Build Coastguard Worker dex_file_offsets_.insert(it, dex_file_offset);
555*288bf522SAndroid Build Coastguard Worker }
556*288bf522SAndroid Build Coastguard Worker
DexFileOffsets()557*288bf522SAndroid Build Coastguard Worker const std::vector<uint64_t>* DexFileOffsets() override { return &dex_file_offsets_; }
558*288bf522SAndroid Build Coastguard Worker
IpToVaddrInFile(uint64_t ip,uint64_t map_start,uint64_t map_pgoff)559*288bf522SAndroid Build Coastguard Worker uint64_t IpToVaddrInFile(uint64_t ip, uint64_t map_start, uint64_t map_pgoff) override {
560*288bf522SAndroid Build Coastguard Worker return ip - map_start + map_pgoff;
561*288bf522SAndroid Build Coastguard Worker }
562*288bf522SAndroid Build Coastguard Worker
LoadSymbolsImpl()563*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> LoadSymbolsImpl() override {
564*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> symbols;
565*288bf522SAndroid Build Coastguard Worker if (StartsWith(path_, kDexFileInMemoryPrefix)) {
566*288bf522SAndroid Build Coastguard Worker // For dex file in memory, the symbols should already be set via SetSymbols().
567*288bf522SAndroid Build Coastguard Worker return symbols;
568*288bf522SAndroid Build Coastguard Worker }
569*288bf522SAndroid Build Coastguard Worker
570*288bf522SAndroid Build Coastguard Worker const std::string& debug_file_path = GetDebugFilePath();
571*288bf522SAndroid Build Coastguard Worker auto tuple = SplitUrlInApk(debug_file_path);
572*288bf522SAndroid Build Coastguard Worker // Symbols of dex files are collected on device. If the dex file doesn't exist, probably
573*288bf522SAndroid Build Coastguard Worker // we are reporting on host, and there is no need to report warning of missing dex files.
574*288bf522SAndroid Build Coastguard Worker if (!IsRegularFile(std::get<0>(tuple) ? std::get<1>(tuple) : debug_file_path)) {
575*288bf522SAndroid Build Coastguard Worker LOG(DEBUG) << "skip reading symbols from non-exist dex_file " << debug_file_path;
576*288bf522SAndroid Build Coastguard Worker return symbols;
577*288bf522SAndroid Build Coastguard Worker }
578*288bf522SAndroid Build Coastguard Worker bool status = false;
579*288bf522SAndroid Build Coastguard Worker auto symbol_callback = [&](DexFileSymbol* symbol) {
580*288bf522SAndroid Build Coastguard Worker symbols.emplace_back(symbol->name, symbol->addr, symbol->size);
581*288bf522SAndroid Build Coastguard Worker };
582*288bf522SAndroid Build Coastguard Worker if (std::get<0>(tuple)) {
583*288bf522SAndroid Build Coastguard Worker std::unique_ptr<ArchiveHelper> ahelper = ArchiveHelper::CreateInstance(std::get<1>(tuple));
584*288bf522SAndroid Build Coastguard Worker ZipEntry entry;
585*288bf522SAndroid Build Coastguard Worker std::vector<uint8_t> data;
586*288bf522SAndroid Build Coastguard Worker if (ahelper && ahelper->FindEntry(std::get<2>(tuple), &entry) &&
587*288bf522SAndroid Build Coastguard Worker ahelper->GetEntryData(entry, &data)) {
588*288bf522SAndroid Build Coastguard Worker status = ReadSymbolsFromDexFileInMemory(data.data(), data.size(), debug_file_path,
589*288bf522SAndroid Build Coastguard Worker dex_file_offsets_, symbol_callback);
590*288bf522SAndroid Build Coastguard Worker }
591*288bf522SAndroid Build Coastguard Worker } else {
592*288bf522SAndroid Build Coastguard Worker status = ReadSymbolsFromDexFile(debug_file_path, dex_file_offsets_, symbol_callback);
593*288bf522SAndroid Build Coastguard Worker }
594*288bf522SAndroid Build Coastguard Worker if (!status) {
595*288bf522SAndroid Build Coastguard Worker android::base::LogSeverity level =
596*288bf522SAndroid Build Coastguard Worker symbols_.empty() ? android::base::WARNING : android::base::DEBUG;
597*288bf522SAndroid Build Coastguard Worker LOG(level) << "Failed to read symbols from dex_file " << debug_file_path;
598*288bf522SAndroid Build Coastguard Worker return symbols;
599*288bf522SAndroid Build Coastguard Worker }
600*288bf522SAndroid Build Coastguard Worker LOG(VERBOSE) << "Read symbols from dex_file " << debug_file_path << " successfully";
601*288bf522SAndroid Build Coastguard Worker SortAndFixSymbols(symbols);
602*288bf522SAndroid Build Coastguard Worker return symbols;
603*288bf522SAndroid Build Coastguard Worker }
604*288bf522SAndroid Build Coastguard Worker
605*288bf522SAndroid Build Coastguard Worker private:
606*288bf522SAndroid Build Coastguard Worker std::vector<uint64_t> dex_file_offsets_;
607*288bf522SAndroid Build Coastguard Worker };
608*288bf522SAndroid Build Coastguard Worker
609*288bf522SAndroid Build Coastguard Worker class ElfDso : public Dso {
610*288bf522SAndroid Build Coastguard Worker public:
ElfDso(const std::string & path,bool force_64bit)611*288bf522SAndroid Build Coastguard Worker ElfDso(const std::string& path, bool force_64bit)
612*288bf522SAndroid Build Coastguard Worker : Dso(DSO_ELF_FILE, path), force_64bit_(force_64bit) {}
613*288bf522SAndroid Build Coastguard Worker
GetReportPath() const614*288bf522SAndroid Build Coastguard Worker std::string_view GetReportPath() const override {
615*288bf522SAndroid Build Coastguard Worker if (JITDebugReader::IsPathInJITSymFile(path_)) {
616*288bf522SAndroid Build Coastguard Worker if (path_.find(kJITAppCacheFile) != path_.npos) {
617*288bf522SAndroid Build Coastguard Worker return "[JIT app cache]";
618*288bf522SAndroid Build Coastguard Worker }
619*288bf522SAndroid Build Coastguard Worker return "[JIT zygote cache]";
620*288bf522SAndroid Build Coastguard Worker }
621*288bf522SAndroid Build Coastguard Worker return path_;
622*288bf522SAndroid Build Coastguard Worker }
623*288bf522SAndroid Build Coastguard Worker
SetMinExecutableVaddr(uint64_t min_vaddr,uint64_t file_offset)624*288bf522SAndroid Build Coastguard Worker void SetMinExecutableVaddr(uint64_t min_vaddr, uint64_t file_offset) override {
625*288bf522SAndroid Build Coastguard Worker min_vaddr_ = min_vaddr;
626*288bf522SAndroid Build Coastguard Worker file_offset_of_min_vaddr_ = file_offset;
627*288bf522SAndroid Build Coastguard Worker }
628*288bf522SAndroid Build Coastguard Worker
GetMinExecutableVaddr(uint64_t * min_vaddr,uint64_t * file_offset)629*288bf522SAndroid Build Coastguard Worker void GetMinExecutableVaddr(uint64_t* min_vaddr, uint64_t* file_offset) override {
630*288bf522SAndroid Build Coastguard Worker if (type_ == DSO_DEX_FILE) {
631*288bf522SAndroid Build Coastguard Worker return dex_file_dso_->GetMinExecutableVaddr(min_vaddr, file_offset);
632*288bf522SAndroid Build Coastguard Worker }
633*288bf522SAndroid Build Coastguard Worker if (min_vaddr_ == uninitialized_value) {
634*288bf522SAndroid Build Coastguard Worker min_vaddr_ = 0;
635*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
636*288bf522SAndroid Build Coastguard Worker
637*288bf522SAndroid Build Coastguard Worker ElfStatus status;
638*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(GetDebugFilePath(), &build_id, &status);
639*288bf522SAndroid Build Coastguard Worker if (elf) {
640*288bf522SAndroid Build Coastguard Worker min_vaddr_ = elf->ReadMinExecutableVaddr(&file_offset_of_min_vaddr_);
641*288bf522SAndroid Build Coastguard Worker } else {
642*288bf522SAndroid Build Coastguard Worker // This is likely to be a file wrongly thought of as an ELF file, due to stack unwinding.
643*288bf522SAndroid Build Coastguard Worker // No need to report it by default.
644*288bf522SAndroid Build Coastguard Worker LOG(DEBUG) << "failed to read min virtual address of " << GetDebugFilePath() << ": "
645*288bf522SAndroid Build Coastguard Worker << status;
646*288bf522SAndroid Build Coastguard Worker }
647*288bf522SAndroid Build Coastguard Worker }
648*288bf522SAndroid Build Coastguard Worker *min_vaddr = min_vaddr_;
649*288bf522SAndroid Build Coastguard Worker *file_offset = file_offset_of_min_vaddr_;
650*288bf522SAndroid Build Coastguard Worker }
651*288bf522SAndroid Build Coastguard Worker
IpToVaddrInFile(uint64_t ip,uint64_t map_start,uint64_t map_pgoff)652*288bf522SAndroid Build Coastguard Worker uint64_t IpToVaddrInFile(uint64_t ip, uint64_t map_start, uint64_t map_pgoff) override {
653*288bf522SAndroid Build Coastguard Worker if (type_ == DSO_DEX_FILE) {
654*288bf522SAndroid Build Coastguard Worker return dex_file_dso_->IpToVaddrInFile(ip, map_start, map_pgoff);
655*288bf522SAndroid Build Coastguard Worker }
656*288bf522SAndroid Build Coastguard Worker uint64_t min_vaddr;
657*288bf522SAndroid Build Coastguard Worker uint64_t file_offset_of_min_vaddr;
658*288bf522SAndroid Build Coastguard Worker GetMinExecutableVaddr(&min_vaddr, &file_offset_of_min_vaddr);
659*288bf522SAndroid Build Coastguard Worker if (file_offset_of_min_vaddr == uninitialized_value) {
660*288bf522SAndroid Build Coastguard Worker return ip - map_start + min_vaddr;
661*288bf522SAndroid Build Coastguard Worker }
662*288bf522SAndroid Build Coastguard Worker // Apps may make part of the executable segment of a shared library writeable, which can
663*288bf522SAndroid Build Coastguard Worker // generate multiple executable segments at runtime. So use map_pgoff to calculate
664*288bf522SAndroid Build Coastguard Worker // vaddr_in_file.
665*288bf522SAndroid Build Coastguard Worker return ip - map_start + map_pgoff - file_offset_of_min_vaddr + min_vaddr;
666*288bf522SAndroid Build Coastguard Worker }
667*288bf522SAndroid Build Coastguard Worker
AddDexFileOffset(uint64_t dex_file_offset)668*288bf522SAndroid Build Coastguard Worker void AddDexFileOffset(uint64_t dex_file_offset) override {
669*288bf522SAndroid Build Coastguard Worker if (type_ == DSO_ELF_FILE) {
670*288bf522SAndroid Build Coastguard Worker // When simpleperf does unwinding while recording, it processes mmap records before reading
671*288bf522SAndroid Build Coastguard Worker // dex file linked list (via JITDebugReader). To process mmap records, it creates Dso
672*288bf522SAndroid Build Coastguard Worker // objects of type ELF_FILE. Then after reading dex file linked list, it realizes some
673*288bf522SAndroid Build Coastguard Worker // ELF_FILE Dso objects should actually be DEX_FILE, because they have dex file offsets.
674*288bf522SAndroid Build Coastguard Worker // So here converts ELF_FILE Dso into DEX_FILE Dso.
675*288bf522SAndroid Build Coastguard Worker type_ = DSO_DEX_FILE;
676*288bf522SAndroid Build Coastguard Worker dex_file_dso_.reset(new DexFileDso(path_));
677*288bf522SAndroid Build Coastguard Worker }
678*288bf522SAndroid Build Coastguard Worker dex_file_dso_->AddDexFileOffset(dex_file_offset);
679*288bf522SAndroid Build Coastguard Worker }
680*288bf522SAndroid Build Coastguard Worker
DexFileOffsets()681*288bf522SAndroid Build Coastguard Worker const std::vector<uint64_t>* DexFileOffsets() override {
682*288bf522SAndroid Build Coastguard Worker return dex_file_dso_ ? dex_file_dso_->DexFileOffsets() : nullptr;
683*288bf522SAndroid Build Coastguard Worker }
684*288bf522SAndroid Build Coastguard Worker
685*288bf522SAndroid Build Coastguard Worker protected:
FindDebugFilePath() const686*288bf522SAndroid Build Coastguard Worker std::string FindDebugFilePath() const override {
687*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
688*288bf522SAndroid Build Coastguard Worker return debug_elf_file_finder_.FindDebugFile(path_, force_64bit_, build_id);
689*288bf522SAndroid Build Coastguard Worker }
690*288bf522SAndroid Build Coastguard Worker
LoadSymbolsImpl()691*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> LoadSymbolsImpl() override {
692*288bf522SAndroid Build Coastguard Worker if (dex_file_dso_) {
693*288bf522SAndroid Build Coastguard Worker return dex_file_dso_->LoadSymbolsImpl();
694*288bf522SAndroid Build Coastguard Worker }
695*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> symbols;
696*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
697*288bf522SAndroid Build Coastguard Worker auto symbol_callback = [&](const ElfFileSymbol& symbol) {
698*288bf522SAndroid Build Coastguard Worker if (symbol.is_func || (symbol.is_label && symbol.is_in_text_section)) {
699*288bf522SAndroid Build Coastguard Worker symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
700*288bf522SAndroid Build Coastguard Worker }
701*288bf522SAndroid Build Coastguard Worker };
702*288bf522SAndroid Build Coastguard Worker ElfStatus status;
703*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(GetDebugFilePath(), &build_id, &status);
704*288bf522SAndroid Build Coastguard Worker if (elf) {
705*288bf522SAndroid Build Coastguard Worker status = elf->ParseSymbols(symbol_callback);
706*288bf522SAndroid Build Coastguard Worker }
707*288bf522SAndroid Build Coastguard Worker android::base::LogSeverity log_level = android::base::WARNING;
708*288bf522SAndroid Build Coastguard Worker if (!symbols_.empty() || !symbols.empty()) {
709*288bf522SAndroid Build Coastguard Worker // We already have some symbols when recording.
710*288bf522SAndroid Build Coastguard Worker log_level = android::base::DEBUG;
711*288bf522SAndroid Build Coastguard Worker }
712*288bf522SAndroid Build Coastguard Worker if ((status == ElfStatus::FILE_NOT_FOUND || status == ElfStatus::FILE_MALFORMED) &&
713*288bf522SAndroid Build Coastguard Worker build_id.IsEmpty()) {
714*288bf522SAndroid Build Coastguard Worker // This is likely to be a file wrongly thought of as an ELF file, due to stack unwinding.
715*288bf522SAndroid Build Coastguard Worker log_level = android::base::DEBUG;
716*288bf522SAndroid Build Coastguard Worker }
717*288bf522SAndroid Build Coastguard Worker ReportReadElfSymbolResult(status, path_, GetDebugFilePath(), log_level);
718*288bf522SAndroid Build Coastguard Worker SortAndFixSymbols(symbols);
719*288bf522SAndroid Build Coastguard Worker return symbols;
720*288bf522SAndroid Build Coastguard Worker }
721*288bf522SAndroid Build Coastguard Worker
722*288bf522SAndroid Build Coastguard Worker private:
723*288bf522SAndroid Build Coastguard Worker static constexpr uint64_t uninitialized_value = std::numeric_limits<uint64_t>::max();
724*288bf522SAndroid Build Coastguard Worker
725*288bf522SAndroid Build Coastguard Worker bool force_64bit_;
726*288bf522SAndroid Build Coastguard Worker uint64_t min_vaddr_ = uninitialized_value;
727*288bf522SAndroid Build Coastguard Worker uint64_t file_offset_of_min_vaddr_ = uninitialized_value;
728*288bf522SAndroid Build Coastguard Worker std::unique_ptr<DexFileDso> dex_file_dso_;
729*288bf522SAndroid Build Coastguard Worker };
730*288bf522SAndroid Build Coastguard Worker
731*288bf522SAndroid Build Coastguard Worker class KernelDso : public Dso {
732*288bf522SAndroid Build Coastguard Worker public:
KernelDso(const std::string & path)733*288bf522SAndroid Build Coastguard Worker KernelDso(const std::string& path) : Dso(DSO_KERNEL, path) {}
734*288bf522SAndroid Build Coastguard Worker
735*288bf522SAndroid Build Coastguard Worker // IpToVaddrInFile() and LoadSymbols() must be consistent in fixing addresses changed by kernel
736*288bf522SAndroid Build Coastguard Worker // address space layout randomization.
IpToVaddrInFile(uint64_t ip,uint64_t map_start,uint64_t)737*288bf522SAndroid Build Coastguard Worker uint64_t IpToVaddrInFile(uint64_t ip, uint64_t map_start, uint64_t) override {
738*288bf522SAndroid Build Coastguard Worker if (map_start != 0 && GetKernelStartAddr() != 0) {
739*288bf522SAndroid Build Coastguard Worker // Fix kernel addresses changed by kernel address randomization.
740*288bf522SAndroid Build Coastguard Worker fix_kernel_address_randomization_ = true;
741*288bf522SAndroid Build Coastguard Worker return ip - map_start + GetKernelStartAddr();
742*288bf522SAndroid Build Coastguard Worker }
743*288bf522SAndroid Build Coastguard Worker return ip;
744*288bf522SAndroid Build Coastguard Worker }
745*288bf522SAndroid Build Coastguard Worker
IpToFileOffset(uint64_t ip,uint64_t map_start,uint64_t)746*288bf522SAndroid Build Coastguard Worker std::optional<uint64_t> IpToFileOffset(uint64_t ip, uint64_t map_start, uint64_t) override {
747*288bf522SAndroid Build Coastguard Worker if (map_start != 0 && GetKernelStartOffset() != 0) {
748*288bf522SAndroid Build Coastguard Worker return ip - map_start + GetKernelStartOffset();
749*288bf522SAndroid Build Coastguard Worker }
750*288bf522SAndroid Build Coastguard Worker return std::nullopt;
751*288bf522SAndroid Build Coastguard Worker }
752*288bf522SAndroid Build Coastguard Worker
753*288bf522SAndroid Build Coastguard Worker protected:
FindDebugFilePath() const754*288bf522SAndroid Build Coastguard Worker std::string FindDebugFilePath() const override {
755*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
756*288bf522SAndroid Build Coastguard Worker if (!vmlinux_.empty()) {
757*288bf522SAndroid Build Coastguard Worker // Use vmlinux as the kernel debug file.
758*288bf522SAndroid Build Coastguard Worker ElfStatus status;
759*288bf522SAndroid Build Coastguard Worker if (ElfFile::Open(vmlinux_, &build_id, &status)) {
760*288bf522SAndroid Build Coastguard Worker return vmlinux_;
761*288bf522SAndroid Build Coastguard Worker }
762*288bf522SAndroid Build Coastguard Worker }
763*288bf522SAndroid Build Coastguard Worker return debug_elf_file_finder_.FindDebugFile(path_, false, build_id);
764*288bf522SAndroid Build Coastguard Worker }
765*288bf522SAndroid Build Coastguard Worker
LoadSymbolsImpl()766*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> LoadSymbolsImpl() override {
767*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> symbols;
768*288bf522SAndroid Build Coastguard Worker ReadSymbolsFromDebugFile(&symbols);
769*288bf522SAndroid Build Coastguard Worker
770*288bf522SAndroid Build Coastguard Worker if (symbols.empty() && !kallsyms_.empty()) {
771*288bf522SAndroid Build Coastguard Worker ReadSymbolsFromKallsyms(kallsyms_, &symbols);
772*288bf522SAndroid Build Coastguard Worker }
773*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
774*288bf522SAndroid Build Coastguard Worker if (symbols.empty()) {
775*288bf522SAndroid Build Coastguard Worker ReadSymbolsFromProc(&symbols);
776*288bf522SAndroid Build Coastguard Worker }
777*288bf522SAndroid Build Coastguard Worker #endif // defined(__linux__)
778*288bf522SAndroid Build Coastguard Worker SortAndFixSymbols(symbols);
779*288bf522SAndroid Build Coastguard Worker if (!symbols.empty() && symbols.back().len == 0) {
780*288bf522SAndroid Build Coastguard Worker symbols.back().len = std::numeric_limits<uint64_t>::max() - symbols.back().addr;
781*288bf522SAndroid Build Coastguard Worker }
782*288bf522SAndroid Build Coastguard Worker return symbols;
783*288bf522SAndroid Build Coastguard Worker }
784*288bf522SAndroid Build Coastguard Worker
785*288bf522SAndroid Build Coastguard Worker private:
ReadSymbolsFromDebugFile(std::vector<Symbol> * symbols)786*288bf522SAndroid Build Coastguard Worker void ReadSymbolsFromDebugFile(std::vector<Symbol>* symbols) {
787*288bf522SAndroid Build Coastguard Worker ElfStatus status;
788*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(GetDebugFilePath(), &status);
789*288bf522SAndroid Build Coastguard Worker if (!elf) {
790*288bf522SAndroid Build Coastguard Worker return;
791*288bf522SAndroid Build Coastguard Worker }
792*288bf522SAndroid Build Coastguard Worker
793*288bf522SAndroid Build Coastguard Worker if (!fix_kernel_address_randomization_) {
794*288bf522SAndroid Build Coastguard Worker LOG(WARNING) << "Don't know how to fix addresses changed by kernel address randomization. So "
795*288bf522SAndroid Build Coastguard Worker "symbols in "
796*288bf522SAndroid Build Coastguard Worker << GetDebugFilePath() << " are not used";
797*288bf522SAndroid Build Coastguard Worker return;
798*288bf522SAndroid Build Coastguard Worker }
799*288bf522SAndroid Build Coastguard Worker // symbols_ are kernel symbols got from /proc/kallsyms while recording. Those symbols are
800*288bf522SAndroid Build Coastguard Worker // not fixed for kernel address randomization. So clear them to avoid mixing them with
801*288bf522SAndroid Build Coastguard Worker // symbols in debug_file_path.
802*288bf522SAndroid Build Coastguard Worker symbols_.clear();
803*288bf522SAndroid Build Coastguard Worker
804*288bf522SAndroid Build Coastguard Worker auto symbol_callback = [&](const ElfFileSymbol& symbol) {
805*288bf522SAndroid Build Coastguard Worker if (symbol.is_func) {
806*288bf522SAndroid Build Coastguard Worker symbols->emplace_back(symbol.name, symbol.vaddr, symbol.len);
807*288bf522SAndroid Build Coastguard Worker }
808*288bf522SAndroid Build Coastguard Worker };
809*288bf522SAndroid Build Coastguard Worker status = elf->ParseSymbols(symbol_callback);
810*288bf522SAndroid Build Coastguard Worker ReportReadElfSymbolResult(status, path_, GetDebugFilePath());
811*288bf522SAndroid Build Coastguard Worker }
812*288bf522SAndroid Build Coastguard Worker
ReadSymbolsFromKallsyms(std::string & kallsyms,std::vector<Symbol> * symbols)813*288bf522SAndroid Build Coastguard Worker void ReadSymbolsFromKallsyms(std::string& kallsyms, std::vector<Symbol>* symbols) {
814*288bf522SAndroid Build Coastguard Worker auto symbol_callback = [&](const KernelSymbol& symbol) {
815*288bf522SAndroid Build Coastguard Worker if (strchr("TtWw", symbol.type) && symbol.addr != 0u) {
816*288bf522SAndroid Build Coastguard Worker if (symbol.module == nullptr) {
817*288bf522SAndroid Build Coastguard Worker symbols->emplace_back(symbol.name, symbol.addr, 0);
818*288bf522SAndroid Build Coastguard Worker } else {
819*288bf522SAndroid Build Coastguard Worker std::string name = std::string(symbol.name) + " [" + symbol.module + "]";
820*288bf522SAndroid Build Coastguard Worker symbols->emplace_back(name, symbol.addr, 0);
821*288bf522SAndroid Build Coastguard Worker }
822*288bf522SAndroid Build Coastguard Worker }
823*288bf522SAndroid Build Coastguard Worker return false;
824*288bf522SAndroid Build Coastguard Worker };
825*288bf522SAndroid Build Coastguard Worker ProcessKernelSymbols(kallsyms, symbol_callback);
826*288bf522SAndroid Build Coastguard Worker if (symbols->empty()) {
827*288bf522SAndroid Build Coastguard Worker LOG(WARNING) << "Symbol addresses in /proc/kallsyms on device are all zero. "
828*288bf522SAndroid Build Coastguard Worker "`echo 0 >/proc/sys/kernel/kptr_restrict` if possible.";
829*288bf522SAndroid Build Coastguard Worker }
830*288bf522SAndroid Build Coastguard Worker }
831*288bf522SAndroid Build Coastguard Worker
832*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
ReadSymbolsFromProc(std::vector<Symbol> * symbols)833*288bf522SAndroid Build Coastguard Worker void ReadSymbolsFromProc(std::vector<Symbol>* symbols) {
834*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
835*288bf522SAndroid Build Coastguard Worker if (!build_id.IsEmpty()) {
836*288bf522SAndroid Build Coastguard Worker // Try /proc/kallsyms only when asked to do so, or when build id matches.
837*288bf522SAndroid Build Coastguard Worker // Otherwise, it is likely to use /proc/kallsyms on host for perf.data recorded on device.
838*288bf522SAndroid Build Coastguard Worker bool can_read_kallsyms = true;
839*288bf522SAndroid Build Coastguard Worker if (!build_id.IsEmpty()) {
840*288bf522SAndroid Build Coastguard Worker BuildId real_build_id;
841*288bf522SAndroid Build Coastguard Worker if (!GetKernelBuildId(&real_build_id) || build_id != real_build_id) {
842*288bf522SAndroid Build Coastguard Worker LOG(DEBUG) << "failed to read symbols from /proc/kallsyms: Build id mismatch";
843*288bf522SAndroid Build Coastguard Worker can_read_kallsyms = false;
844*288bf522SAndroid Build Coastguard Worker }
845*288bf522SAndroid Build Coastguard Worker }
846*288bf522SAndroid Build Coastguard Worker if (can_read_kallsyms) {
847*288bf522SAndroid Build Coastguard Worker std::string kallsyms;
848*288bf522SAndroid Build Coastguard Worker if (LoadKernelSymbols(&kallsyms)) {
849*288bf522SAndroid Build Coastguard Worker ReadSymbolsFromKallsyms(kallsyms, symbols);
850*288bf522SAndroid Build Coastguard Worker }
851*288bf522SAndroid Build Coastguard Worker }
852*288bf522SAndroid Build Coastguard Worker }
853*288bf522SAndroid Build Coastguard Worker }
854*288bf522SAndroid Build Coastguard Worker #endif // defined(__linux__)
855*288bf522SAndroid Build Coastguard Worker
GetKernelStartAddr()856*288bf522SAndroid Build Coastguard Worker uint64_t GetKernelStartAddr() {
857*288bf522SAndroid Build Coastguard Worker if (!kernel_start_addr_) {
858*288bf522SAndroid Build Coastguard Worker ParseKernelStartAddr();
859*288bf522SAndroid Build Coastguard Worker }
860*288bf522SAndroid Build Coastguard Worker return kernel_start_addr_.value();
861*288bf522SAndroid Build Coastguard Worker }
862*288bf522SAndroid Build Coastguard Worker
GetKernelStartOffset()863*288bf522SAndroid Build Coastguard Worker uint64_t GetKernelStartOffset() {
864*288bf522SAndroid Build Coastguard Worker if (!kernel_start_file_offset_) {
865*288bf522SAndroid Build Coastguard Worker ParseKernelStartAddr();
866*288bf522SAndroid Build Coastguard Worker }
867*288bf522SAndroid Build Coastguard Worker return kernel_start_file_offset_.value();
868*288bf522SAndroid Build Coastguard Worker }
869*288bf522SAndroid Build Coastguard Worker
ParseKernelStartAddr()870*288bf522SAndroid Build Coastguard Worker void ParseKernelStartAddr() {
871*288bf522SAndroid Build Coastguard Worker kernel_start_addr_ = 0;
872*288bf522SAndroid Build Coastguard Worker kernel_start_file_offset_ = 0;
873*288bf522SAndroid Build Coastguard Worker ElfStatus status;
874*288bf522SAndroid Build Coastguard Worker if (auto elf = ElfFile::Open(GetDebugFilePath(), &status); elf) {
875*288bf522SAndroid Build Coastguard Worker for (const auto& section : elf->GetSectionHeader()) {
876*288bf522SAndroid Build Coastguard Worker if (section.name == ".text") {
877*288bf522SAndroid Build Coastguard Worker kernel_start_addr_ = section.vaddr;
878*288bf522SAndroid Build Coastguard Worker kernel_start_file_offset_ = section.file_offset;
879*288bf522SAndroid Build Coastguard Worker break;
880*288bf522SAndroid Build Coastguard Worker }
881*288bf522SAndroid Build Coastguard Worker }
882*288bf522SAndroid Build Coastguard Worker }
883*288bf522SAndroid Build Coastguard Worker }
884*288bf522SAndroid Build Coastguard Worker
885*288bf522SAndroid Build Coastguard Worker bool fix_kernel_address_randomization_ = false;
886*288bf522SAndroid Build Coastguard Worker std::optional<uint64_t> kernel_start_addr_;
887*288bf522SAndroid Build Coastguard Worker std::optional<uint64_t> kernel_start_file_offset_;
888*288bf522SAndroid Build Coastguard Worker };
889*288bf522SAndroid Build Coastguard Worker
890*288bf522SAndroid Build Coastguard Worker class KernelModuleDso : public Dso {
891*288bf522SAndroid Build Coastguard Worker public:
KernelModuleDso(const std::string & path,uint64_t memory_start,uint64_t memory_end,Dso * kernel_dso)892*288bf522SAndroid Build Coastguard Worker KernelModuleDso(const std::string& path, uint64_t memory_start, uint64_t memory_end,
893*288bf522SAndroid Build Coastguard Worker Dso* kernel_dso)
894*288bf522SAndroid Build Coastguard Worker : Dso(DSO_KERNEL_MODULE, path),
895*288bf522SAndroid Build Coastguard Worker memory_start_(memory_start),
896*288bf522SAndroid Build Coastguard Worker memory_end_(memory_end),
897*288bf522SAndroid Build Coastguard Worker kernel_dso_(kernel_dso) {}
898*288bf522SAndroid Build Coastguard Worker
SetMinExecutableVaddr(uint64_t min_vaddr,uint64_t memory_offset)899*288bf522SAndroid Build Coastguard Worker void SetMinExecutableVaddr(uint64_t min_vaddr, uint64_t memory_offset) override {
900*288bf522SAndroid Build Coastguard Worker min_vaddr_ = min_vaddr;
901*288bf522SAndroid Build Coastguard Worker memory_offset_of_min_vaddr_ = memory_offset;
902*288bf522SAndroid Build Coastguard Worker }
903*288bf522SAndroid Build Coastguard Worker
GetMinExecutableVaddr(uint64_t * min_vaddr,uint64_t * memory_offset)904*288bf522SAndroid Build Coastguard Worker void GetMinExecutableVaddr(uint64_t* min_vaddr, uint64_t* memory_offset) override {
905*288bf522SAndroid Build Coastguard Worker if (!min_vaddr_) {
906*288bf522SAndroid Build Coastguard Worker CalculateMinVaddr();
907*288bf522SAndroid Build Coastguard Worker }
908*288bf522SAndroid Build Coastguard Worker *min_vaddr = min_vaddr_.value();
909*288bf522SAndroid Build Coastguard Worker *memory_offset = memory_offset_of_min_vaddr_.value();
910*288bf522SAndroid Build Coastguard Worker }
911*288bf522SAndroid Build Coastguard Worker
IpToVaddrInFile(uint64_t ip,uint64_t map_start,uint64_t)912*288bf522SAndroid Build Coastguard Worker uint64_t IpToVaddrInFile(uint64_t ip, uint64_t map_start, uint64_t) override {
913*288bf522SAndroid Build Coastguard Worker uint64_t min_vaddr;
914*288bf522SAndroid Build Coastguard Worker uint64_t memory_offset;
915*288bf522SAndroid Build Coastguard Worker GetMinExecutableVaddr(&min_vaddr, &memory_offset);
916*288bf522SAndroid Build Coastguard Worker return ip - map_start - memory_offset + min_vaddr;
917*288bf522SAndroid Build Coastguard Worker }
918*288bf522SAndroid Build Coastguard Worker
919*288bf522SAndroid Build Coastguard Worker protected:
FindDebugFilePath() const920*288bf522SAndroid Build Coastguard Worker std::string FindDebugFilePath() const override {
921*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
922*288bf522SAndroid Build Coastguard Worker return debug_elf_file_finder_.FindDebugFile(path_, false, build_id);
923*288bf522SAndroid Build Coastguard Worker }
924*288bf522SAndroid Build Coastguard Worker
LoadSymbolsImpl()925*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> LoadSymbolsImpl() override {
926*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> symbols;
927*288bf522SAndroid Build Coastguard Worker BuildId build_id = GetExpectedBuildId();
928*288bf522SAndroid Build Coastguard Worker auto symbol_callback = [&](const ElfFileSymbol& symbol) {
929*288bf522SAndroid Build Coastguard Worker // We only know how to map ip addrs to symbols in text section.
930*288bf522SAndroid Build Coastguard Worker if (symbol.is_in_text_section && (symbol.is_label || symbol.is_func)) {
931*288bf522SAndroid Build Coastguard Worker symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
932*288bf522SAndroid Build Coastguard Worker }
933*288bf522SAndroid Build Coastguard Worker };
934*288bf522SAndroid Build Coastguard Worker ElfStatus status;
935*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(GetDebugFilePath(), &build_id, &status);
936*288bf522SAndroid Build Coastguard Worker if (elf) {
937*288bf522SAndroid Build Coastguard Worker status = elf->ParseSymbols(symbol_callback);
938*288bf522SAndroid Build Coastguard Worker }
939*288bf522SAndroid Build Coastguard Worker // Don't warn when a kernel module is missing. As a backup, we read symbols from /proc/kallsyms.
940*288bf522SAndroid Build Coastguard Worker ReportReadElfSymbolResult(status, path_, GetDebugFilePath(), android::base::DEBUG);
941*288bf522SAndroid Build Coastguard Worker SortAndFixSymbols(symbols);
942*288bf522SAndroid Build Coastguard Worker return symbols;
943*288bf522SAndroid Build Coastguard Worker }
944*288bf522SAndroid Build Coastguard Worker
945*288bf522SAndroid Build Coastguard Worker private:
CalculateMinVaddr()946*288bf522SAndroid Build Coastguard Worker void CalculateMinVaddr() {
947*288bf522SAndroid Build Coastguard Worker min_vaddr_ = 0;
948*288bf522SAndroid Build Coastguard Worker memory_offset_of_min_vaddr_ = 0;
949*288bf522SAndroid Build Coastguard Worker
950*288bf522SAndroid Build Coastguard Worker // min_vaddr and memory_offset are used to convert an ip addr of a kernel module to its
951*288bf522SAndroid Build Coastguard Worker // vaddr_in_file, as shown in IpToVaddrInFile(). When the kernel loads a kernel module, it
952*288bf522SAndroid Build Coastguard Worker // puts ALLOC sections (like .plt, .text.ftrace_trampoline, .text) in memory in order. The
953*288bf522SAndroid Build Coastguard Worker // text section may not be at the start of the module memory. To do address conversion, we
954*288bf522SAndroid Build Coastguard Worker // need to know its relative position in the module memory. There are two ways:
955*288bf522SAndroid Build Coastguard Worker // 1. Read the kernel module file to calculate the relative position of .text section. It
956*288bf522SAndroid Build Coastguard Worker // is relatively complex and depends on both PLT entries and the kernel version.
957*288bf522SAndroid Build Coastguard Worker // 2. Find a module symbol in .text section, get its address in memory from /proc/kallsyms,
958*288bf522SAndroid Build Coastguard Worker // and its vaddr_in_file from the kernel module file. Then other symbols in .text section can
959*288bf522SAndroid Build Coastguard Worker // be mapped in the same way. Below we use the second method.
960*288bf522SAndroid Build Coastguard Worker
961*288bf522SAndroid Build Coastguard Worker if (!IsRegularFile(GetDebugFilePath())) {
962*288bf522SAndroid Build Coastguard Worker return;
963*288bf522SAndroid Build Coastguard Worker }
964*288bf522SAndroid Build Coastguard Worker
965*288bf522SAndroid Build Coastguard Worker // 1. Select a module symbol in /proc/kallsyms.
966*288bf522SAndroid Build Coastguard Worker kernel_dso_->LoadSymbols();
967*288bf522SAndroid Build Coastguard Worker const auto& kernel_symbols = kernel_dso_->GetSymbols();
968*288bf522SAndroid Build Coastguard Worker auto it = std::lower_bound(kernel_symbols.begin(), kernel_symbols.end(), memory_start_,
969*288bf522SAndroid Build Coastguard Worker CompareSymbolToAddr);
970*288bf522SAndroid Build Coastguard Worker const Symbol* kernel_symbol = nullptr;
971*288bf522SAndroid Build Coastguard Worker while (it != kernel_symbols.end() && it->addr < memory_end_) {
972*288bf522SAndroid Build Coastguard Worker if (strlen(it->Name()) > 0 && it->Name()[0] != '$') {
973*288bf522SAndroid Build Coastguard Worker kernel_symbol = &*it;
974*288bf522SAndroid Build Coastguard Worker break;
975*288bf522SAndroid Build Coastguard Worker }
976*288bf522SAndroid Build Coastguard Worker ++it;
977*288bf522SAndroid Build Coastguard Worker }
978*288bf522SAndroid Build Coastguard Worker if (kernel_symbol == nullptr) {
979*288bf522SAndroid Build Coastguard Worker return;
980*288bf522SAndroid Build Coastguard Worker }
981*288bf522SAndroid Build Coastguard Worker
982*288bf522SAndroid Build Coastguard Worker // 2. Find the symbol in .ko file.
983*288bf522SAndroid Build Coastguard Worker std::string symbol_name = kernel_symbol->Name();
984*288bf522SAndroid Build Coastguard Worker if (auto pos = symbol_name.rfind(' '); pos != std::string::npos) {
985*288bf522SAndroid Build Coastguard Worker symbol_name.resize(pos);
986*288bf522SAndroid Build Coastguard Worker }
987*288bf522SAndroid Build Coastguard Worker LoadSymbols();
988*288bf522SAndroid Build Coastguard Worker for (const auto& symbol : symbols_) {
989*288bf522SAndroid Build Coastguard Worker if (symbol_name == symbol.Name()) {
990*288bf522SAndroid Build Coastguard Worker min_vaddr_ = symbol.addr;
991*288bf522SAndroid Build Coastguard Worker memory_offset_of_min_vaddr_ = kernel_symbol->addr - memory_start_;
992*288bf522SAndroid Build Coastguard Worker return;
993*288bf522SAndroid Build Coastguard Worker }
994*288bf522SAndroid Build Coastguard Worker }
995*288bf522SAndroid Build Coastguard Worker }
996*288bf522SAndroid Build Coastguard Worker
997*288bf522SAndroid Build Coastguard Worker uint64_t memory_start_;
998*288bf522SAndroid Build Coastguard Worker uint64_t memory_end_;
999*288bf522SAndroid Build Coastguard Worker Dso* kernel_dso_;
1000*288bf522SAndroid Build Coastguard Worker std::optional<uint64_t> min_vaddr_;
1001*288bf522SAndroid Build Coastguard Worker std::optional<uint64_t> memory_offset_of_min_vaddr_;
1002*288bf522SAndroid Build Coastguard Worker };
1003*288bf522SAndroid Build Coastguard Worker
1004*288bf522SAndroid Build Coastguard Worker class SymbolMapFileDso : public Dso {
1005*288bf522SAndroid Build Coastguard Worker public:
SymbolMapFileDso(const std::string & path)1006*288bf522SAndroid Build Coastguard Worker SymbolMapFileDso(const std::string& path) : Dso(DSO_SYMBOL_MAP_FILE, path) {}
1007*288bf522SAndroid Build Coastguard Worker
IpToVaddrInFile(uint64_t ip,uint64_t,uint64_t)1008*288bf522SAndroid Build Coastguard Worker uint64_t IpToVaddrInFile(uint64_t ip, uint64_t, uint64_t) override { return ip; }
1009*288bf522SAndroid Build Coastguard Worker
1010*288bf522SAndroid Build Coastguard Worker protected:
LoadSymbolsImpl()1011*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> LoadSymbolsImpl() override { return {}; }
1012*288bf522SAndroid Build Coastguard Worker };
1013*288bf522SAndroid Build Coastguard Worker
1014*288bf522SAndroid Build Coastguard Worker class UnknownDso : public Dso {
1015*288bf522SAndroid Build Coastguard Worker public:
UnknownDso(const std::string & path)1016*288bf522SAndroid Build Coastguard Worker UnknownDso(const std::string& path) : Dso(DSO_UNKNOWN_FILE, path) {}
1017*288bf522SAndroid Build Coastguard Worker
IpToVaddrInFile(uint64_t ip,uint64_t,uint64_t)1018*288bf522SAndroid Build Coastguard Worker uint64_t IpToVaddrInFile(uint64_t ip, uint64_t, uint64_t) override { return ip; }
1019*288bf522SAndroid Build Coastguard Worker
1020*288bf522SAndroid Build Coastguard Worker protected:
LoadSymbolsImpl()1021*288bf522SAndroid Build Coastguard Worker std::vector<Symbol> LoadSymbolsImpl() override { return std::vector<Symbol>(); }
1022*288bf522SAndroid Build Coastguard Worker };
1023*288bf522SAndroid Build Coastguard Worker
CreateDso(DsoType dso_type,const std::string & dso_path,bool force_64bit)1024*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Dso> Dso::CreateDso(DsoType dso_type, const std::string& dso_path,
1025*288bf522SAndroid Build Coastguard Worker bool force_64bit) {
1026*288bf522SAndroid Build Coastguard Worker switch (dso_type) {
1027*288bf522SAndroid Build Coastguard Worker case DSO_ELF_FILE:
1028*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<Dso>(new ElfDso(dso_path, force_64bit));
1029*288bf522SAndroid Build Coastguard Worker case DSO_KERNEL:
1030*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<Dso>(new KernelDso(dso_path));
1031*288bf522SAndroid Build Coastguard Worker case DSO_DEX_FILE:
1032*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<Dso>(new DexFileDso(dso_path));
1033*288bf522SAndroid Build Coastguard Worker case DSO_SYMBOL_MAP_FILE:
1034*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<Dso>(new SymbolMapFileDso(dso_path));
1035*288bf522SAndroid Build Coastguard Worker case DSO_UNKNOWN_FILE:
1036*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<Dso>(new UnknownDso(dso_path));
1037*288bf522SAndroid Build Coastguard Worker default:
1038*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected dso_type " << static_cast<int>(dso_type);
1039*288bf522SAndroid Build Coastguard Worker return nullptr;
1040*288bf522SAndroid Build Coastguard Worker }
1041*288bf522SAndroid Build Coastguard Worker }
1042*288bf522SAndroid Build Coastguard Worker
CreateDsoWithBuildId(DsoType dso_type,const std::string & dso_path,BuildId & build_id)1043*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Dso> Dso::CreateDsoWithBuildId(DsoType dso_type, const std::string& dso_path,
1044*288bf522SAndroid Build Coastguard Worker BuildId& build_id) {
1045*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Dso> dso;
1046*288bf522SAndroid Build Coastguard Worker switch (dso_type) {
1047*288bf522SAndroid Build Coastguard Worker case DSO_ELF_FILE:
1048*288bf522SAndroid Build Coastguard Worker dso.reset(new ElfDso(dso_path, false));
1049*288bf522SAndroid Build Coastguard Worker break;
1050*288bf522SAndroid Build Coastguard Worker case DSO_KERNEL:
1051*288bf522SAndroid Build Coastguard Worker dso.reset(new KernelDso(dso_path));
1052*288bf522SAndroid Build Coastguard Worker break;
1053*288bf522SAndroid Build Coastguard Worker case DSO_KERNEL_MODULE:
1054*288bf522SAndroid Build Coastguard Worker dso.reset(new KernelModuleDso(dso_path, 0, 0, nullptr));
1055*288bf522SAndroid Build Coastguard Worker break;
1056*288bf522SAndroid Build Coastguard Worker default:
1057*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected dso_type " << static_cast<int>(dso_type);
1058*288bf522SAndroid Build Coastguard Worker return nullptr;
1059*288bf522SAndroid Build Coastguard Worker }
1060*288bf522SAndroid Build Coastguard Worker dso->debug_file_path_ = debug_elf_file_finder_.FindDebugFile(dso_path, false, build_id);
1061*288bf522SAndroid Build Coastguard Worker return dso;
1062*288bf522SAndroid Build Coastguard Worker }
1063*288bf522SAndroid Build Coastguard Worker
CreateKernelModuleDso(const std::string & dso_path,uint64_t memory_start,uint64_t memory_end,Dso * kernel_dso)1064*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Dso> Dso::CreateKernelModuleDso(const std::string& dso_path, uint64_t memory_start,
1065*288bf522SAndroid Build Coastguard Worker uint64_t memory_end, Dso* kernel_dso) {
1066*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<Dso>(new KernelModuleDso(dso_path, memory_start, memory_end, kernel_dso));
1067*288bf522SAndroid Build Coastguard Worker }
1068*288bf522SAndroid Build Coastguard Worker
DsoTypeToString(DsoType dso_type)1069*288bf522SAndroid Build Coastguard Worker const char* DsoTypeToString(DsoType dso_type) {
1070*288bf522SAndroid Build Coastguard Worker switch (dso_type) {
1071*288bf522SAndroid Build Coastguard Worker case DSO_KERNEL:
1072*288bf522SAndroid Build Coastguard Worker return "dso_kernel";
1073*288bf522SAndroid Build Coastguard Worker case DSO_KERNEL_MODULE:
1074*288bf522SAndroid Build Coastguard Worker return "dso_kernel_module";
1075*288bf522SAndroid Build Coastguard Worker case DSO_ELF_FILE:
1076*288bf522SAndroid Build Coastguard Worker return "dso_elf_file";
1077*288bf522SAndroid Build Coastguard Worker case DSO_DEX_FILE:
1078*288bf522SAndroid Build Coastguard Worker return "dso_dex_file";
1079*288bf522SAndroid Build Coastguard Worker case DSO_SYMBOL_MAP_FILE:
1080*288bf522SAndroid Build Coastguard Worker return "dso_symbol_map_file";
1081*288bf522SAndroid Build Coastguard Worker default:
1082*288bf522SAndroid Build Coastguard Worker return "unknown";
1083*288bf522SAndroid Build Coastguard Worker }
1084*288bf522SAndroid Build Coastguard Worker }
1085*288bf522SAndroid Build Coastguard Worker
GetBuildIdFromDsoPath(const std::string & dso_path,BuildId * build_id)1086*288bf522SAndroid Build Coastguard Worker bool GetBuildIdFromDsoPath(const std::string& dso_path, BuildId* build_id) {
1087*288bf522SAndroid Build Coastguard Worker ElfStatus status;
1088*288bf522SAndroid Build Coastguard Worker auto elf = ElfFile::Open(dso_path, &status);
1089*288bf522SAndroid Build Coastguard Worker if (status == ElfStatus::NO_ERROR && elf->GetBuildId(build_id) == ElfStatus::NO_ERROR) {
1090*288bf522SAndroid Build Coastguard Worker return true;
1091*288bf522SAndroid Build Coastguard Worker }
1092*288bf522SAndroid Build Coastguard Worker return false;
1093*288bf522SAndroid Build Coastguard Worker }
1094*288bf522SAndroid Build Coastguard Worker
GetBuildId(const Dso & dso,BuildId & build_id)1095*288bf522SAndroid Build Coastguard Worker bool GetBuildId(const Dso& dso, BuildId& build_id) {
1096*288bf522SAndroid Build Coastguard Worker if (dso.type() == DSO_KERNEL) {
1097*288bf522SAndroid Build Coastguard Worker if (GetKernelBuildId(&build_id)) {
1098*288bf522SAndroid Build Coastguard Worker return true;
1099*288bf522SAndroid Build Coastguard Worker }
1100*288bf522SAndroid Build Coastguard Worker } else if (dso.type() == DSO_KERNEL_MODULE) {
1101*288bf522SAndroid Build Coastguard Worker bool has_build_id = false;
1102*288bf522SAndroid Build Coastguard Worker if (android::base::EndsWith(dso.Path(), ".ko")) {
1103*288bf522SAndroid Build Coastguard Worker return GetBuildIdFromDsoPath(dso.Path(), &build_id);
1104*288bf522SAndroid Build Coastguard Worker }
1105*288bf522SAndroid Build Coastguard Worker if (const std::string& path = dso.Path();
1106*288bf522SAndroid Build Coastguard Worker path.size() > 2 && path[0] == '[' && path.back() == ']') {
1107*288bf522SAndroid Build Coastguard Worker // For kernel modules that we can't find the corresponding file, read build id from /sysfs.
1108*288bf522SAndroid Build Coastguard Worker return GetModuleBuildId(path.substr(1, path.size() - 2), &build_id);
1109*288bf522SAndroid Build Coastguard Worker }
1110*288bf522SAndroid Build Coastguard Worker } else if (dso.type() == DSO_ELF_FILE) {
1111*288bf522SAndroid Build Coastguard Worker if (dso.Path() == DEFAULT_EXECNAME_FOR_THREAD_MMAP || dso.IsForJavaMethod()) {
1112*288bf522SAndroid Build Coastguard Worker return false;
1113*288bf522SAndroid Build Coastguard Worker }
1114*288bf522SAndroid Build Coastguard Worker if (GetBuildIdFromDsoPath(dso.Path(), &build_id)) {
1115*288bf522SAndroid Build Coastguard Worker return true;
1116*288bf522SAndroid Build Coastguard Worker }
1117*288bf522SAndroid Build Coastguard Worker }
1118*288bf522SAndroid Build Coastguard Worker return false;
1119*288bf522SAndroid Build Coastguard Worker }
1120*288bf522SAndroid Build Coastguard Worker
1121*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
1122