blob: 396bb35206c6fad9a69d9cf0e23398d97d4f7cfa [file] [log] [blame]
Yabin Cuiec12ed92015-06-08 10:38:10 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "dso.h"
18
Yabin Cuib3783552015-06-11 11:15:42 -070019#include <stdlib.h>
Yabin Cuicc2e59e2015-08-21 14:23:43 -070020#include <string.h>
Yabin Cuic8485602015-08-20 15:04:39 -070021
Yabin Cuicc2e59e2015-08-21 14:23:43 -070022#include <algorithm>
Yabin Cuic8485602015-08-20 15:04:39 -070023#include <limits>
Yabin Cuicc2e59e2015-08-21 14:23:43 -070024#include <vector>
Yabin Cuic8485602015-08-20 15:04:39 -070025
Yabin Cuib4212972016-05-25 14:08:05 -070026#include <android-base/file.h>
Elliott Hughes66dd09e2015-12-04 14:00:57 -080027#include <android-base/logging.h>
Yabin Cui40b70ff2018-04-09 14:06:08 -070028#include <android-base/strings.h>
Yabin Cuic8485602015-08-20 15:04:39 -070029
Yabin Cuiec12ed92015-06-08 10:38:10 -070030#include "environment.h"
Yabin Cuib1a885b2016-02-14 19:18:02 -080031#include "read_apk.h"
Yabin Cui516a87c2018-03-26 17:34:00 -070032#include "read_dex_file.h"
Yabin Cuiec12ed92015-06-08 10:38:10 -070033#include "read_elf.h"
Yabin Cuib3783552015-06-11 11:15:42 -070034#include "utils.h"
Yabin Cuiec12ed92015-06-08 10:38:10 -070035
Yabin Cui40b70ff2018-04-09 14:06:08 -070036namespace simpleperf_dso_impl {
37
38void DebugElfFileFinder::Reset() {
39 vdso_64bit_.clear();
40 vdso_32bit_.clear();
41 symfs_dir_.clear();
42 build_id_to_file_map_.clear();
43}
44
45bool DebugElfFileFinder::SetSymFsDir(const std::string& symfs_dir) {
46 std::string dirname = symfs_dir;
47 if (!dirname.empty()) {
48 if (dirname.back() != '/') {
49 dirname.push_back('/');
50 }
51 if (!IsDir(symfs_dir)) {
52 LOG(ERROR) << "Invalid symfs_dir '" << symfs_dir << "'";
53 return false;
54 }
55 }
56 symfs_dir_ = dirname;
57 build_id_to_file_map_.clear();
58 std::string build_id_list_file = symfs_dir_ + "build_id_list";
59 std::string build_id_list;
60 if (android::base::ReadFileToString(build_id_list_file, &build_id_list)) {
61 for (auto& line : android::base::Split(build_id_list, "\n")) {
62 std::vector<std::string> items = android::base::Split(line, "=");
63 if (items.size() == 2u) {
64 build_id_to_file_map_[items[0]] = items[1];
65 }
66 }
67 }
68 return true;
69}
70
71void DebugElfFileFinder::SetVdsoFile(const std::string& vdso_file, bool is_64bit) {
72 if (is_64bit) {
73 vdso_64bit_ = vdso_file;
74 } else {
75 vdso_32bit_ = vdso_file;
76 }
77}
78
79std::string DebugElfFileFinder::FindDebugFile(const std::string& dso_path, bool force_64bit,
80 BuildId& build_id) {
81 if (dso_path == "[vdso]") {
82 if (force_64bit && !vdso_64bit_.empty()) {
83 return vdso_64bit_;
84 } else if (!force_64bit && !vdso_32bit_.empty()) {
85 return vdso_32bit_;
86 }
87 } else if (!symfs_dir_.empty()) {
88 if (!build_id.IsEmpty() || GetBuildIdFromDsoPath(dso_path, &build_id)) {
89 std::string result;
90 auto check_path = [&](const std::string& path) {
91 BuildId debug_build_id;
92 if (GetBuildIdFromDsoPath(path, &debug_build_id) && debug_build_id == build_id) {
93 result = path;
94 return true;
95 }
96 return false;
97 };
98
99 // 1. Try build_id_to_file_map.
100 auto it = build_id_to_file_map_.find(build_id.ToString());
101 if (it != build_id_to_file_map_.end()) {
102 if (check_path(symfs_dir_ + it->second)) {
103 return result;
104 }
105 }
106 // 2. Try concatenating symfs_dir and dso_path.
107 if (check_path(symfs_dir_ + dso_path)) {
108 return result;
109 }
110 // 3. Try concatenating /usr/lib/debug and dso_path.
111 // Linux host can store debug shared libraries in /usr/lib/debug.
112 if (check_path("/usr/lib/debug" + dso_path)) {
113 return result;
114 }
115 }
116 }
117 return dso_path;
118}
119} // namespace simpleperf_dso_imp
120
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700121static OneTimeFreeAllocator symbol_name_allocator;
122
123Symbol::Symbol(const std::string& name, uint64_t addr, uint64_t len)
124 : addr(addr),
125 len(len),
126 name_(symbol_name_allocator.AllocateString(name)),
Yabin Cui767dd172016-06-02 21:02:43 -0700127 demangled_name_(nullptr),
Yabin Cui516a87c2018-03-26 17:34:00 -0700128 dump_id_(UINT_MAX) {
129}
Yabin Cuib10a8fb2015-08-18 16:32:18 -0700130
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700131const char* Symbol::DemangledName() const {
132 if (demangled_name_ == nullptr) {
133 const std::string s = Dso::Demangle(name_);
134 if (s == name_) {
135 demangled_name_ = name_;
136 } else {
137 demangled_name_ = symbol_name_allocator.AllocateString(s);
138 }
139 }
140 return demangled_name_;
Yabin Cuiec12ed92015-06-08 10:38:10 -0700141}
142
Yabin Cuic8485602015-08-20 15:04:39 -0700143bool Dso::demangle_ = true;
Yabin Cuic8485602015-08-20 15:04:39 -0700144std::string Dso::vmlinux_;
Yabin Cuib4212972016-05-25 14:08:05 -0700145std::string Dso::kallsyms_;
Yabin Cuia9392452017-01-12 18:07:27 -0800146bool Dso::read_kernel_symbols_from_proc_;
Yabin Cuic8485602015-08-20 15:04:39 -0700147std::unordered_map<std::string, BuildId> Dso::build_id_map_;
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700148size_t Dso::dso_count_;
Yabin Cui16501ff2016-10-19 15:06:29 -0700149uint32_t Dso::g_dump_id_;
Yabin Cui40b70ff2018-04-09 14:06:08 -0700150simpleperf_dso_impl::DebugElfFileFinder Dso::debug_elf_file_finder_;
Yabin Cuiba50c4b2015-07-21 11:24:48 -0700151
Yabin Cui767dd172016-06-02 21:02:43 -0700152void Dso::SetDemangle(bool demangle) { demangle_ = demangle; }
Yabin Cuib3783552015-06-11 11:15:42 -0700153
Yabin Cui767dd172016-06-02 21:02:43 -0700154extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n,
155 int* status);
Yabin Cuib10a8fb2015-08-18 16:32:18 -0700156
Yabin Cuic8485602015-08-20 15:04:39 -0700157std::string Dso::Demangle(const std::string& name) {
Yabin Cuib10a8fb2015-08-18 16:32:18 -0700158 if (!demangle_) {
159 return name;
160 }
161 int status;
162 bool is_linker_symbol = (name.find(linker_prefix) == 0);
163 const char* mangled_str = name.c_str();
164 if (is_linker_symbol) {
165 mangled_str += linker_prefix.size();
166 }
167 std::string result = name;
168 char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status);
169 if (status == 0) {
170 if (is_linker_symbol) {
171 result = std::string("[linker]") + demangled_name;
172 } else {
173 result = demangled_name;
174 }
175 free(demangled_name);
176 } else if (is_linker_symbol) {
177 result = std::string("[linker]") + mangled_str;
178 }
179 return result;
180}
181
Yabin Cuic8485602015-08-20 15:04:39 -0700182bool Dso::SetSymFsDir(const std::string& symfs_dir) {
Yabin Cui40b70ff2018-04-09 14:06:08 -0700183 return debug_elf_file_finder_.SetSymFsDir(symfs_dir);
Yabin Cuic8485602015-08-20 15:04:39 -0700184}
185
Yabin Cui767dd172016-06-02 21:02:43 -0700186void Dso::SetVmlinux(const std::string& vmlinux) { vmlinux_ = vmlinux; }
Yabin Cuic8485602015-08-20 15:04:39 -0700187
Yabin Cui767dd172016-06-02 21:02:43 -0700188void Dso::SetBuildIds(
189 const std::vector<std::pair<std::string, BuildId>>& build_ids) {
Yabin Cuic8485602015-08-20 15:04:39 -0700190 std::unordered_map<std::string, BuildId> map;
191 for (auto& pair : build_ids) {
Yabin Cui767dd172016-06-02 21:02:43 -0700192 LOG(DEBUG) << "build_id_map: " << pair.first << ", "
193 << pair.second.ToString();
Yabin Cuic8485602015-08-20 15:04:39 -0700194 map.insert(pair);
195 }
196 build_id_map_ = std::move(map);
197}
198
Yabin Cuic68e66d2018-03-07 15:47:15 -0800199void Dso::SetVdsoFile(const std::string& vdso_file, bool is_64bit) {
Yabin Cui40b70ff2018-04-09 14:06:08 -0700200 debug_elf_file_finder_.SetVdsoFile(vdso_file, is_64bit);
Yabin Cui63a1c3d2017-05-19 12:57:44 -0700201}
202
Yabin Cui52c63692016-11-28 17:28:08 -0800203BuildId Dso::FindExpectedBuildIdForPath(const std::string& path) {
204 auto it = build_id_map_.find(path);
Yabin Cuic8485602015-08-20 15:04:39 -0700205 if (it != build_id_map_.end()) {
206 return it->second;
207 }
208 return BuildId();
209}
210
Yabin Cui52c63692016-11-28 17:28:08 -0800211BuildId Dso::GetExpectedBuildId() {
212 return FindExpectedBuildIdForPath(path_);
213}
214
Yabin Cui516a87c2018-03-26 17:34:00 -0700215Dso::Dso(DsoType type, const std::string& path, const std::string& debug_file_path)
Yabin Cui767dd172016-06-02 21:02:43 -0700216 : type_(type),
Yabin Cui767dd172016-06-02 21:02:43 -0700217 path_(path),
Yabin Cui516a87c2018-03-26 17:34:00 -0700218 debug_file_path_(debug_file_path),
Yabin Cui767dd172016-06-02 21:02:43 -0700219 is_loaded_(false),
Yabin Cui16501ff2016-10-19 15:06:29 -0700220 dump_id_(UINT_MAX),
Yabin Cuie466d4d2017-08-11 17:03:07 -0700221 symbol_dump_id_(0),
222 symbol_warning_loglevel_(android::base::WARNING) {
Yabin Cui15475e62016-07-14 13:26:19 -0700223 size_t pos = path.find_last_of("/\\");
224 if (pos != std::string::npos) {
225 file_name_ = path.substr(pos + 1);
226 } else {
227 file_name_ = path;
228 }
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700229 dso_count_++;
Yabin Cuic8485602015-08-20 15:04:39 -0700230}
231
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700232Dso::~Dso() {
233 if (--dso_count_ == 0) {
Yabin Cuib4212972016-05-25 14:08:05 -0700234 // Clean up global variables when no longer used.
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700235 symbol_name_allocator.Clear();
Yabin Cuib4212972016-05-25 14:08:05 -0700236 demangle_ = true;
Yabin Cuib4212972016-05-25 14:08:05 -0700237 vmlinux_.clear();
238 kallsyms_.clear();
Yabin Cuia9392452017-01-12 18:07:27 -0800239 read_kernel_symbols_from_proc_ = false;
Yabin Cuib4212972016-05-25 14:08:05 -0700240 build_id_map_.clear();
Yabin Cui16501ff2016-10-19 15:06:29 -0700241 g_dump_id_ = 0;
Yabin Cui40b70ff2018-04-09 14:06:08 -0700242 debug_elf_file_finder_.Reset();
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700243 }
244}
245
Yabin Cui16501ff2016-10-19 15:06:29 -0700246uint32_t Dso::CreateDumpId() {
247 CHECK(!HasDumpId());
248 return dump_id_ = g_dump_id_++;
249}
250
251uint32_t Dso::CreateSymbolDumpId(const Symbol* symbol) {
252 CHECK(!symbol->HasDumpId());
253 symbol->dump_id_ = symbol_dump_id_++;
254 return symbol->dump_id_;
255}
256
Yabin Cui547c60e2015-10-12 16:56:05 -0700257const Symbol* Dso::FindSymbol(uint64_t vaddr_in_dso) {
Yabin Cuic8485602015-08-20 15:04:39 -0700258 if (!is_loaded_) {
Yabin Cuic5b4a312016-10-24 13:38:38 -0700259 Load();
260 }
Yabin Cui516a87c2018-03-26 17:34:00 -0700261 auto it = std::upper_bound(symbols_.begin(), symbols_.end(),
262 Symbol("", vaddr_in_dso, 0),
263 Symbol::CompareValueByAddr);
264 if (it != symbols_.begin()) {
265 --it;
266 if (it->addr <= vaddr_in_dso && (it->addr + it->len > vaddr_in_dso)) {
267 return &*it;
Yabin Cuic8485602015-08-20 15:04:39 -0700268 }
269 }
Yabin Cuic5b4a312016-10-24 13:38:38 -0700270 if (!unknown_symbols_.empty()) {
271 auto it = unknown_symbols_.find(vaddr_in_dso);
272 if (it != unknown_symbols_.end()) {
273 return &it->second;
Yabin Cuic8485602015-08-20 15:04:39 -0700274 }
275 }
276 return nullptr;
277}
278
Yabin Cuic5b4a312016-10-24 13:38:38 -0700279void Dso::SetSymbols(std::vector<Symbol>* symbols) {
280 symbols_ = std::move(*symbols);
281 symbols->clear();
282}
283
284void Dso::AddUnknownSymbol(uint64_t vaddr_in_dso, const std::string& name) {
285 unknown_symbols_.insert(std::make_pair(vaddr_in_dso, Symbol(name, vaddr_in_dso, 1)));
286}
287
Yabin Cuic5b4a312016-10-24 13:38:38 -0700288void Dso::Load() {
289 is_loaded_ = true;
Yabin Cui516a87c2018-03-26 17:34:00 -0700290 std::vector<Symbol> symbols = LoadSymbols();
291 if (symbols_.empty()) {
292 symbols_ = std::move(symbols);
Yabin Cuidec43c12016-07-29 16:40:40 -0700293 } else {
Yabin Cui516a87c2018-03-26 17:34:00 -0700294 std::vector<Symbol> merged_symbols;
295 std::set_union(symbols_.begin(), symbols_.end(), symbols.begin(), symbols.end(),
296 std::back_inserter(merged_symbols), Symbol::CompareValueByAddr);
297 symbols_ = std::move(merged_symbols);
Yabin Cuic8485602015-08-20 15:04:39 -0700298 }
Yabin Cuiba50c4b2015-07-21 11:24:48 -0700299}
300
Yabin Cui516a87c2018-03-26 17:34:00 -0700301static void ReportReadElfSymbolResult(ElfStatus result, const std::string& path,
302 const std::string& debug_file_path,
303 android::base::LogSeverity warning_loglevel = android::base::WARNING) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700304 if (result == ElfStatus::NO_ERROR) {
Yabin Cui516a87c2018-03-26 17:34:00 -0700305 LOG(VERBOSE) << "Read symbols from " << debug_file_path << " successfully";
Yabin Cuidec43c12016-07-29 16:40:40 -0700306 } else if (result == ElfStatus::NO_SYMBOL_TABLE) {
Yabin Cui516a87c2018-03-26 17:34:00 -0700307 if (path == "[vdso]") {
Yabin Cui63a1c3d2017-05-19 12:57:44 -0700308 // Vdso only contains dynamic symbol table, and we can't change that.
Yabin Cui516a87c2018-03-26 17:34:00 -0700309 return;
Yabin Cui63a1c3d2017-05-19 12:57:44 -0700310 }
Yabin Cuidec43c12016-07-29 16:40:40 -0700311 // Lacking symbol table isn't considered as an error but worth reporting.
Yabin Cui516a87c2018-03-26 17:34:00 -0700312 LOG(warning_loglevel) << debug_file_path << " doesn't contain symbol table";
Yabin Cuidec43c12016-07-29 16:40:40 -0700313 } else {
Yabin Cui516a87c2018-03-26 17:34:00 -0700314 LOG(warning_loglevel) << "failed to read symbols from " << debug_file_path << ": " << result;
Yabin Cuidec43c12016-07-29 16:40:40 -0700315 }
316}
317
Yabin Cui516a87c2018-03-26 17:34:00 -0700318static void SortAndFixSymbols(std::vector<Symbol>& symbols) {
319 std::sort(symbols.begin(), symbols.end(), Symbol::CompareValueByAddr);
Yabin Cuic8485602015-08-20 15:04:39 -0700320 Symbol* prev_symbol = nullptr;
Yabin Cui516a87c2018-03-26 17:34:00 -0700321 for (auto& symbol : symbols) {
Yabin Cuic8485602015-08-20 15:04:39 -0700322 if (prev_symbol != nullptr && prev_symbol->len == 0) {
Yabin Cuicc2e59e2015-08-21 14:23:43 -0700323 prev_symbol->len = symbol.addr - prev_symbol->addr;
Yabin Cuic8485602015-08-20 15:04:39 -0700324 }
Yabin Cui3d4aa262017-11-01 15:58:55 -0700325 prev_symbol = &symbol;
Yabin Cui638c5582015-07-01 16:16:57 -0700326 }
Yabin Cui516a87c2018-03-26 17:34:00 -0700327}
328
329class ElfDso : public Dso {
330 public:
331 ElfDso(const std::string& path, const std::string& debug_file_path)
332 : Dso(DSO_ELF_FILE, path, debug_file_path),
333 min_vaddr_(std::numeric_limits<uint64_t>::max()) {}
334
335 uint64_t MinVirtualAddress() override {
336 if (min_vaddr_ == std::numeric_limits<uint64_t>::max()) {
337 min_vaddr_ = 0;
338 if (type_ == DSO_ELF_FILE) {
339 BuildId build_id = GetExpectedBuildId();
340
341 uint64_t addr;
342 ElfStatus result = ReadMinExecutableVirtualAddressFromElfFile(
343 GetDebugFilePath(), build_id, &addr);
344 if (result != ElfStatus::NO_ERROR) {
345 LOG(WARNING) << "failed to read min virtual address of "
346 << GetDebugFilePath() << ": " << result;
347 } else {
348 min_vaddr_ = addr;
349 }
350 }
351 }
352 return min_vaddr_;
Yabin Cuic8485602015-08-20 15:04:39 -0700353 }
Yabin Cui516a87c2018-03-26 17:34:00 -0700354
355 void SetMinVirtualAddress(uint64_t min_vaddr) override {
356 min_vaddr_ = min_vaddr;
357 }
358
359 protected:
360 std::vector<Symbol> LoadSymbols() override {
361 std::vector<Symbol> symbols;
362 BuildId build_id = GetExpectedBuildId();
363 auto symbol_callback = [&](const ElfFileSymbol& symbol) {
364 if (symbol.is_func || (symbol.is_label && symbol.is_in_text_section)) {
365 symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
366 }
367 };
368 ElfStatus status;
369 std::tuple<bool, std::string, std::string> tuple = SplitUrlInApk(debug_file_path_);
370 if (std::get<0>(tuple)) {
371 status = ParseSymbolsFromApkFile(std::get<1>(tuple), std::get<2>(tuple), build_id,
372 symbol_callback);
373 } else {
374 status = ParseSymbolsFromElfFile(debug_file_path_, build_id, symbol_callback);
375 }
376 ReportReadElfSymbolResult(status, path_, debug_file_path_,
377 symbols_.empty() ? android::base::WARNING : android::base::DEBUG);
378 SortAndFixSymbols(symbols);
379 return symbols;
380 }
381
382 private:
383 uint64_t min_vaddr_;
384};
385
386class KernelDso : public Dso {
387 public:
388 KernelDso(const std::string& path, const std::string& debug_file_path)
389 : Dso(DSO_KERNEL, path, debug_file_path) {}
390
391 protected:
392 std::vector<Symbol> LoadSymbols() override {
393 std::vector<Symbol> symbols;
394 BuildId build_id = GetExpectedBuildId();
395 if (!vmlinux_.empty()) {
396 auto symbol_callback = [&](const ElfFileSymbol& symbol) {
397 if (symbol.is_func) {
398 symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
399 }
400 };
401 ElfStatus status = ParseSymbolsFromElfFile(vmlinux_, build_id, symbol_callback);
402 ReportReadElfSymbolResult(status, path_, vmlinux_);
403 } else if (!kallsyms_.empty()) {
404 symbols = ReadSymbolsFromKallsyms(kallsyms_);
405 } else if (read_kernel_symbols_from_proc_ || !build_id.IsEmpty()) {
406 // Try /proc/kallsyms only when asked to do so, or when build id matches.
407 // Otherwise, it is likely to use /proc/kallsyms on host for perf.data recorded on device.
408 bool can_read_kallsyms = true;
409 if (!build_id.IsEmpty()) {
410 BuildId real_build_id;
411 if (!GetKernelBuildId(&real_build_id) || build_id != real_build_id) {
412 LOG(DEBUG) << "failed to read symbols from /proc/kallsyms: Build id mismatch";
413 can_read_kallsyms = false;
414 }
415 }
416 if (can_read_kallsyms) {
417 std::string kallsyms;
418 if (!android::base::ReadFileToString("/proc/kallsyms", &kallsyms)) {
419 LOG(DEBUG) << "failed to read /proc/kallsyms";
420 } else {
421 symbols = ReadSymbolsFromKallsyms(kallsyms);
422 }
423 }
424 }
425 SortAndFixSymbols(symbols);
426 if (!symbols.empty()) {
427 symbols.back().len = std::numeric_limits<uint64_t>::max() - symbols.back().addr;
428 }
429 return symbols;
430 }
431
432 private:
433 std::vector<Symbol> ReadSymbolsFromKallsyms(std::string& kallsyms) {
434 std::vector<Symbol> symbols;
435 auto symbol_callback = [&](const KernelSymbol& symbol) {
436 if (strchr("TtWw", symbol.type) && symbol.addr != 0u) {
437 symbols.emplace_back(symbol.name, symbol.addr, 0);
438 }
439 return false;
440 };
441 ProcessKernelSymbols(kallsyms, symbol_callback);
442 if (symbols.empty()) {
443 LOG(WARNING) << "Symbol addresses in /proc/kallsyms on device are all zero. "
444 "`echo 0 >/proc/sys/kernel/kptr_restrict` if possible.";
445 }
446 return symbols;
447 }
448};
449
450class KernelModuleDso : public Dso {
451 public:
452 KernelModuleDso(const std::string& path, const std::string& debug_file_path)
453 : Dso(DSO_KERNEL_MODULE, path, debug_file_path) {}
454
455 protected:
456 std::vector<Symbol> LoadSymbols() override {
457 std::vector<Symbol> symbols;
458 BuildId build_id = GetExpectedBuildId();
459 auto symbol_callback = [&](const ElfFileSymbol& symbol) {
460 if (symbol.is_func || symbol.is_in_text_section) {
461 symbols.emplace_back(symbol.name, symbol.vaddr, symbol.len);
462 }
463 };
464 ElfStatus status = ParseSymbolsFromElfFile(debug_file_path_, build_id, symbol_callback);
465 ReportReadElfSymbolResult(status, path_, debug_file_path_,
466 symbols_.empty() ? android::base::WARNING : android::base::DEBUG);
467 SortAndFixSymbols(symbols);
468 return symbols;
469 }
470};
471
472std::unique_ptr<Dso> Dso::CreateDso(DsoType dso_type, const std::string& dso_path,
473 bool force_64bit) {
Yabin Cui516a87c2018-03-26 17:34:00 -0700474 switch (dso_type) {
Yabin Cui40b70ff2018-04-09 14:06:08 -0700475 case DSO_ELF_FILE: {
476 BuildId build_id = FindExpectedBuildIdForPath(dso_path);
477 return std::unique_ptr<Dso>(new ElfDso(dso_path,
478 debug_elf_file_finder_.FindDebugFile(dso_path, force_64bit, build_id)));
479 }
Yabin Cui516a87c2018-03-26 17:34:00 -0700480 case DSO_KERNEL:
481 return std::unique_ptr<Dso>(new KernelDso(dso_path, dso_path));
482 case DSO_KERNEL_MODULE:
Yabin Cui40b70ff2018-04-09 14:06:08 -0700483 return std::unique_ptr<Dso>(new KernelModuleDso(dso_path, dso_path));
Yabin Cui516a87c2018-03-26 17:34:00 -0700484 case DSO_DEX_FILE:
Yabin Cui40b70ff2018-04-09 14:06:08 -0700485 return std::unique_ptr<Dso>(new DexFileDso(dso_path, dso_path));
Yabin Cui516a87c2018-03-26 17:34:00 -0700486 default:
487 LOG(FATAL) << "Unexpected dso_type " << static_cast<int>(dso_type);
488 }
489 return nullptr;
490}
491
492std::vector<Symbol> DexFileDso::LoadSymbols() {
493 std::vector<Symbol> symbols;
494 std::vector<DexFileSymbol> dex_file_symbols;
495 if (!ReadSymbolsFromDexFile(debug_file_path_, dex_file_offsets_, &dex_file_symbols)) {
496 android::base::LogSeverity level = symbols_.empty() ? android::base::WARNING
497 : android::base::DEBUG;
498 LOG(level) << "Failed to read symbols from " << debug_file_path_;
499 return symbols;
500 }
501 LOG(VERBOSE) << "Read symbols from " << debug_file_path_ << " successfully";
502 for (auto& symbol : dex_file_symbols) {
503 symbols.emplace_back(symbol.name, symbol.offset, symbol.len);
504 }
505 SortAndFixSymbols(symbols);
506 return symbols;
Yabin Cui638c5582015-07-01 16:16:57 -0700507}
Yabin Cui767dd172016-06-02 21:02:43 -0700508
509const char* DsoTypeToString(DsoType dso_type) {
510 switch (dso_type) {
511 case DSO_KERNEL:
512 return "dso_kernel";
513 case DSO_KERNEL_MODULE:
514 return "dso_kernel_module";
515 case DSO_ELF_FILE:
516 return "dso_elf_file";
Yabin Cui516a87c2018-03-26 17:34:00 -0700517 case DSO_DEX_FILE:
518 return "dso_dex_file";
Yabin Cui767dd172016-06-02 21:02:43 -0700519 default:
520 return "unknown";
521 }
522}
Yabin Cui40b70ff2018-04-09 14:06:08 -0700523
524bool GetBuildIdFromDsoPath(const std::string& dso_path, BuildId* build_id) {
525 auto tuple = SplitUrlInApk(dso_path);
526 ElfStatus result;
527 if (std::get<0>(tuple)) {
528 result = GetBuildIdFromApkFile(std::get<1>(tuple), std::get<2>(tuple), build_id);
529 } else {
530 result = GetBuildIdFromElfFile(dso_path, build_id);
531 }
532 return result == ElfStatus::NO_ERROR;
533}