]
//
+// Static library for ELF symbolization.
+//
+// TODO: make this a proper part of simpleperf once that is moved to Soong.
+//
+
+cc_library_static {
+ name: "libperfprofd_elf_read",
+
+ export_include_dirs: [
+ "simpleperf",
+ ],
+
+ cflags: [
+ "-DSIMPLEPERF_REVISION=\"dummy\"",
+ ],
+
+ static_libs: [
+ "libbase",
+ ],
+ // Use whole-static to avoid having to pull this in later.
+ whole_static_libs: [
+ "libLLVMObject",
+ "libLLVMBitReader",
+ "libLLVMMC",
+ "libLLVMMCParser",
+ "libLLVMCore",
+ "libLLVMSupport",
+ "liblog",
+ "liblzma",
+ "libz",
+ "libziparchive",
+ ],
+
+ target: {
+ // Required for LLVM.
+ linux_glibc: {
+ host_ldlibs: [
+ "-lncurses",
+ ],
+ },
+ },
+
+ srcs: [
+ "simpleperf/read_apk.cpp",
+ "simpleperf/read_elf.cpp",
+ "simpleperf/utils.cpp",
+ ],
+
+ group_static_libs: true,
+}
+
+//
// Static library containing guts of AWP daemon.
//
local_include_dirs: ["quipper/kernel-headers"],
export_include_dirs: ["."],
- static_libs: ["libbase"],
+ static_libs: [
+ "libbase",
+ "libperfprofd_elf_read",
+ ],
srcs: [
"perf_profile.proto",
"quipper/perf_utils.cc",
"configreader.cc",
"cpuconfig.cc",
"perfprofdcore.cc",
+ "symbolizer.cc"
],
cflags: perfprofd_cflags,
"libperfprofdcore",
"libperfprofdutils",
"libperfprofd_binder",
+ "libperfprofd_elf_read",
],
shared_libs: [
"liblog",
bool collect_booting = true;
bool collect_camera_active = false;
+ // If true, use an ELF symbolizer to on-device symbolize.
+ bool use_elf_symbolizer = true;
+
// Sleep for the given number of seconds.
virtual void Sleep(size_t seconds) = 0;
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
-#include <string>
-#include <sstream>
+
+#include <cctype>
#include <map>
+#include <memory>
#include <set>
-#include <cctype>
+#include <sstream>
+#include <string>
#include <android-base/file.h>
#include <android-base/macros.h>
#include "perf_data_converter.h"
#include "cpuconfig.h"
#include "configreader.h"
+#include "symbolizer.h"
//
// Perf profiling daemon -- collects system-wide profiles using
//
std::string path = android::base::StringPrintf(
"%s.encoded.%d", data_file_path.c_str(), seq);
- return encode_to_proto(data_file_path, path.c_str(), config, cpu_utilization, nullptr);
+ std::unique_ptr<perfprofd::Symbolizer> symbolizer;
+ if (config.use_elf_symbolizer) {
+ symbolizer = perfprofd::CreateELFSymbolizer();
+ }
+ return encode_to_proto(data_file_path, path.c_str(), config, cpu_utilization, symbolizer.get());
}
//
--- /dev/null
+../simpleperf
\ No newline at end of file
--- /dev/null
+/*
+ *
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "symbolizer.h"
+
+#include <map>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+
+#include "build_id.h"
+#include "read_elf.h"
+
+namespace perfprofd {
+
+namespace {
+
+struct SimpleperfSymbolizer : public Symbolizer {
+ // For simplicity, we assume non-overlapping symbols.
+ struct Symbol {
+ std::string name;
+ uint64_t length;
+ };
+ using SymbolMap = std::map<uint64_t, Symbol>;
+
+ std::string Decode(const std::string& dso, uint64_t address) override {
+ auto it = dsos.find(dso);
+ if (it == dsos.end()) {
+ LoadDso(dso);
+ it = dsos.find(dso);
+ DCHECK(it != dsos.end());
+ }
+
+ const SymbolMap& map = it->second;
+ if (map.empty()) {
+ return "";
+ }
+ auto upper_bound = map.upper_bound(address);
+ if (upper_bound == map.begin()) {
+ // Nope, not in the map.
+ return "";
+ }
+
+ upper_bound--;
+ if (upper_bound->first + upper_bound->second.length > address) {
+ // This element covers the given address, return its name.
+ return upper_bound->second.name;
+ }
+
+ return "";
+ }
+
+ void LoadDso(const std::string& dso) {
+ SymbolMap data;
+ auto callback = [&data](const ElfFileSymbol& sym) {
+ Symbol symbol;
+ symbol.name = sym.name;
+ symbol.length = sym.len;
+ data.emplace(sym.vaddr, std::move(symbol));
+ };
+ ElfStatus status = ParseSymbolsFromElfFile(dso, BuildId(), callback);
+ if (status != ElfStatus::NO_ERROR) {
+ LOG(WARNING) << "Could not parse dso " << dso << ": " << status;
+ }
+ dsos.emplace(dso, std::move(data));
+ }
+
+ std::unordered_map<std::string, SymbolMap> dsos;
+};
+
+} // namespace
+
+std::unique_ptr<Symbolizer> CreateELFSymbolizer() {
+ return std::unique_ptr<Symbolizer>(new SimpleperfSymbolizer());
+}
+
+} // namespace perfprofd
+
#ifndef SYSTEM_EXTRAS_PERFPROFD_SYMBOLIZER_H_
#define SYSTEM_EXTRAS_PERFPROFD_SYMBOLIZER_H_
+#include <memory>
+
namespace perfprofd {
struct Symbolizer {
virtual std::string Decode(const std::string& dso, uint64_t address) = 0;
};
+std::unique_ptr<Symbolizer> CreateELFSymbolizer();
+
} // namespace perfprofd
#endif // SYSTEM_EXTRAS_PERFPROFD_SYMBOLIZER_H_
static_libs: [
"libperfprofdcore",
"libperfprofdmockutils",
+ "libperfprofd_elf_read",
"libbase",
],
shared_libs: [