simpleperf: inject: Add option to search binaries with filename
When --symdir is given, binaries are searched by build id.
This patch adds --allow-mismatched-build-id in the inject
cmd. When used, it searches binaries by filename and allows
missing or mismatched build ids. It also generates a message
to show the found binary. So users can check if that is correct.
Bug: 361638495
Test: run simpleperf_unit_test
Test: run simpleperf inject --allow-mismatched-build-id
Change-Id: I0c34eeca2b6cd6ec860d7ea97935b97933969b97
diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp
index 1380ada..15a269b 100644
--- a/simpleperf/dso.cpp
+++ b/simpleperf/dso.cpp
@@ -54,6 +54,7 @@
}
void DebugElfFileFinder::Reset() {
+ allow_mismatched_build_id_ = false;
vdso_64bit_.clear();
vdso_32bit_.clear();
symfs_dir_.clear();
@@ -113,8 +114,8 @@
}
}
-static bool CheckDebugFilePath(const std::string& path, BuildId& build_id,
- bool report_build_id_mismatch) {
+bool DebugElfFileFinder::CheckDebugFilePath(const std::string& path, BuildId& build_id,
+ bool report_build_id_mismatch) {
ElfStatus status;
auto elf = ElfFile::Open(path, &status);
if (!elf) {
@@ -126,6 +127,10 @@
return false;
}
+ if (allow_mismatched_build_id_) {
+ return true;
+ }
+
// Native libraries in apks and kernel modules may not have build ids.
// So build_id and debug_build_id can either be empty, or have the same value.
bool match = build_id == debug_build_id;
@@ -152,12 +157,18 @@
// 1. Try build_id_to_file_map.
if (!build_id_to_file_map_.empty()) {
- if (!build_id.IsEmpty() || GetBuildIdFromDsoPath(dso_path, &build_id)) {
+ if (!build_id.IsEmpty()) {
auto it = build_id_to_file_map_.find(build_id.ToString());
if (it != build_id_to_file_map_.end() && CheckDebugFilePath(it->second, build_id, false)) {
return it->second;
}
}
+ if (allow_mismatched_build_id_) {
+ std::optional<std::string> s = SearchFileMapByPath(dso_path);
+ if (s.has_value()) {
+ return s.value();
+ }
+ }
}
if (!symfs_dir_.empty()) {
// 2. Try concatenating symfs_dir and dso_path.
@@ -205,6 +216,39 @@
std::replace(elf_path.begin(), elf_path.end(), '/', OS_PATH_SEPARATOR);
return add_symfs_prefix(elf_path);
}
+
+std::optional<std::string> DebugElfFileFinder::SearchFileMapByPath(const std::string& path) {
+ std::string filename;
+ if (size_t pos = path.rfind('/'); pos != std::string::npos) {
+ filename = path.substr(pos + 1);
+ } else {
+ filename = path;
+ }
+ std::string best_elf_file;
+ size_t best_match_length = 0;
+ for (const auto& p : build_id_to_file_map_) {
+ const std::string& elf_file = p.second;
+ if (EndsWith(elf_file, filename)) {
+ size_t i = elf_file.size();
+ size_t j = path.size();
+ while (i > 0 && j > 0 && elf_file[i - 1] == path[j - 1]) {
+ i--;
+ j--;
+ }
+ size_t match_length = elf_file.size() - i;
+ if (match_length > best_match_length) {
+ best_elf_file = elf_file;
+ best_match_length = match_length;
+ }
+ }
+ }
+ if (!best_elf_file.empty()) {
+ LOG(INFO) << "Found " << best_elf_file << " for " << path << " by filename";
+ return best_elf_file;
+ }
+ return std::nullopt;
+}
+
} // namespace simpleperf_dso_impl
static OneTimeFreeAllocator symbol_name_allocator;
@@ -320,6 +364,10 @@
return debug_elf_file_finder_.AddSymbolDir(symbol_dir);
}
+void Dso::AllowMismatchedBuildId() {
+ return debug_elf_file_finder_.AllowMismatchedBuildId();
+}
+
void Dso::SetVmlinux(const std::string& vmlinux) {
vmlinux_ = vmlinux;
}