summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--perfprofd/Android.bp62
-rw-r--r--perfprofd/binder_interface/perfprofd_binder.cc91
-rw-r--r--perfprofd/binder_interface/perfprofd_config.proto3
-rw-r--r--perfprofd/config.h3
-rw-r--r--perfprofd/configreader.cc4
-rw-r--r--perfprofd/cpuconfig.cc10
-rw-r--r--perfprofd/map_utils.h129
-rw-r--r--perfprofd/perf_data_converter.cc419
-rw-r--r--perfprofd/perf_data_converter.h14
-rw-r--r--perfprofd/perfprofd_io.cc310
-rw-r--r--perfprofd/perfprofd_io.h38
-rw-r--r--perfprofd/perfprofd_record-fwd.h27
-rw-r--r--perfprofd/perfprofd_record.proto59
-rw-r--r--perfprofd/perfprofdcore.cc75
-rw-r--r--perfprofd/perfprofdcore.h11
-rw-r--r--perfprofd/quipper/address_mapper.cc217
-rw-r--r--perfprofd/quipper/address_mapper.h128
-rw-r--r--perfprofd/quipper/base/basictypes.h58
-rw-r--r--perfprofd/quipper/base/compiler_specific.h208
-rw-r--r--perfprofd/quipper/base/logging.cc110
-rw-r--r--perfprofd/quipper/base/logging.h671
-rw-r--r--perfprofd/quipper/base/macros.h257
-rw-r--r--perfprofd/quipper/base/port.h48
-rw-r--r--perfprofd/quipper/build/build_config.h159
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/perf.h196
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/build-id.h25
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/event.h212
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/header.h121
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/bitops.h41
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/kernel/kernel.h79
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/types.h43
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/target.h52
-rw-r--r--perfprofd/quipper/kernel-headers/tools/perf/util/types.h38
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/perf.h236
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/build-id.h19
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/event.h263
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/header.h159
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/bitops.h158
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/kernel/kernel.h134
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/types.h29
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/target.h65
-rw-r--r--perfprofd/quipper/original-kernel-headers/tools/perf/util/types.h24
-rw-r--r--perfprofd/quipper/perf_internals.h77
-rw-r--r--perfprofd/quipper/perf_parser.cc591
-rw-r--r--perfprofd/quipper/perf_parser.h263
-rw-r--r--perfprofd/quipper/perf_reader.cc1708
-rw-r--r--perfprofd/quipper/perf_reader.h296
-rw-r--r--perfprofd/quipper/perf_utils.cc188
-rw-r--r--perfprofd/quipper/perf_utils.h112
-rw-r--r--perfprofd/quipper/quipper_string.h13
-rw-r--r--perfprofd/quipper/quipper_test.h10
-rw-r--r--perfprofd/quipper_helper.h146
-rw-r--r--perfprofd/symbolizer.cc5
-rw-r--r--perfprofd/symbolizer.h1
-rw-r--r--perfprofd/tests/Android.bp36
-rw-r--r--perfprofd/tests/perfprofd_test.cc684
-rw-r--r--simpleperf/Android.mk2
57 files changed, 1550 insertions, 7587 deletions
diff --git a/perfprofd/Android.bp b/perfprofd/Android.bp
index 2787dc69..351c7aab 100644
--- a/perfprofd/Android.bp
+++ b/perfprofd/Android.bp
@@ -41,41 +41,78 @@ cc_defaults {
],
}
+cc_defaults {
+ name: "perfprofd_debug_defaults",
+
+ cflags: [
+ "-O0",
+ "-g",
+ "-UNDEBUG",
+ ],
+}
+
//
// Static library containing guts of AWP daemon.
//
-cc_library_static {
- name: "libperfprofdcore",
+cc_defaults {
+ name: "libperfprofdcore_defaults",
defaults: [
"perfprofd_defaults",
],
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
- local_include_dirs: ["quipper/kernel-headers"],
- export_include_dirs: ["."],
static_libs: [
"libbase",
"libsimpleperf_elf_read",
],
+ whole_static_libs: [
+ "libquipper",
+ ],
srcs: [
- "perf_profile.proto",
- "quipper/perf_utils.cc",
- "quipper/base/logging.cc",
- "quipper/address_mapper.cc",
- "quipper/perf_reader.cc",
- "quipper/perf_parser.cc",
+ "perfprofd_record.proto",
"perf_data_converter.cc",
"configreader.cc",
"cpuconfig.cc",
"perfprofdcore.cc",
+ "perfprofd_io.cc",
"symbolizer.cc"
],
proto: {
export_proto_headers: true,
+ include_dirs: ["external/perf_data_converter/src/quipper"],
+ type: "lite",
},
+ cflags: [
+ "-Wno-gnu-anonymous-struct",
+ ],
+
+ export_include_dirs: ["."],
+}
+
+cc_library_static {
+ name: "libperfprofdcore",
+ defaults: [
+ "libperfprofdcore_defaults",
+ ],
}
+// Debug version.
+cc_library_static {
+ name: "libperfprofdcored",
+ defaults: [
+ "libperfprofdcore_defaults",
+ "perfprofd_debug_defaults",
+ ],
+}
+
+
//
// Main daemon
//
@@ -112,6 +149,11 @@ cc_binary {
enabled: false,
},
},
+
+ // We're technically independent, but ensure simpleperf is there.
+ required: [
+ "simpleperf",
+ ],
}
subdirs = [
diff --git a/perfprofd/binder_interface/perfprofd_binder.cc b/perfprofd/binder_interface/perfprofd_binder.cc
index 388dea61..eeb53602 100644
--- a/perfprofd/binder_interface/perfprofd_binder.cc
+++ b/perfprofd/binder_interface/perfprofd_binder.cc
@@ -19,6 +19,7 @@
#include <chrono>
#include <condition_variable>
+#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <memory>
@@ -30,8 +31,10 @@
#include <inttypes.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <android/os/DropBoxManager.h>
#include <binder/BinderService.h>
#include <binder/IResultReceiver.h>
@@ -43,10 +46,11 @@
#include "android/os/BnPerfProfd.h"
#include "perfprofd_config.pb.h"
-#include "perf_profile.pb.h"
+#include "perfprofd_record.pb.h"
#include "config.h"
#include "perfprofdcore.h"
+#include "perfprofd_io.h"
namespace android {
namespace perfprofd {
@@ -56,7 +60,7 @@ using Status = ::android::binder::Status;
class BinderConfig : public Config {
public:
- bool send_to_dropbox = true;
+ bool send_to_dropbox = false;
bool is_profiling = false;
@@ -129,7 +133,7 @@ class PerfProfdNativeService : public BinderService<PerfProfdNativeService>,
private:
// Handler for ProfilingLoop.
- bool BinderHandler(wireless_android_play_playlog::AndroidPerfProfile* encodedProfile,
+ bool BinderHandler(android::perfprofd::PerfprofdRecord* encodedProfile,
Config* config);
// Helper for the handler.
HandlerFn GetBinderHandler();
@@ -147,24 +151,77 @@ class PerfProfdNativeService : public BinderService<PerfProfdNativeService>,
int seq_ = 0;
};
+static Status WriteDropboxFile(android::perfprofd::PerfprofdRecord* encodedProfile,
+ Config* config) {
+ android::base::unique_fd tmp_fd;
+ {
+ char path[PATH_MAX];
+ snprintf(path,
+ sizeof(path),
+ "%s%cdropboxtmp-XXXXXX",
+ config->destination_directory.c_str(),
+ OS_PATH_SEPARATOR);
+ tmp_fd.reset(mkstemp(path));
+ if (tmp_fd.get() == -1) {
+ PLOG(ERROR) << "Could not create temp file " << path;
+ return Status::fromExceptionCode(1, "Could not create temp file");
+ }
+ if (unlink(path) != 0) {
+ PLOG(WARNING) << "Could not unlink binder temp file";
+ }
+ }
+
+ // Dropbox takes ownership of the fd, and if it is not readonly,
+ // a selinux violation will occur. Get a read-only version.
+ android::base::unique_fd read_only;
+ {
+ char fdpath[64];
+ snprintf(fdpath, arraysize(fdpath), "/proc/self/fd/%d", tmp_fd.get());
+ read_only.reset(open(fdpath, O_RDONLY | O_CLOEXEC));
+ if (read_only.get() < 0) {
+ PLOG(ERROR) << "Could not create read-only fd";
+ return Status::fromExceptionCode(1, "Could not create read-only fd");
+ }
+ }
+
+ constexpr bool kCompress = true; // Ignore the config here. Dropbox will always end up
+ // compressing the data, might as well make the temp
+ // file smaller and help it out.
+ using DropBoxManager = android::os::DropBoxManager;
+ constexpr int kDropboxFlags = DropBoxManager::IS_GZIPPED;
+
+ if (!SerializeProtobuf(encodedProfile, std::move(tmp_fd), kCompress)) {
+ return Status::fromExceptionCode(1, "Could not serialize to temp file");
+ }
+
+ sp<DropBoxManager> dropbox(new DropBoxManager());
+ return dropbox->addFile(String16("perfprofd"), read_only.release(), kDropboxFlags);
+}
+
bool PerfProfdNativeService::BinderHandler(
- wireless_android_play_playlog::AndroidPerfProfile* encodedProfile,
+ android::perfprofd::PerfprofdRecord* encodedProfile,
Config* config) {
CHECK(config != nullptr);
if (static_cast<BinderConfig*>(config)->send_to_dropbox) {
size_t size = encodedProfile->ByteSize();
- std::unique_ptr<uint8_t[]> data(new uint8_t[size]);
- encodedProfile->SerializeWithCachedSizesToArray(data.get());
-
- using DropBoxManager = android::os::DropBoxManager;
- sp<DropBoxManager> dropbox(new DropBoxManager());
- Status status = dropbox->addData(String16("perfprofd"),
- data.get(),
- size,
- 0);
+ Status status;
+ if (size < 1024 * 1024) {
+ // For a small size, send as a byte buffer directly.
+ std::unique_ptr<uint8_t[]> data(new uint8_t[size]);
+ encodedProfile->SerializeWithCachedSizesToArray(data.get());
+
+ using DropBoxManager = android::os::DropBoxManager;
+ sp<DropBoxManager> dropbox(new DropBoxManager());
+ status = dropbox->addData(String16("perfprofd"),
+ data.get(),
+ size,
+ 0);
+ } else {
+ // For larger buffers, we need to go through the filesystem.
+ status = WriteDropboxFile(encodedProfile, config);
+ }
if (!status.isOk()) {
- LOG(WARNING) << "Failed dropbox submission: " << status.exceptionCode()
- << " " << status.exceptionMessage().c_str();
+ LOG(WARNING) << "Failed dropbox submission: " << status.toString8();
}
return status.isOk();
}
@@ -175,8 +232,7 @@ bool PerfProfdNativeService::BinderHandler(
std::string data_file_path(config->destination_directory);
data_file_path += "/perf.data";
std::string path = android::base::StringPrintf("%s.encoded.%d", data_file_path.c_str(), seq_);
- PROFILE_RESULT result = SerializeProtobuf(encodedProfile, path.c_str());
- if (result != PROFILE_RESULT::OK_PROFILE_COLLECTION) {
+ if (!SerializeProtobuf(encodedProfile, path.c_str(), config->compress)) {
return false;
}
@@ -290,6 +346,7 @@ Status PerfProfdNativeService::StartProfilingProtobuf(ProtoLoaderFn fn) {
CHECK_AND_COPY_FROM_PROTO(process)
CHECK_AND_COPY_FROM_PROTO(use_elf_symbolizer)
CHECK_AND_COPY_FROM_PROTO(send_to_dropbox)
+ CHECK_AND_COPY_FROM_PROTO(compress)
#undef CHECK_AND_COPY_FROM_PROTO
};
return StartProfiling(config_fn);
diff --git a/perfprofd/binder_interface/perfprofd_config.proto b/perfprofd/binder_interface/perfprofd_config.proto
index bb7b52d8..c25aa93b 100644
--- a/perfprofd/binder_interface/perfprofd_config.proto
+++ b/perfprofd/binder_interface/perfprofd_config.proto
@@ -76,4 +76,7 @@ message ProfilingConfig {
// Whether to send the result to dropbox.
optional bool send_to_dropbox = 20;
+
+ // If true, use libz to compress the output proto.
+ optional bool compress = 21;
};
diff --git a/perfprofd/config.h b/perfprofd/config.h
index bbbcb3fc..4c1f12b1 100644
--- a/perfprofd/config.h
+++ b/perfprofd/config.h
@@ -93,6 +93,9 @@ struct Config {
// If true, use an ELF symbolizer to on-device symbolize.
bool use_elf_symbolizer = true;
+ // If true, use libz to compress the output proto.
+ bool compress = true;
+
// Sleep for the given number of seconds.
virtual void Sleep(size_t seconds) = 0;
diff --git a/perfprofd/configreader.cc b/perfprofd/configreader.cc
index f8fb3d6d..f7d6fd29 100644
--- a/perfprofd/configreader.cc
+++ b/perfprofd/configreader.cc
@@ -127,6 +127,9 @@ void ConfigReader::addDefaultEntries()
// If true, use an ELF symbolizer to on-device symbolize.
addUnsignedEntry("use_elf_symbolizer", 1, 0, 1);
+
+ // If true, use libz to compress the output proto.
+ addUnsignedEntry("compress", 0, 0, 1);
}
void ConfigReader::addUnsignedEntry(const char *key,
@@ -325,4 +328,5 @@ void ConfigReader::FillConfig(Config* config) {
config->process = -1;
config->use_elf_symbolizer = getBoolValue("use_elf_symbolizer");
+ config->compress = getBoolValue("compress");
}
diff --git a/perfprofd/cpuconfig.cc b/perfprofd/cpuconfig.cc
index 337da56e..0f23fd0f 100644
--- a/perfprofd/cpuconfig.cc
+++ b/perfprofd/cpuconfig.cc
@@ -25,7 +25,9 @@
#include <sys/wait.h>
#include <android-base/logging.h>
+#ifdef __BIONIC__
#include <android-base/properties.h>
+#endif
#include "cpuconfig.h"
@@ -53,7 +55,11 @@ HardwireCpuHelper::~HardwireCpuHelper()
bool HardwireCpuHelper::GetMpdecisionRunning()
{
+#ifdef __BIONIC__
return android::base::GetProperty("init.svc.mpdecision", "") == "running";
+#else
+ return false;
+#endif
}
@@ -87,17 +93,21 @@ void HardwireCpuHelper::OnlineCore(int i, int onoff)
void HardwireCpuHelper::StopMpdecision()
{
+#ifdef __BIONIC__
if (!android::base::SetProperty("ctl.stop", "mpdecision")) {
LOG(ERROR) << "setprop ctl.stop mpdecision failed";
}
+#endif
}
void HardwireCpuHelper::RestartMpdecision()
{
+#ifdef __BIONIC__
// Don't try to offline the cores we previously onlined -- let
// mpdecision figure out what to do
if (!android::base::SetProperty("ctl.start", "mpdecision")) {
LOG(ERROR) << "setprop ctl.start mpdecision failed";
}
+#endif
}
diff --git a/perfprofd/map_utils.h b/perfprofd/map_utils.h
new file mode 100644
index 00000000..2e3d97d9
--- /dev/null
+++ b/perfprofd/map_utils.h
@@ -0,0 +1,129 @@
+#ifndef SYSTEM_EXTRAS_PERFPROFD_MAP_UTILS_H_
+#define SYSTEM_EXTRAS_PERFPROFD_MAP_UTILS_H_
+
+#include <map>
+#include <set>
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace perfprofd {
+
+template <typename T, typename U>
+decltype(static_cast<T*>(nullptr)->begin()) GetLeqIterator(T& map, U key) {
+ if (map.empty()) {
+ return map.end();
+ }
+ auto it = map.upper_bound(key);
+ if (it == map.begin()) {
+ return map.end();
+ }
+ --it;
+ return it;
+}
+
+template <typename SymType, typename ValType>
+class RangeMap {
+ public:
+ struct AggregatedSymbol {
+ SymType symbol;
+ std::set<ValType> offsets;
+ AggregatedSymbol(const SymType& sym, const ValType& offset) : symbol(sym) {
+ offsets.insert(offset);
+ }
+ };
+
+ public:
+ void Insert(const SymType& sym, const ValType& val) {
+ auto aggr_it = GetLeqIterator(map_, val);
+ if (aggr_it == map_.end()) {
+ // Maybe we need to extend the first one.
+ if (!map_.empty()) {
+ AggregatedSymbol& first = map_.begin()->second;
+ CHECK_LT(val, map_.begin()->first);
+ if (first.symbol == sym) {
+ ExtendLeft(map_.begin(), val);
+ return;
+ }
+ }
+ // Nope, new entry needed.
+ map_.emplace(val, AggregatedSymbol(sym, val));
+ return;
+ }
+
+ AggregatedSymbol& maybe_match = aggr_it->second;
+
+ if (maybe_match.symbol == sym) {
+ // Same symbol, just insert. This is true for overlap as well as extension.
+ maybe_match.offsets.insert(val);
+ return;
+ }
+
+ // Is there overlap?
+ if (*maybe_match.offsets.rbegin() < val) {
+ // No. See if it can be merged with the next one.
+ ++aggr_it;
+ if (aggr_it != map_.end() && aggr_it->second.symbol == sym) {
+ ExtendLeft(aggr_it, val);
+ return;
+ }
+
+ // Just add a new symbol entry.
+ map_.emplace(val, AggregatedSymbol(sym, val));
+ return;
+ }
+
+ // OK, we have an overlapping non-symbol-equal AggregatedSymbol. Need to break
+ // things up.
+ AggregatedSymbol left(maybe_match.symbol, *maybe_match.offsets.begin());
+ auto offset_it = maybe_match.offsets.begin();
+ for (; *offset_it < val; ++offset_it) {
+ left.offsets.insert(*offset_it);
+ }
+
+ if (*offset_it == val) {
+ // This should not happen.
+ LOG(ERROR) << "Unexpected overlap!";
+ return;
+ }
+
+ AggregatedSymbol right(maybe_match.symbol, *offset_it);
+ for (; offset_it != maybe_match.offsets.end(); ++offset_it) {
+ right.offsets.insert(*offset_it);
+ }
+
+ map_.erase(aggr_it);
+ map_.emplace(*left.offsets.begin(), std::move(left));
+ map_.emplace(val, AggregatedSymbol(sym, val));
+ map_.emplace(*right.offsets.begin(), std::move(right));
+ }
+
+ using RangeMapType = std::map<ValType, AggregatedSymbol>;
+
+ typename RangeMapType::const_iterator begin() const {
+ return map_.begin();
+ }
+ typename RangeMapType::const_iterator end() const {
+ return map_.end();
+ }
+
+ bool empty() const {
+ return map_.empty();
+ }
+
+ private:
+ void ExtendLeft(typename RangeMapType::iterator it, const ValType& val) {
+ CHECK(val < *it->second.offsets.begin());
+ AggregatedSymbol copy = std::move(it->second);
+ map_.erase(it);
+ copy.offsets.insert(val);
+ map_.emplace(val, std::move(copy));
+ }
+
+ RangeMapType map_;
+};
+
+} // namespace perfprofd
+} // namespace android
+
+#endif // SYSTEM_EXTRAS_PERFPROFD_MAP_UTILS_H_
diff --git a/perfprofd/perf_data_converter.cc b/perfprofd/perf_data_converter.cc
index 9d35d337..f94cc861 100644
--- a/perfprofd/perf_data_converter.cc
+++ b/perfprofd/perf_data_converter.cc
@@ -4,330 +4,189 @@
#include <algorithm>
#include <limits>
#include <map>
+#include <memory>
+#include <set>
#include <unordered_map>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
#include <android-base/strings.h>
+#include <perf_data_utils.h>
+#include <perf_parser.h>
+#include <perf_protobuf_io.h>
-#include "perf_profile.pb.h"
+#include "perfprofd_record.pb.h"
+#include "perf_data.pb.h"
-#include "quipper/perf_parser.h"
+#include "map_utils.h"
+#include "quipper_helper.h"
#include "symbolizer.h"
using std::map;
-namespace wireless_android_logging_awp {
+namespace android {
+namespace perfprofd {
-// Flag to turn off symbolization, even if a symbolizer is given.
-static constexpr bool kUseSymbolizer = true;
+namespace {
-// If this flag is true, symbols will be computed on-device for all samples. If this
-// flag is false, this will only be done for modules without a build id (i.e., where
-// symbols cannot be derived in the cloud).
-//
-// This is turned off for now to conserve space.
-static constexpr bool kUseSymbolizerForModulesWithBuildId = false;
-
-typedef quipper::ParsedEvent::DSOAndOffset DSOAndOffset;
-typedef std::vector<DSOAndOffset> callchain;
+void AddSymbolInfo(PerfprofdRecord* record,
+ ::quipper::PerfParser& perf_parser,
+ ::perfprofd::Symbolizer* symbolizer) {
+ std::unordered_set<std::string> filenames_w_build_id;
+ for (auto& perf_build_id : record->perf_data().build_ids()) {
+ filenames_w_build_id.insert(perf_build_id.filename());
+ }
-struct callchain_lt {
- bool operator()(const callchain *c1, const callchain *c2) const {
- if (c1->size() != c2->size()) {
- return c1->size() < c2->size();
- }
- for (unsigned idx = 0; idx < c1->size(); ++idx) {
- const DSOAndOffset *do1 = &(*c1)[idx];
- const DSOAndOffset *do2 = &(*c2)[idx];
- if (do1->offset() != do2->offset()) {
- return do1->offset() < do2->offset();
+ std::unordered_set<std::string> files_wo_build_id;
+ {
+ quipper::MmapEventIterator it(record->perf_data());
+ for (; it != it.end(); ++it) {
+ const ::quipper::PerfDataProto_MMapEvent* mmap_event = &it->mmap_event();
+ if (!mmap_event->has_filename() || !mmap_event->has_start() || !mmap_event->has_len()) {
+ // Don't care.
+ continue;
}
- int rc = do1->dso_name().compare(do2->dso_name());
- if (rc) {
- return rc < 0;
+ if (filenames_w_build_id.count(mmap_event->filename()) == 0) {
+ files_wo_build_id.insert(mmap_event->filename());
}
}
- return false;
- }
-};
-
-struct RangeTarget {
- RangeTarget(uint64 start, uint64 end, uint64 to)
- : start(start), end(end), to(to) {}
-
- bool operator<(const RangeTarget &r) const {
- if (start != r.start) {
- return start < r.start;
- } else if (end != r.end) {
- return end < r.end;
- } else {
- return to < r.to;
- }
}
- uint64 start;
- uint64 end;
- uint64 to;
-};
-
-struct BinaryProfile {
- map<uint64, uint64> address_count_map;
- map<RangeTarget, uint64> range_count_map;
- map<const callchain *, uint64, callchain_lt> callchain_count_map;
-};
-
-wireless_android_play_playlog::AndroidPerfProfile*
-RawPerfDataToAndroidPerfProfile(const string &perf_file,
- ::perfprofd::Symbolizer* symbolizer) {
- quipper::PerfParser parser;
- if (!parser.ReadFile(perf_file) || !parser.ParseRawEvents()) {
- return nullptr;
+ if (files_wo_build_id.empty()) {
+ return;
}
- std::unique_ptr<wireless_android_play_playlog::AndroidPerfProfile> ret(
- new wireless_android_play_playlog::AndroidPerfProfile());
-
- using ModuleProfileMap = std::map<string, BinaryProfile>;
- using Program = std::pair<uint32_t /* index into process name table, or uint32_t max */,
- std::string /* program name = comm of thread */>;
- using ProgramProfileMap = std::map<Program, ModuleProfileMap>;
- struct ProcessNameTable {
- std::vector<std::string> names;
- std::unordered_map<std::string, uint32_t> index_lookup;
- };
- constexpr uint32_t kNoProcessNameTableEntry = std::numeric_limits<uint32_t>::max();
- ProcessNameTable process_name_table;
-
- // Note: the callchain_count_map member in BinaryProfile contains
- // pointers into callchains owned by "parser" above, meaning
- // that once the parser is destroyed, callchain pointers in
- // name_profile_map will become stale (e.g. keep these two
- // together in the same region).
- ProgramProfileMap name_profile_map;
- uint64 total_samples = 0;
- bool seen_branch_stack = false;
- bool seen_callchain = false;
-
- auto is_kernel_dso = [](const std::string& dso) {
- constexpr const char* kKernelDsos[] = {
- "[kernel.kallsyms]",
- "[vdso]",
- };
- for (auto kernel_dso : kKernelDsos) {
- if (dso == kernel_dso) {
- return true;
- }
+ struct Dso {
+ uint64_t min_vaddr;
+ RangeMap<std::string, uint64_t> symbols;
+ explicit Dso(uint64_t min_vaddr_in) : min_vaddr(min_vaddr_in) {
}
- return false;
};
-
- for (const auto &event : parser.parsed_events()) {
- if (!event.raw_event ||
- event.raw_event->header.type != PERF_RECORD_SAMPLE) {
+ std::unordered_map<std::string, Dso> files;
+
+ auto it = record->perf_data().events().begin();
+ auto end = record->perf_data().events().end();
+ auto parsed_it = perf_parser.parsed_events().begin();
+ auto parsed_end = perf_parser.parsed_events().end();
+ for (; it != end; ++it, ++parsed_it) {
+ CHECK(parsed_it != parsed_end);
+ if (!it->has_sample_event()) {
continue;
}
- string dso_name = event.dso_and_offset.dso_name();
- Program program_id;
- {
- std::string program_name = event.command();
- const std::string kernel_name = "[kernel.kallsyms]";
- if (android::base::StartsWith(dso_name, kernel_name)) {
- dso_name = kernel_name;
- if (program_name == "") {
- program_name = "kernel";
- }
- } else if (program_name == "") {
- if (is_kernel_dso(dso_name)) {
- program_name = "kernel";
- } else {
- program_name = "unknown_program";
- }
- }
- std::string process_name = event.process_command();
- uint32_t process_name_index = kNoProcessNameTableEntry;
- if (!process_name.empty()) {
- auto name_iter = process_name_table.index_lookup.find(process_name);
- if (name_iter == process_name_table.index_lookup.end()) {
- process_name_index = process_name_table.names.size();
- process_name_table.index_lookup.emplace(process_name, process_name_index);
- process_name_table.names.push_back(process_name);
- } else {
- process_name_index = name_iter->second;
- }
- }
- program_id = std::make_pair(process_name_index, program_name);
- }
- ModuleProfileMap& module_profile_map = name_profile_map[program_id];
-
- total_samples++;
- // We expect to see either all callchain events, all branch stack
- // events, or all flat sample events, not a mix. For callchains,
- // however, it can be the case that none of the IPs in a chain
- // are mappable, in which case the parsed/mapped chain will appear
- // empty (appearing as a flat sample).
- if (!event.callchain.empty()) {
- CHECK(!seen_branch_stack && "examining callchain");
- seen_callchain = true;
- const callchain *cc = &event.callchain;
- module_profile_map[dso_name].callchain_count_map[cc]++;
- } else if (!event.branch_stack.empty()) {
- CHECK(!seen_callchain && "examining branch stack");
- seen_branch_stack = true;
- module_profile_map[dso_name].address_count_map[
- event.dso_and_offset.offset()]++;
- } else {
- module_profile_map[dso_name].address_count_map[
- event.dso_and_offset.offset()]++;
- }
- for (size_t i = 1; i < event.branch_stack.size(); i++) {
- if (dso_name == event.branch_stack[i - 1].to.dso_name()) {
- uint64 start = event.branch_stack[i].to.offset();
- uint64 end = event.branch_stack[i - 1].from.offset();
- uint64 to = event.branch_stack[i - 1].to.offset();
- // The interval between two taken branches should not be too large.
- if (end < start || end - start > (1 << 20)) {
- LOG(WARNING) << "Bogus LBR data: " << start << "->" << end;
- continue;
- }
- module_profile_map[dso_name].range_count_map[
- RangeTarget(start, end, to)]++;
- }
- }
- }
-
- struct ModuleData {
- int index = 0;
- std::vector<std::string> symbols;
- std::unordered_map<uint64_t, size_t> addr_to_symbol_index;
+ const ::quipper::PerfDataProto_SampleEvent& sample_event = it->sample_event();
- wireless_android_play_playlog::LoadModule* module = nullptr;
- };
- map<string, ModuleData> name_data_map;
- for (const auto &program_profile : name_profile_map) {
- for (const auto &module_profile : program_profile.second) {
- name_data_map[module_profile.first] = ModuleData();
+ if (android::base::kEnableDChecks) {
+ // Check that the parsed_event and sample_event are consistent.
+ CHECK_EQ(parsed_it->callchain.size(), sample_event.callchain_size());
}
- }
- int current_index = 0;
- for (auto iter = name_data_map.begin(); iter != name_data_map.end(); ++iter) {
- iter->second.index = current_index++;
- }
- map<string, string> name_buildid_map;
- parser.GetFilenamesToBuildIDs(&name_buildid_map);
- ret->set_total_samples(total_samples);
-
- for (auto& name_data : name_data_map) {
- auto load_module = ret->add_load_modules();
- load_module->set_name(name_data.first);
- auto nbmi = name_buildid_map.find(name_data.first);
- bool has_build_id = nbmi != name_buildid_map.end();
- if (has_build_id) {
- const std::string &build_id = nbmi->second;
- if (build_id.size() == 40 && build_id.substr(32) == "00000000") {
- load_module->set_build_id(build_id.substr(0, 32));
- } else {
- load_module->set_build_id(build_id);
+ auto check_address = [&](const std::string& dso_name, uint64_t offset) {
+ if (files_wo_build_id.count(dso_name) == 0) {
+ return;
}
- }
- if (kUseSymbolizer && symbolizer != nullptr && !is_kernel_dso(name_data.first)) {
- if (kUseSymbolizerForModulesWithBuildId || !has_build_id) {
- // Add the module to signal that we'd want to add symbols.
- name_data.second.module = load_module;
- }
- }
- }
- auto symbolize = [symbolizer](ModuleData* module_data,
- const std::string& dso,
- uint64_t address) {
- if (module_data->module == nullptr) {
- return address;
- }
- auto it = module_data->addr_to_symbol_index.find(address);
- size_t index = std::numeric_limits<size_t>::max();
- if (it == module_data->addr_to_symbol_index.end()) {
- std::string symbol = symbolizer->Decode(dso, address);
- if (!symbol.empty()) {
- // Deduplicate symbols.
- auto it = std::find(module_data->symbols.begin(), module_data->symbols.end(), symbol);
- if (it == module_data->symbols.end()) {
- index = module_data->symbols.size();
- module_data->symbols.push_back(symbol);
+ // OK, that's a hit in the mmap segment (w/o build id).
+
+ Dso* dso_data;
+ {
+ auto dso_it = files.find(dso_name);
+ constexpr uint64_t kNoMinAddr = std::numeric_limits<uint64_t>::max();
+ if (dso_it == files.end()) {
+ uint64_t min_vaddr;
+ bool has_min_vaddr = symbolizer->GetMinExecutableVAddr(dso_name, &min_vaddr);
+ if (!has_min_vaddr) {
+ min_vaddr = kNoMinAddr;
+ }
+ auto it = files.emplace(dso_name, Dso(min_vaddr));
+ dso_data = &it.first->second;
} else {
- index = it - module_data->symbols.begin();
+ dso_data = &dso_it->second;
+ }
+ if (dso_data->min_vaddr == kNoMinAddr) {
+ return;
}
- module_data->addr_to_symbol_index.emplace(address, index);
}
- } else {
- index = it->second;
- }
- if (index != std::numeric_limits<size_t>::max()) {
- // Note: consider an actual entry in the proto? Maybe a oneof? But that
- // will be complicated with the separate repeated addr & module.
- address = std::numeric_limits<size_t>::max() - index;
- }
- return address;
- };
- for (const auto &program_profile : name_profile_map) {
- auto program = ret->add_programs();
- const Program& program_id = program_profile.first;
- program->set_name(program_id.second);
- if (program_id.first != kNoProcessNameTableEntry) {
- program->set_process_name_id(program_id.first);
- }
- for (const auto &module_profile : program_profile.second) {
- ModuleData& module_data = name_data_map[module_profile.first];
- int32 module_id = module_data.index;
- auto module = program->add_modules();
- module->set_load_module_id(module_id);
-
- // TODO: Templatize to avoid branch overhead?
- for (const auto &addr_count : module_profile.second.address_count_map) {
- auto address_samples = module->add_address_samples();
-
- uint64_t address = symbolize(&module_data, module_profile.first, addr_count.first);
- address_samples->add_address(address);
- address_samples->set_count(addr_count.second);
- }
- for (const auto &range_count : module_profile.second.range_count_map) {
- auto range_samples = module->add_range_samples();
- range_samples->set_start(range_count.first.start);
- range_samples->set_end(range_count.first.end);
- range_samples->set_to(range_count.first.to);
- range_samples->set_count(range_count.second);
+ // TODO: Is min_vaddr necessary here?
+ const uint64_t file_addr = offset;
+
+ std::string symbol = symbolizer->Decode(dso_name, file_addr);
+ if (symbol.empty()) {
+ return;
}
- for (const auto &callchain_count :
- module_profile.second.callchain_count_map) {
- auto address_samples = module->add_address_samples();
- address_samples->set_count(callchain_count.second);
- for (const auto &d_o : *callchain_count.first) {
- ModuleData& module_data = name_data_map[d_o.dso_name()];
- int32 module_id = module_data.index;
- address_samples->add_load_module_id(module_id);
- address_samples->add_address(symbolize(&module_data, d_o.dso_name(), d_o.offset()));
+
+ dso_data->symbols.Insert(symbol, file_addr);
+ };
+ if (sample_event.has_ip() && parsed_it->dso_and_offset.dso_info_ != nullptr) {
+ check_address(parsed_it->dso_and_offset.dso_info_->name, parsed_it->dso_and_offset.offset_);
+ }
+ if (sample_event.callchain_size() > 0) {
+ for (auto& callchain_data: parsed_it->callchain) {
+ if (callchain_data.dso_info_ == nullptr) {
+ continue;
}
+ check_address(callchain_data.dso_info_->name, callchain_data.offset_);
}
}
}
- for (auto& name_data : name_data_map) {
- auto load_module = name_data.second.module;
- if (load_module != nullptr) {
- for (const std::string& symbol : name_data.second.symbols) {
- load_module->add_symbol(symbol);
+ if (!files.empty()) {
+ // We have extra symbol info, create proto messages now.
+ for (auto& file_data : files) {
+ const std::string& filename = file_data.first;
+ const Dso& dso = file_data.second;
+ if (dso.symbols.empty()) {
+ continue;
+ }
+
+ PerfprofdRecord_SymbolInfo* symbol_info = record->add_symbol_info();
+ symbol_info->set_filename(filename);
+ symbol_info->set_filename_md5_prefix(::quipper::Md5Prefix(filename));
+ symbol_info->set_min_vaddr(dso.min_vaddr);
+ for (auto& aggr_sym : dso.symbols) {
+ PerfprofdRecord_SymbolInfo_Symbol* symbol = symbol_info->add_symbols();
+ symbol->set_addr(*aggr_sym.second.offsets.begin());
+ symbol->set_size(*aggr_sym.second.offsets.rbegin() - *aggr_sym.second.offsets.begin() + 1);
+ symbol->set_name(aggr_sym.second.symbol);
+ symbol->set_name_md5_prefix(::quipper::Md5Prefix(aggr_sym.second.symbol));
}
}
}
+}
- if (!process_name_table.names.empty()) {
- wireless_android_play_playlog::ProcessNames* process_names = ret->mutable_process_names();
- for (const std::string& name : process_name_table.names) {
- process_names->add_name(name);
- }
+} // namespace
+
+PerfprofdRecord*
+RawPerfDataToAndroidPerfProfile(const string &perf_file,
+ ::perfprofd::Symbolizer* symbolizer) {
+ std::unique_ptr<PerfprofdRecord> ret(new PerfprofdRecord());
+ ret->set_id(0); // TODO.
+
+ ::quipper::PerfParserOptions options = {};
+ options.do_remap = true;
+ options.discard_unused_events = true;
+ options.read_missing_buildids = true;
+
+ ::quipper::PerfDataProto* perf_data = ret->mutable_perf_data();
+
+ ::quipper::PerfReader reader;
+ if (!reader.ReadFile(perf_file)) return nullptr;
+
+ ::quipper::PerfParser parser(&reader, options);
+ if (!parser.ParseRawEvents()) return nullptr;
+
+ if (!reader.Serialize(perf_data)) return nullptr;
+
+ // Append parser stats to protobuf.
+ ::quipper::PerfSerializer::SerializeParserStats(parser.stats(), perf_data);
+
+ // TODO: Symbolization.
+ if (symbolizer != nullptr) {
+ AddSymbolInfo(ret.get(), parser, symbolizer);
}
return ret.release();
}
-} // namespace wireless_android_logging_awp
+} // namespace perfprofd
+} // namespace android
diff --git a/perfprofd/perf_data_converter.h b/perfprofd/perf_data_converter.h
index 5941a31e..3f05f9ec 100644
--- a/perfprofd/perf_data_converter.h
+++ b/perfprofd/perf_data_converter.h
@@ -3,20 +3,20 @@
#include <string>
+#include "perfprofd_record-fwd.h"
+
namespace perfprofd {
struct Symbolizer;
} // namespace perfprofd
-namespace wireless_android_play_playlog {
-class AndroidPerfProfile;
-} // namespace wireless_android_play_playlog
-
-namespace wireless_android_logging_awp {
+namespace android {
+namespace perfprofd {
-wireless_android_play_playlog::AndroidPerfProfile*
+PerfprofdRecord*
RawPerfDataToAndroidPerfProfile(const std::string &perf_file,
::perfprofd::Symbolizer* symbolizer);
-} // namespace wireless_android_logging_awp
+} // namespace perfprofd
+} // namespace android
#endif // WIRELESS_ANDROID_LOGGING_AWP_PERF_DATA_CONVERTER_H_
diff --git a/perfprofd/perfprofd_io.cc b/perfprofd/perfprofd_io.cc
new file mode 100644
index 00000000..d88cae4a
--- /dev/null
+++ b/perfprofd/perfprofd_io.cc
@@ -0,0 +1,310 @@
+/*
+**
+** Copyright 2015, 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 "perfprofd_io.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <zlib.h>
+
+#include "perfprofd_record.pb.h"
+
+namespace android {
+namespace perfprofd {
+
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::base::WriteFully;
+
+namespace {
+
+// Protobuf's file implementation is not available in protobuf-lite. :-(
+class FileCopyingOutputStream : public ::google::protobuf::io::CopyingOutputStream {
+ public:
+ explicit FileCopyingOutputStream(android::base::unique_fd&& fd_in) : fd_(std::move(fd_in)) {
+ };
+ bool Write(const void * buffer, int size) override {
+ return WriteFully(fd_.get(), buffer, size);
+ }
+
+ private:
+ android::base::unique_fd fd_;
+};
+
+using google::protobuf::io::ZeroCopyOutputStream;
+
+// Protobuf's Gzip implementation is not available in protobuf-lite. :-(
+class GzipOutputStream : public ZeroCopyOutputStream {
+ public:
+ ~GzipOutputStream();
+
+ static std::unique_ptr<GzipOutputStream> Create(ZeroCopyOutputStream* next,
+ std::string* error_msg);
+
+ bool Next(void** data, int* size) override;
+
+ void BackUp(int count) override;
+
+ google::protobuf::int64 ByteCount() const override;
+
+ bool WriteAliasedRaw(const void* data, int size) override;
+ bool AllowsAliasing() const override;
+
+ bool Flush();
+ bool Close();
+
+ private:
+ GzipOutputStream(ZeroCopyOutputStream* next, z_stream* stream);
+
+ int Write(int flush_flags);
+ bool NextBuffer();
+
+ ZeroCopyOutputStream* next_;
+ void* next_data_;
+ int next_size_;
+
+ z_stream* stream_;
+ std::unique_ptr<uint8_t[]> stream_buffer_;
+ bool had_error_;
+};
+
+constexpr size_t kStreamBufferSize = 16u * 1024u;
+
+GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* next, z_stream* stream)
+ : next_(next),
+ next_data_(nullptr),
+ next_size_(0),
+ stream_(stream),
+ stream_buffer_(nullptr),
+ had_error_(false) {
+}
+
+GzipOutputStream::~GzipOutputStream() {
+ if (stream_ != nullptr) {
+ deflateEnd(stream_);
+ delete stream_;
+ stream_ = nullptr;
+ }
+}
+
+bool GzipOutputStream::WriteAliasedRaw(const void* data ATTRIBUTE_UNUSED,
+ int size ATTRIBUTE_UNUSED) {
+ LOG(FATAL) << "Not supported";
+ __builtin_unreachable();
+}
+bool GzipOutputStream::AllowsAliasing() const {
+ return false;
+}
+
+google::protobuf::int64 GzipOutputStream::ByteCount() const {
+ return stream_->total_in + stream_->avail_in;
+}
+
+std::unique_ptr<GzipOutputStream> GzipOutputStream::Create(ZeroCopyOutputStream* next,
+ std::string* error_msg) {
+ std::unique_ptr<z_stream> stream(new z_stream);
+
+ stream->zalloc = Z_NULL;
+ stream->zfree = Z_NULL;
+ stream->opaque = Z_NULL;
+ stream->msg = nullptr;
+ stream->avail_in = 0;
+ stream->total_in = 0;
+ stream->next_in = nullptr;
+ stream->total_out = 0;
+
+ {
+ constexpr int kWindowBits = 15;
+ constexpr int kGzipEncoding = 16;
+ constexpr int kMemLevel = 8; // Default.
+ int init_result = deflateInit2(stream.get(),
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ kWindowBits | kGzipEncoding,
+ kMemLevel,
+ Z_DEFAULT_STRATEGY);
+ if (init_result != Z_OK) {
+ *error_msg = StringPrintf("Could not initialize compression: %d (%s)",
+ init_result,
+ stream->msg != nullptr ? stream->msg : "no message");
+ return nullptr;
+ }
+ }
+
+ return std::unique_ptr<GzipOutputStream>(new GzipOutputStream(next, stream.release()));
+}
+
+bool GzipOutputStream::NextBuffer() {
+ for (;;) {
+ if (!next_->Next(&next_data_, &next_size_)) {
+ next_data_ = nullptr;
+ next_size_ = 0;
+ return false;
+ }
+ if (next_size_ == 0) {
+ continue;
+ }
+ stream_->next_out = static_cast<Bytef*>(next_data_);
+ stream_->avail_out = next_size_;
+ return true;
+ }
+}
+
+int GzipOutputStream::Write(int flush_flags) {
+ CHECK(flush_flags == Z_NO_FLUSH || flush_flags == Z_FULL_FLUSH || flush_flags == Z_FINISH);
+
+ int res;
+ do {
+ if ((next_data_ == nullptr || stream_->avail_out == 0) && !NextBuffer()) {
+ return Z_BUF_ERROR;
+ }
+ res = deflate(stream_, flush_flags);
+ } while (res == Z_OK && stream_->avail_out == 0);
+
+ if (flush_flags == Z_FULL_FLUSH || flush_flags == Z_FINISH) {
+ next_->BackUp(stream_->avail_out);
+ next_data_ = nullptr;
+ next_size_ = 0;
+ }
+
+ return res;
+}
+
+bool GzipOutputStream::Next(void** data, int* size) {
+ if (had_error_) {
+ return false;
+ }
+
+ // Write all pending data.
+ if (stream_->avail_in > 0) {
+ int write_error = Write(Z_NO_FLUSH);
+ if (write_error != Z_OK) {
+ had_error_ = true;
+ return false;
+ }
+ CHECK_EQ(stream_->avail_in, 0);
+ }
+
+ if (stream_buffer_ == nullptr) {
+ stream_buffer_.reset(new uint8_t[kStreamBufferSize]);
+ }
+
+ stream_->next_in = static_cast<Bytef*>(stream_buffer_.get());
+ stream_->avail_in = kStreamBufferSize;
+ *data = stream_buffer_.get();
+ *size = kStreamBufferSize;
+ return true;
+}
+
+void GzipOutputStream::BackUp(int count) {
+ CHECK_GE(stream_->avail_in, count);
+ stream_->avail_in -= count;
+}
+
+bool GzipOutputStream::Flush() {
+ if (had_error_) {
+ return false;
+ }
+
+ int res = Write(Z_FULL_FLUSH);
+ had_error_ |= (res != Z_OK)
+ && !(res == Z_BUF_ERROR && stream_->avail_in == 0 && stream_->avail_out > 0);
+ return !had_error_;
+}
+
+bool GzipOutputStream::Close() {
+ if (had_error_) {
+ return false;
+ }
+
+ {
+ int res;
+ do {
+ res = Write(Z_FINISH);
+ } while (res == Z_OK);
+ }
+
+ int res = deflateEnd(stream_);
+ delete stream_;
+ stream_ = nullptr;
+
+ had_error_ = true; // Pretend an error so no other operations succeed.
+
+ return res == Z_OK;
+}
+
+} // namespace
+
+bool SerializeProtobuf(android::perfprofd::PerfprofdRecord* encodedProfile,
+ android::base::unique_fd&& fd,
+ bool compress) {
+ FileCopyingOutputStream fcos(std::move(fd));
+ google::protobuf::io::CopyingOutputStreamAdaptor cosa(&fcos);
+
+ ZeroCopyOutputStream* out;
+
+ std::unique_ptr<GzipOutputStream> gzip;
+ if (compress) {
+ std::string error_msg;
+ gzip = GzipOutputStream::Create(&cosa, &error_msg);
+ if (gzip == nullptr) {
+ LOG(ERROR) << error_msg;
+ return false;
+ }
+ out = gzip.get();
+ } else {
+ out = &cosa;
+ }
+
+ bool serialized = encodedProfile->SerializeToZeroCopyStream(out);
+ if (!serialized) {
+ LOG(WARNING) << "SerializeToZeroCopyStream failed";
+ return false;
+ }
+
+ bool zip_ok = true;
+ if (gzip != nullptr) {
+ zip_ok = gzip->Flush();
+ zip_ok = gzip->Close() && zip_ok;
+ }
+ cosa.Flush();
+ return zip_ok;
+}
+
+bool SerializeProtobuf(PerfprofdRecord* encodedProfile,
+ const char* encoded_file_path,
+ bool compress) {
+ unlink(encoded_file_path); // Attempt to unlink for a clean slate.
+ constexpr int kFlags = O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC;
+ unique_fd fd(open(encoded_file_path, kFlags, 0664));
+ if (fd.get() == -1) {
+ PLOG(WARNING) << "Could not open " << encoded_file_path << " for serialization";
+ return false;
+ }
+ return SerializeProtobuf(encodedProfile, std::move(fd), compress);
+}
+
+} // namespace perfprofd
+} // namespace android
diff --git a/perfprofd/perfprofd_io.h b/perfprofd/perfprofd_io.h
new file mode 100644
index 00000000..3e754b54
--- /dev/null
+++ b/perfprofd/perfprofd_io.h
@@ -0,0 +1,38 @@
+/*
+**
+** 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.
+*/
+
+#ifndef SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_IO_H_
+#define SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_IO_H_
+
+#include <android-base/unique_fd.h>
+
+#include "perfprofd_record-fwd.h"
+
+namespace android {
+namespace perfprofd {
+
+bool SerializeProtobuf(android::perfprofd::PerfprofdRecord* encodedProfile,
+ const char* encoded_file_path,
+ bool compress = true);
+bool SerializeProtobuf(android::perfprofd::PerfprofdRecord* encodedProfile,
+ android::base::unique_fd&& fd,
+ bool compress = true);
+
+} // namespace perfprofd
+} // namespace android
+
+#endif
diff --git a/perfprofd/perfprofd_record-fwd.h b/perfprofd/perfprofd_record-fwd.h
new file mode 100644
index 00000000..000ccecb
--- /dev/null
+++ b/perfprofd/perfprofd_record-fwd.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ */
+
+#ifndef SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_RECORD_FWD_H_
+#define SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_RECORD_FWD_H_
+
+namespace android {
+namespace perfprofd {
+class PerfprofdRecord;
+} // namespace perfprofd
+} // namespace android
+
+#endif // SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_RECORD_FWD_H_
diff --git a/perfprofd/perfprofd_record.proto b/perfprofd/perfprofd_record.proto
new file mode 100644
index 00000000..08b5fa2b
--- /dev/null
+++ b/perfprofd/perfprofd_record.proto
@@ -0,0 +1,59 @@
+
+syntax = "proto2";
+
+import "perf_data.proto";
+
+option java_package = "com.google.android.perfprofd";
+
+package android.perfprofd;
+
+message PerfprofdRecord {
+ // Symbol info for a shared library without build id.
+ message SymbolInfo {
+ // A symbol, stretching the given range of the library.
+ message Symbol {
+ optional string name = 1;
+ optional uint64 name_md5_prefix = 2;
+
+ optional uint64 addr = 3;
+ optional uint64 size = 4;
+ };
+
+ optional string filename = 1;
+ optional uint64 filename_md5_prefix = 2;
+
+ optional uint64 min_vaddr = 3;
+
+ repeated Symbol symbols = 4;
+ };
+
+ optional int64 id = 1;
+ optional quipper.PerfDataProto perf_data = 2;
+
+ // Extra symbol info.
+ repeated SymbolInfo symbol_info = 3;
+
+ // Stats inherited from old perf_profile.proto.
+
+ // is device screen on at point when profile is collected?
+ optional bool display_on = 5;
+
+ // system load at point when profile is collected; corresponds
+ // to first value from /proc/loadavg multiplied by 100 then
+ // converted to int32
+ optional int32 sys_load_average = 6;
+
+ // At the point when the profile was collected, was a camera active?
+ optional bool camera_active = 7;
+
+ // At the point when the profile was collected, was the device still booting?
+ optional bool booting = 8;
+
+ // At the point when the profile was collected, was the device plugged into
+ // a charger?
+ optional bool on_charger = 9;
+
+ // CPU utilization measured prior to profile collection (expressed as
+ // 100 minus the idle percentage).
+ optional int32 cpu_utilization = 10;
+};
diff --git a/perfprofd/perfprofdcore.cc b/perfprofd/perfprofdcore.cc
index 69a8a75f..4fa666d3 100644
--- a/perfprofd/perfprofdcore.cc
+++ b/perfprofd/perfprofdcore.cc
@@ -39,16 +39,20 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
-#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
-#include "perf_profile.pb.h"
+#ifdef __BIONIC__
+#include <android-base/properties.h>
+#endif
+
+#include "perfprofd_record.pb.h"
-#include "perfprofdcore.h"
-#include "perf_data_converter.h"
-#include "cpuconfig.h"
#include "configreader.h"
+#include "cpuconfig.h"
+#include "perf_data_converter.h"
+#include "perfprofdcore.h"
+#include "perfprofd_io.h"
#include "symbolizer.h"
//
@@ -61,6 +65,8 @@
//......................................................................
+using ProtoUniquePtr = std::unique_ptr<android::perfprofd::PerfprofdRecord>;
+
//
// Output file from 'perf record'.
//
@@ -231,7 +237,11 @@ static CKPROFILE_RESULT check_profiling_enabled(const Config& config)
bool get_booting()
{
+#ifdef __BIONIC__
return android::base::GetBoolProperty("sys.boot_completed", false) != true;
+#else
+ return false;
+#endif
}
//
@@ -416,7 +426,7 @@ unsigned collect_cpu_utilization()
return busy_delta * 100 / total_delta;
}
-static void annotate_encoded_perf_profile(wireless_android_play_playlog::AndroidPerfProfile *profile,
+static void annotate_encoded_perf_profile(android::perfprofd::PerfprofdRecord* profile,
const Config& config,
unsigned cpu_utilization)
{
@@ -468,7 +478,6 @@ static void annotate_encoded_perf_profile(wireless_android_play_playlog::Android
}
}
-using ProtoUniquePtr = std::unique_ptr<wireless_android_play_playlog::AndroidPerfProfile>;
static ProtoUniquePtr encode_to_proto(const std::string &data_file_path,
const Config& config,
unsigned cpu_utilization,
@@ -477,7 +486,7 @@ static ProtoUniquePtr encode_to_proto(const std::string &data_file_path,
// Open and read perf.data file
//
ProtoUniquePtr encodedProfile(
- wireless_android_logging_awp::RawPerfDataToAndroidPerfProfile(data_file_path, symbolizer));
+ android::perfprofd::RawPerfDataToAndroidPerfProfile(data_file_path, symbolizer));
if (encodedProfile == nullptr) {
return nullptr;
}
@@ -489,33 +498,6 @@ static ProtoUniquePtr encode_to_proto(const std::string &data_file_path,
return encodedProfile;
}
-PROFILE_RESULT SerializeProtobuf(wireless_android_play_playlog::AndroidPerfProfile* encodedProfile,
- const char* encoded_file_path) {
- //
- // Serialize protobuf to array
- //
- size_t size = encodedProfile->ByteSize();
- std::unique_ptr<uint8_t[]> data(new uint8_t[size]);
- encodedProfile->SerializeWithCachedSizesToArray(data.get());
-
- //
- // Open file and write encoded data to it
- //
- unlink(encoded_file_path); // Attempt to unlink for a clean slate.
- constexpr int kFlags = O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC;
- android::base::unique_fd fd(open(encoded_file_path, kFlags, 0664));
- if (fd.get() == -1) {
- PLOG(WARNING) << "Could not open " << encoded_file_path << " for serialization";
- return ERR_OPEN_ENCODED_FILE_FAILED;
- }
- if (!android::base::WriteFully(fd.get(), data.get(), size)) {
- PLOG(WARNING) << "Could not write to " << encoded_file_path;
- return ERR_WRITE_ENCODED_FILE_FAILED;
- }
-
- return OK_PROFILE_COLLECTION;
-}
-
PROFILE_RESULT encode_to_proto(const std::string &data_file_path,
const char *encoded_file_path,
const Config& config,
@@ -530,11 +512,15 @@ PROFILE_RESULT encode_to_proto(const std::string &data_file_path,
//
// Issue error if no samples
//
- if (encodedProfile == nullptr || encodedProfile->programs().size() == 0) {
+ if (encodedProfile == nullptr || encodedProfile->perf_data().events_size() == 0) {
return ERR_PERF_ENCODE_FAILED;
}
- return SerializeProtobuf(encodedProfile.get(), encoded_file_path);
+ return android::perfprofd::SerializeProtobuf(encodedProfile.get(),
+ encoded_file_path,
+ config.compress)
+ ? OK_PROFILE_COLLECTION
+ : ERR_WRITE_ENCODED_FILE_FAILED;
}
//
@@ -851,7 +837,11 @@ static void set_seed(uint32_t use_fixed_seed)
//
// Randomized seed
//
+#ifdef __BIONIC__
seed = arc4random();
+#else
+ seed = 12345678u;
+#endif
}
LOG(INFO) << "random seed set to " << seed;
// Distribute the 32-bit seed into the three 16-bit array
@@ -877,8 +867,13 @@ static void CommonInit(uint32_t use_fixed_seed, const char* dest_dir) {
cleanup_destination_dir(dest_dir);
}
+#ifdef __BIONIC__
running_in_emulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
is_debug_build = android::base::GetBoolProperty("ro.debuggable", false);
+#else
+ running_in_emulator = false;
+ is_debug_build = true;
+#endif
}
//
@@ -1008,8 +1003,7 @@ int perfprofd_main(int argc, char** argv, Config* config)
config_reader.FillConfig(config);
};
int seq = 0;
- auto handler = [&seq](wireless_android_play_playlog::AndroidPerfProfile* proto,
- Config* handler_config) {
+ auto handler = [&seq](android::perfprofd::PerfprofdRecord* proto, Config* handler_config) {
if (proto == nullptr) {
return false;
}
@@ -1017,8 +1011,7 @@ int perfprofd_main(int argc, char** argv, Config* config)
data_file_path += "/";
data_file_path += PERF_OUTPUT;
std::string path = android::base::StringPrintf("%s.encoded.%d", data_file_path.c_str(), seq);
- PROFILE_RESULT result = SerializeProtobuf(proto, path.c_str());
- if (result != PROFILE_RESULT::OK_PROFILE_COLLECTION) {
+ if (!android::perfprofd::SerializeProtobuf(proto, path.c_str(), handler_config->compress)) {
return false;
}
diff --git a/perfprofd/perfprofdcore.h b/perfprofd/perfprofdcore.h
index 6ea24ab1..73a9c567 100644
--- a/perfprofd/perfprofdcore.h
+++ b/perfprofd/perfprofdcore.h
@@ -21,11 +21,9 @@
#include <functional>
#include <memory>
-struct Config;
+#include "perfprofd_record-fwd.h"
-namespace wireless_android_play_playlog {
-class AndroidPerfProfile;
-}
+struct Config;
namespace perfprofd {
struct Symbolizer;
@@ -84,10 +82,7 @@ PROFILE_RESULT encode_to_proto(const std::string &data_file_path,
unsigned cpu_utilization,
perfprofd::Symbolizer* symbolizer);
-PROFILE_RESULT SerializeProtobuf(wireless_android_play_playlog::AndroidPerfProfile* encodedProfile,
- const char* encoded_file_path);
-
-using HandlerFn = std::function<bool(wireless_android_play_playlog::AndroidPerfProfile* proto,
+using HandlerFn = std::function<bool(android::perfprofd::PerfprofdRecord* proto,
Config* config)>;
void ProfilingLoop(Config& config, HandlerFn handler);
diff --git a/perfprofd/quipper/address_mapper.cc b/perfprofd/quipper/address_mapper.cc
deleted file mode 100644
index 70a2e5e9..00000000
--- a/perfprofd/quipper/address_mapper.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "address_mapper.h"
-
-#include "base/logging.h"
-
-namespace quipper {
-
-AddressMapper::AddressMapper(const AddressMapper& source) {
- mappings_ = source.mappings_;
-}
-
-bool AddressMapper::Map(const uint64_t real_addr,
- const uint64_t size,
- const bool remove_existing_mappings) {
- return MapWithID(real_addr, size, kuint64max, 0, remove_existing_mappings);
-}
-
-bool AddressMapper::MapWithID(const uint64_t real_addr,
- const uint64_t size,
- const uint64_t id,
- const uint64_t offset_base,
- bool remove_existing_mappings) {
- MappedRange range;
- range.real_addr = real_addr;
- range.size = size;
- range.id = id;
- range.offset_base = offset_base;
-
- if (size == 0) {
- LOG(ERROR) << "Must allocate a nonzero-length address range.";
- return false;
- }
-
- // Check that this mapping does not overflow the address space.
- if (real_addr + size - 1 != kuint64max &&
- !(real_addr + size > real_addr)) {
- DumpToLog();
- LOG(ERROR) << "Address mapping at " << std::hex << real_addr
- << " with size " << std::hex << size << " overflows.";
- return false;
- }
-
- // Check for collision with an existing mapping. This must be an overlap that
- // does not result in one range being completely covered by another
- MappingList::iterator iter;
- MappingList mappings_to_delete;
- bool old_range_found = false;
- MappedRange old_range;
- for (iter = mappings_.begin(); iter != mappings_.end(); ++iter) {
- if (!iter->Intersects(range))
- continue;
- // Quit if existing ranges that collide aren't supposed to be removed.
- if (!remove_existing_mappings)
- return false;
- if (!old_range_found && iter->Covers(range) && iter->size > range.size) {
- old_range_found = true;
- old_range = *iter;
- continue;
- }
- mappings_to_delete.push_back(*iter);
- }
-
- while (!mappings_to_delete.empty()) {
- const MappedRange& range = mappings_to_delete.front();
- CHECK(Unmap(range));
- mappings_to_delete.pop_front();
- }
-
- // Otherwise check for this range being covered by another range. If that
- // happens, split or reduce the existing range to make room.
- if (old_range_found) {
- CHECK(Unmap(old_range));
-
- uint64_t gap_before = range.real_addr - old_range.real_addr;
- uint64_t gap_after = (old_range.real_addr + old_range.size) -
- (range.real_addr + range.size);
-
- if (gap_before) {
- CHECK(MapWithID(old_range.real_addr,
- gap_before,
- old_range.id,
- old_range.offset_base,
- false));
- }
-
- CHECK(MapWithID(range.real_addr, range.size, id, offset_base, false));
-
- if (gap_after) {
- CHECK(MapWithID(range.real_addr + range.size,
- gap_after,
- old_range.id,
- old_range.offset_base + gap_before + range.size,
- false));
- }
-
- return true;
- }
-
- // Now search for a location for the new range. It should be in the first
- // free block in quipper space.
-
- // If there is no existing mapping, add it to the beginning of quipper space.
- if (mappings_.empty()) {
- range.mapped_addr = 0;
- range.unmapped_space_after = kuint64max - range.size;
- mappings_.push_back(range);
- return true;
- }
-
- // If there is space before the first mapped range in quipper space, use it.
- if (mappings_.begin()->mapped_addr >= range.size) {
- range.mapped_addr = 0;
- range.unmapped_space_after = mappings_.begin()->mapped_addr - range.size;
- mappings_.push_front(range);
- return true;
- }
-
- // Otherwise, search through the existing mappings for a free block after one
- // of them.
- for (iter = mappings_.begin(); iter != mappings_.end(); ++iter) {
- if (iter->unmapped_space_after < range.size)
- continue;
-
- range.mapped_addr = iter->mapped_addr + iter->size;
- range.unmapped_space_after = iter->unmapped_space_after - range.size;
- iter->unmapped_space_after = 0;
-
- mappings_.insert(++iter, range);
- return true;
- }
-
- // If it still hasn't succeeded in mapping, it means there is no free space in
- // quipper space large enough for a mapping of this size.
- DumpToLog();
- LOG(ERROR) << "Could not find space to map addr=" << std::hex << real_addr
- << " with size " << std::hex << size;
- return false;
-}
-
-void AddressMapper::DumpToLog() const {
- MappingList::const_iterator it;
- for (it = mappings_.begin(); it != mappings_.end(); ++it) {
- LOG(INFO) << " real_addr: " << std::hex << it->real_addr
- << " mapped: " << std::hex << it->mapped_addr
- << " id: " << std::hex << it->id
- << " size: " << std::hex << it->size;
- }
-}
-
-bool AddressMapper::GetMappedAddress(const uint64_t real_addr,
- uint64_t* mapped_addr) const {
- CHECK(mapped_addr);
- MappingList::const_iterator iter;
- for (iter = mappings_.begin(); iter != mappings_.end(); ++iter) {
- if (!iter->ContainsAddress(real_addr))
- continue;
- *mapped_addr = iter->mapped_addr + real_addr - iter->real_addr;
- return true;
- }
- return false;
-}
-
-bool AddressMapper::GetMappedIDAndOffset(const uint64_t real_addr,
- uint64_t* id,
- uint64_t* offset) const {
- CHECK(id);
- CHECK(offset);
- MappingList::const_iterator iter;
- for (iter = mappings_.begin(); iter != mappings_.end(); ++iter) {
- if (!iter->ContainsAddress(real_addr))
- continue;
- *id = iter->id;
- *offset = real_addr - iter->real_addr + iter->offset_base;
- return true;
- }
- return false;
-}
-
-uint64_t AddressMapper::GetMaxMappedLength() const {
- if (IsEmpty())
- return 0;
-
- uint64_t min = mappings_.begin()->mapped_addr;
-
- MappingList::const_iterator iter = mappings_.end();
- --iter;
- uint64_t max = iter->mapped_addr + iter->size;
-
- return max - min;
-}
-
-bool AddressMapper::Unmap(const MappedRange& range) {
- MappingList::iterator iter;
- // TODO(sque): this is highly inefficient since Unmap() is called from a
- // function that has already iterated to the right place within |mappings_|.
- // For a first revision, I am sacrificing efficiency for of clarity, due to
- // the trickiness of removing elements using iterators.
- for (iter = mappings_.begin(); iter != mappings_.end(); ++iter) {
- if (range.real_addr == iter->real_addr && range.size == iter->size) {
- // Add the freed up space to the free space counter of the previous
- // mapped region, if it exists.
- if (iter != mappings_.begin()) {
- --iter;
- iter->unmapped_space_after += range.size + range.unmapped_space_after;
- ++iter;
- }
- mappings_.erase(iter);
- return true;
- }
- }
- return false;
-}
-
-} // namespace quipper
diff --git a/perfprofd/quipper/address_mapper.h b/perfprofd/quipper/address_mapper.h
deleted file mode 100644
index ef2d6d21..00000000
--- a/perfprofd/quipper/address_mapper.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMIUMOS_WIDE_PROFILING_ADDRESS_MAPPER_H_
-#define CHROMIUMOS_WIDE_PROFILING_ADDRESS_MAPPER_H_
-
-#include <stdint.h>
-
-#include <list>
-
-namespace quipper {
-
-class AddressMapper {
- public:
- AddressMapper() {}
-
- // Copy constructor: copies mappings from |source| to this AddressMapper. This
- // is useful for copying mappings from parent to child process upon fork(). It
- // is also useful to copy kernel mappings to any process that is created.
- AddressMapper(const AddressMapper& source);
-
- // Maps a new address range to quipper space.
- // |remove_existing_mappings| indicates whether to remove old mappings that
- // collide with the new range in real address space, indicating it has been
- // unmapped.
- // Returns true if mapping was successful.
- bool Map(const uint64_t real_addr,
- const uint64_t length,
- bool remove_existing_mappings);
-
- // Like Map(real_addr, length, remove_existing_mappings). |id| is an
- // identifier value to be stored along with the mapping. AddressMapper does
- // not care whether it is unique compared to all other IDs passed in. That is
- // up to the caller to keep track of.
- // |offset_base| represents the offset within the original region at which the
- // mapping begins. The original region can be much larger than the mapped
- // region.
- // e.g. Given a mapped region with base=0x4000 and size=0x2000 mapped with
- // offset_base=0x10000, then the address 0x5000 maps to an offset of 0x11000
- // (0x5000 - 0x4000 + 0x10000).
- bool MapWithID(const uint64_t real_addr,
- const uint64_t length,
- const uint64_t id,
- const uint64_t offset_base,
- bool remove_existing_mappings);
-
- // Looks up |real_addr| and returns the mapped address.
- bool GetMappedAddress(const uint64_t real_addr, uint64_t* mapped_addr) const;
-
- // Looks up |real_addr| and returns the mapping's ID and offset from the
- // start of the mapped space.
- bool GetMappedIDAndOffset(const uint64_t real_addr,
- uint64_t* id,
- uint64_t* offset) const;
-
- // Returns true if there are no mappings.
- bool IsEmpty() const {
- return mappings_.empty();
- }
-
- // Returns the number of address ranges that are currently mapped.
- unsigned int GetNumMappedRanges() const {
- return mappings_.size();
- }
-
- // Returns the maximum length of quipper space containing mapped areas.
- // There may be gaps in between blocks.
- // If the result is 2^64 (all of quipper space), this returns 0. Call
- // IsEmpty() to distinguish this from actual emptiness.
- uint64_t GetMaxMappedLength() const;
-
- // Dumps the state of the address mapper to logs. Useful for debugging.
- void DumpToLog() const;
-
- private:
- struct MappedRange {
- uint64_t real_addr;
- uint64_t mapped_addr;
- uint64_t size;
-
- uint64_t id;
- uint64_t offset_base;
-
- // Length of unmapped space after this range.
- uint64_t unmapped_space_after;
-
- // Determines if this range intersects another range in real space.
- inline bool Intersects(const MappedRange& range) const {
- return (real_addr <= range.real_addr + range.size - 1) &&
- (real_addr + size - 1 >= range.real_addr);
- }
-
- // Determines if this range fully covers another range in real space.
- inline bool Covers(const MappedRange& range) const {
- return (real_addr <= range.real_addr) &&
- (real_addr + size - 1 >= range.real_addr + range.size - 1);
- }
-
- // Determines if this range fully contains another range in real space.
- // This is different from Covers() in that the boundaries cannot overlap.
- inline bool Contains(const MappedRange& range) const {
- return (real_addr < range.real_addr) &&
- (real_addr + size - 1 > range.real_addr + range.size - 1);
- }
-
- // Determines if this range contains the given address |addr|.
- inline bool ContainsAddress(uint64_t addr) const {
- return (addr >= real_addr && addr <= real_addr + size - 1);
- }
- };
-
- // TODO(sque): implement with set or map to improve searching.
- typedef std::list<MappedRange> MappingList;
-
- // Removes an existing address mapping.
- // Returns true if successful, false if no mapped address range was found.
- bool Unmap(const MappedRange& range);
-
- // Container for all the existing mappings.
- MappingList mappings_;
-
- bool CheckMappings() const;
-};
-
-} // namespace quipper
-
-#endif // CHROMIUMOS_WIDE_PROFILING_ADDRESS_MAPPER_H_
diff --git a/perfprofd/quipper/base/basictypes.h b/perfprofd/quipper/base/basictypes.h
deleted file mode 100644
index cec5bedd..00000000
--- a/perfprofd/quipper/base/basictypes.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains definitions of our old basic integral types
-// ((u)int{8,16,32,64}) and further includes. I recommend that you use the C99
-// standard types instead, and include <stdint.h>/<stddef.h>/etc. as needed.
-// Note that the macros and macro-like constructs that were formerly defined in
-// this file are now available separately in base/macros.h.
-
-#ifndef BASE_BASICTYPES_H_
-#define BASE_BASICTYPES_H_
-
-#include <limits.h> // So we can set the bounds of our types.
-#include <stddef.h> // For size_t.
-#include <stdint.h> // For intptr_t.
-
-#include "quipper/base/macros.h"
-#include "quipper/base/port.h" // Types that only need exist on certain systems.
-
-// DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include <stdint.h>).
-typedef int8_t int8;
-typedef uint8_t uint8;
-typedef int16_t int16;
-typedef int32_t int32;
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-
-// TODO(vtl): Figure what's up with the 64-bit types. Can we just define them as
-// |int64_t|/|uint64_t|?
-// The NSPR system headers define 64-bit as |long| when possible, except on
-// Mac OS X. In order to not have typedef mismatches, we do the same on LP64.
-//
-// On Mac OS X, |long long| is used for 64-bit types for compatibility with
-// <inttypes.h> format macros even in the LP64 model.
-#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
-typedef long int64;
-typedef unsigned long uint64;
-#else
-typedef long long int64;
-typedef unsigned long long uint64;
-#endif
-
-// DEPRECATED: Please use std::numeric_limits (from <limits>) instead.
-const uint8 kuint8max = 0xFF;
-const uint16 kuint16max = 0xFFFF;
-const uint32 kuint32max = 0xFFFFFFFF;
-const uint64 kuint64max = 0xFFFFFFFFFFFFFFFFULL;
-const int8 kint8min = -0x7F - 1;
-const int8 kint8max = 0x7F;
-const int16 kint16min = -0x7FFF - 1;
-const int16 kint16max = 0x7FFF;
-const int32 kint32min = -0x7FFFFFFF - 1;
-const int32 kint32max = 0x7FFFFFFF;
-const int64 kint64min = -0x7FFFFFFFFFFFFFFFLL - 1;
-const int64 kint64max = 0x7FFFFFFFFFFFFFFFLL;
-
-#endif // BASE_BASICTYPES_H_
diff --git a/perfprofd/quipper/base/compiler_specific.h b/perfprofd/quipper/base/compiler_specific.h
deleted file mode 100644
index 000c7d74..00000000
--- a/perfprofd/quipper/base/compiler_specific.h
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_COMPILER_SPECIFIC_H_
-#define BASE_COMPILER_SPECIFIC_H_
-
-#include "quipper/build/build_config.h"
-
-#if defined(COMPILER_MSVC)
-
-// Macros for suppressing and disabling warnings on MSVC.
-//
-// Warning numbers are enumerated at:
-// http://msdn.microsoft.com/en-us/library/8x5x43k7(VS.80).aspx
-//
-// The warning pragma:
-// http://msdn.microsoft.com/en-us/library/2c8f766e(VS.80).aspx
-//
-// Using __pragma instead of #pragma inside macros:
-// http://msdn.microsoft.com/en-us/library/d9x1s805.aspx
-
-// MSVC_SUPPRESS_WARNING disables warning |n| for the remainder of the line and
-// for the next line of the source file.
-#define MSVC_SUPPRESS_WARNING(n) __pragma(warning(suppress:n))
-
-// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled.
-// The warning remains disabled until popped by MSVC_POP_WARNING.
-#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
- __pragma(warning(disable:n))
-
-// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level
-// remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all
-// warnings.
-#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n))
-
-// Pop effects of innermost MSVC_PUSH_* macro.
-#define MSVC_POP_WARNING() __pragma(warning(pop))
-
-#define MSVC_DISABLE_OPTIMIZE() __pragma(optimize("", off))
-#define MSVC_ENABLE_OPTIMIZE() __pragma(optimize("", on))
-
-// Allows exporting a class that inherits from a non-exported base class.
-// This uses suppress instead of push/pop because the delimiter after the
-// declaration (either "," or "{") has to be placed before the pop macro.
-//
-// Example usage:
-// class EXPORT_API Foo : NON_EXPORTED_BASE(public Bar) {
-//
-// MSVC Compiler warning C4275:
-// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'.
-// Note that this is intended to be used only when no access to the base class'
-// static data is done through derived classes or inline methods. For more info,
-// see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
-#define NON_EXPORTED_BASE(code) MSVC_SUPPRESS_WARNING(4275) \
- code
-
-#else // Not MSVC
-
-#define MSVC_SUPPRESS_WARNING(n)
-#define MSVC_PUSH_DISABLE_WARNING(n)
-#define MSVC_PUSH_WARNING_LEVEL(n)
-#define MSVC_POP_WARNING()
-#define MSVC_DISABLE_OPTIMIZE()
-#define MSVC_ENABLE_OPTIMIZE()
-#define NON_EXPORTED_BASE(code) code
-
-#endif // COMPILER_MSVC
-
-
-// The C++ standard requires that static const members have an out-of-class
-// definition (in a single compilation unit), but MSVC chokes on this (when
-// language extensions, which are required, are enabled). (You're only likely to
-// notice the need for a definition if you take the address of the member or,
-// more commonly, pass it to a function that takes it as a reference argument --
-// probably an STL function.) This macro makes MSVC do the right thing. See
-// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more
-// information. Use like:
-//
-// In .h file:
-// struct Foo {
-// static const int kBar = 5;
-// };
-//
-// In .cc file:
-// STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar;
-#if defined(COMPILER_MSVC)
-#define STATIC_CONST_MEMBER_DEFINITION __declspec(selectany)
-#else
-#define STATIC_CONST_MEMBER_DEFINITION
-#endif
-
-// Annotate a variable indicating it's ok if the variable is not used.
-// (Typically used to silence a compiler warning when the assignment
-// is important for some other reason.)
-// Use like:
-// int x ALLOW_UNUSED = ...;
-#if defined(COMPILER_GCC)
-#define ALLOW_UNUSED __attribute__((unused))
-#else
-#define ALLOW_UNUSED
-#endif
-
-// Annotate a function indicating it should not be inlined.
-// Use like:
-// NOINLINE void DoStuff() { ... }
-#if defined(COMPILER_GCC)
-#define NOINLINE __attribute__((noinline))
-#elif defined(COMPILER_MSVC)
-#define NOINLINE __declspec(noinline)
-#else
-#define NOINLINE
-#endif
-
-// Specify memory alignment for structs, classes, etc.
-// Use like:
-// class ALIGNAS(16) MyClass { ... }
-// ALIGNAS(16) int array[4];
-#if defined(COMPILER_MSVC)
-#define ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
-#elif defined(COMPILER_GCC)
-#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
-#endif
-
-// Return the byte alignment of the given type (available at compile time). Use
-// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
-// http://goo.gl/isH0C
-// Use like:
-// ALIGNOF(int32) // this would be 4
-#if defined(COMPILER_MSVC)
-#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
-#elif defined(COMPILER_GCC)
-#define ALIGNOF(type) __alignof__(type)
-#endif
-
-// Annotate a virtual method indicating it must be overriding a virtual
-// method in the parent class.
-// Use like:
-// virtual void foo() OVERRIDE;
-#define OVERRIDE override
-
-// Annotate a virtual method indicating that subclasses must not override it,
-// or annotate a class to indicate that it cannot be subclassed.
-// Use like:
-// virtual void foo() FINAL;
-// class B FINAL : public A {};
-#define FINAL final
-
-// Annotate a function indicating the caller must examine the return value.
-// Use like:
-// int foo() WARN_UNUSED_RESULT;
-// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
-#if defined(COMPILER_GCC)
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-#define WARN_UNUSED_RESULT
-#endif
-
-// Tell the compiler a function is using a printf-style format string.
-// |format_param| is the one-based index of the format string parameter;
-// |dots_param| is the one-based index of the "..." parameter.
-// For v*printf functions (which take a va_list), pass 0 for dots_param.
-// (This is undocumented but matches what the system C headers do.)
-#if defined(COMPILER_GCC)
-#define PRINTF_FORMAT(format_param, dots_param) \
- __attribute__((format(printf, format_param, dots_param)))
-#else
-#define PRINTF_FORMAT(format_param, dots_param)
-#endif
-
-// WPRINTF_FORMAT is the same, but for wide format strings.
-// This doesn't appear to yet be implemented in any compiler.
-// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 .
-#define WPRINTF_FORMAT(format_param, dots_param)
-// If available, it would look like:
-// __attribute__((format(wprintf, format_param, dots_param)))
-
-// MemorySanitizer annotations.
-#if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
-#include <sanitizer/msan_interface.h>
-
-// Mark a memory region fully initialized.
-// Use this to annotate code that deliberately reads uninitialized data, for
-// example a GC scavenging root set pointers from the stack.
-#define MSAN_UNPOISON(p, s) __msan_unpoison(p, s)
-#else // MEMORY_SANITIZER
-#define MSAN_UNPOISON(p, s)
-#endif // MEMORY_SANITIZER
-
-// Macro useful for writing cross-platform function pointers.
-#if !defined(CDECL)
-#if defined(OS_WIN)
-#define CDECL __cdecl
-#else // defined(OS_WIN)
-#define CDECL
-#endif // defined(OS_WIN)
-#endif // !defined(CDECL)
-
-// Macro for hinting that an expression is likely to be false.
-#if !defined(UNLIKELY)
-#if defined(COMPILER_GCC)
-#define UNLIKELY(x) __builtin_expect(!!(x), 0)
-#else
-#define UNLIKELY(x) (x)
-#endif // defined(COMPILER_GCC)
-#endif // !defined(UNLIKELY)
-
-#endif // BASE_COMPILER_SPECIFIC_H_
diff --git a/perfprofd/quipper/base/logging.cc b/perfprofd/quipper/base/logging.cc
deleted file mode 100644
index 3495d1ff..00000000
--- a/perfprofd/quipper/base/logging.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Logging support functions. These are designed to mimic those used in
-// chromium_org/base in terms of interface, but to redirect error to
-// the system log.
-//
-
-#define LOG_TAG "perf_reader"
-
-#include "quipper/base/logging.h"
-
-#if defined(OS_POSIX)
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#endif
-
-#include <algorithm>
-#include <cstring>
-#include <ctime>
-#include <iomanip>
-#include <ostream>
-#include <string>
-
-#include <android/log.h>
-
-namespace logging {
-
-namespace {
-
-int min_log_level = 0;
-
-}
-
-void SetMinLogLevel(int level) {
- min_log_level = std::min(LOG_FATAL, level);
-}
-
-int GetMinLogLevel() {
- return min_log_level;
-}
-
-// MSVC doesn't like complex extern templates and DLLs.
-#if !defined(COMPILER_MSVC)
-// Explicit instantiations for commonly used comparisons.
-template std::string* MakeCheckOpString<int, int>(
- const int&, const int&, const char* names);
-template std::string* MakeCheckOpString<unsigned long, unsigned long>(
- const unsigned long&, const unsigned long&, const char* names);
-template std::string* MakeCheckOpString<unsigned long, unsigned int>(
- const unsigned long&, const unsigned int&, const char* names);
-template std::string* MakeCheckOpString<unsigned int, unsigned long>(
- const unsigned int&, const unsigned long&, const char* names);
-template std::string* MakeCheckOpString<std::string, std::string>(
- const std::string&, const std::string&, const char* name);
-#endif
-
-LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
- : severity_(severity), file_(file), line_(line) {
- Init(file, line);
-}
-
-LogMessage::LogMessage(const char* file, int line, std::string* result)
- : severity_(LOG_FATAL), file_(file), line_(line) {
- Init(file, line);
- stream_ << "Check failed: " << *result;
- delete result;
-}
-
-LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
- std::string* result)
- : severity_(severity), file_(file), line_(line) {
- Init(file, line);
- stream_ << "Check failed: " << *result;
- delete result;
-}
-
-LogMessage::~LogMessage() {
- stream_ << std::endl;
- std::string str_newline(stream_.str());
-
- android_LogPriority priority =
- (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN;
- switch (severity_) {
- case LOG_INFO:
- priority = ANDROID_LOG_INFO;
- break;
- case LOG_WARNING:
- priority = ANDROID_LOG_WARN;
- break;
- case LOG_ERROR:
- priority = ANDROID_LOG_ERROR;
- break;
- case LOG_FATAL:
- priority = ANDROID_LOG_FATAL;
- break;
- }
- __android_log_write(priority, LOG_TAG, str_newline.c_str());
-
- if (severity_ == LOG_FATAL) {
- abort();
- }
-}
-
-void LogMessage::Init(const char* /* file */, int /* line */) {
-}
-
-} // namespace logging
diff --git a/perfprofd/quipper/base/logging.h b/perfprofd/quipper/base/logging.h
deleted file mode 100644
index aaf01c1b..00000000
--- a/perfprofd/quipper/base/logging.h
+++ /dev/null
@@ -1,671 +0,0 @@
-
-#ifndef BASE_LOGGING_H_
-#define BASE_LOGGING_H_
-
-#include <cassert>
-#include <string>
-#include <cstring>
-#include <sstream>
-
-#include "quipper/base/macros.h"
-#include "quipper/base/basictypes.h"
-
-//
-// Logging macros designed to mimic those used in chromium_org/base.
-//
-
-// Instructions
-// ------------
-//
-// Make a bunch of macros for logging. The way to log things is to stream
-// things to LOG(<a particular severity level>). E.g.,
-//
-// LOG(INFO) << "Found " << num_cookies << " cookies";
-//
-// You can also do conditional logging:
-//
-// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// The CHECK(condition) macro is active in both debug and release builds and
-// effectively performs a LOG(FATAL) which terminates the process and
-// generates a crashdump unless a debugger is attached.
-//
-// There are also "debug mode" logging macros like the ones above:
-//
-// DLOG(INFO) << "Found cookies";
-//
-// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// All "debug mode" logging is compiled away to nothing for non-debug mode
-// compiles. LOG_IF and development flags also work well together
-// because the code can be compiled away sometimes.
-//
-// We also have
-//
-// LOG_ASSERT(assertion);
-// DLOG_ASSERT(assertion);
-//
-// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
-//
-// There are "verbose level" logging macros. They look like
-//
-// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
-// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
-//
-// These always log at the INFO log level (when they log at all).
-// The verbose logging can also be turned on module-by-module. For instance,
-// --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
-// will cause:
-// a. VLOG(2) and lower messages to be printed from profile.{h,cc}
-// b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
-// c. VLOG(3) and lower messages to be printed from files prefixed with
-// "browser"
-// d. VLOG(4) and lower messages to be printed from files under a
-// "chromeos" directory.
-// e. VLOG(0) and lower messages to be printed from elsewhere
-//
-// The wildcarding functionality shown by (c) supports both '*' (match
-// 0 or more characters) and '?' (match any single character)
-// wildcards. Any pattern containing a forward or backward slash will
-// be tested against the whole pathname and not just the module.
-// E.g., "*/foo/bar/*=2" would change the logging level for all code
-// in source files under a "foo/bar" directory.
-//
-// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
-//
-// if (VLOG_IS_ON(2)) {
-// // do some logging preparation and logging
-// // that can't be accomplished with just VLOG(2) << ...;
-// }
-//
-// There is also a VLOG_IF "verbose level" condition macro for sample
-// cases, when some extra computation and preparation for logs is not
-// needed.
-//
-// VLOG_IF(1, (size > 1024))
-// << "I'm printed when size is more than 1024 and when you run the "
-// "program with --v=1 or more";
-//
-// We also override the standard 'assert' to use 'DLOG_ASSERT'.
-//
-// Lastly, there is:
-//
-// PLOG(ERROR) << "Couldn't do foo";
-// DPLOG(ERROR) << "Couldn't do foo";
-// PLOG_IF(ERROR, cond) << "Couldn't do foo";
-// DPLOG_IF(ERROR, cond) << "Couldn't do foo";
-// PCHECK(condition) << "Couldn't do foo";
-// DPCHECK(condition) << "Couldn't do foo";
-//
-// which append the last system error to the message in string form (taken from
-// GetLastError() on Windows and errno on POSIX).
-//
-// The supported severity levels for macros that allow you to specify one
-// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
-//
-// Very important: logging a message at the FATAL severity level causes
-// the program to terminate (after the message is logged).
-//
-// There is the special severity of DFATAL, which logs FATAL in debug mode,
-// ERROR in normal mode.
-
-#define BASE_EXPORT
-
-namespace logging {
-
-// Sets the log level. Anything at or above this level will be written to the
-// log file/displayed to the user (if applicable). Anything below this level
-// will be silently ignored. The log level defaults to 0 (everything is logged
-// up to level INFO) if this function is not called.
-// Note that log messages for VLOG(x) are logged at level -x, so setting
-// the min log level to negative values enables verbose logging.
-BASE_EXPORT void SetMinLogLevel(int level);
-
-// Gets the current log level.
-BASE_EXPORT int GetMinLogLevel();
-
-// Gets the VLOG default verbosity level.
-BASE_EXPORT int GetVlogVerbosity();
-
-typedef int LogSeverity;
-const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity
-// Note: the log severities are used to index into the array of names,
-// see log_severity_names.
-const LogSeverity LOG_INFO = 0;
-const LogSeverity LOG_WARNING = 1;
-const LogSeverity LOG_ERROR = 2;
-const LogSeverity LOG_FATAL = 3;
-const LogSeverity LOG_NUM_SEVERITIES = 4;
-
-// A few definitions of macros that don't generate much code. These are used
-// by LOG() and LOG_IF, etc. Since these are used all over our code, it's
-// better to have compact code for these operations.
-#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_DFATAL , ##__VA_ARGS__)
-
-#define COMPACT_GOOGLE_LOG_INFO \
- COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
-#define COMPACT_GOOGLE_LOG_WARNING \
- COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
-#define COMPACT_GOOGLE_LOG_ERROR \
- COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage)
-#define COMPACT_GOOGLE_LOG_FATAL \
- COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage)
-#define COMPACT_GOOGLE_LOG_DFATAL \
- COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage)
-
-// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also,
-// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will
-// always fire if they fail.
-#define LOG_IS_ON(severity) \
- ((::logging::LOG_ ## severity) >= ::logging::GetMinLogLevel())
-
-#define VLOG_IS_ON(verboselevel) false
-
-// Helper macro which avoids evaluating the arguments to a stream if
-// the condition doesn't hold.
-#define LAZY_STREAM(stream, condition) \
- !(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream) /* NOLINT */
-
-// We use the preprocessor's merging operator, "##", so that, e.g.,
-// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny
-// subtle difference between ostream member streaming functions (e.g.,
-// ostream::operator<<(int) and ostream non-member streaming functions
-// (e.g., ::operator<<(ostream&, string&): it turns out that it's
-// impossible to stream something like a string directly to an unnamed
-// ostream. We employ a neat hack by calling the stream() member
-// function of LogMessage which seems to avoid the problem.
-#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
-
-#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity))
-#define LOG_IF(severity, condition) \
- LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
-
-// The VLOG macros log with negative verbosities.
-#define VLOG_STREAM(verbose_level) \
- logging::LogMessage(__FILE__, __LINE__, -(verbose_level)).stream()
-
-#define VLOG(verbose_level) \
- LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
-
-#define VLOG_IF(verbose_level, condition) \
- LAZY_STREAM(VLOG_STREAM(verbose_level), \
- VLOG_IS_ON(verbose_level) && (condition))
-
-// TODO(akalin): Add more VLOG variants, e.g. VPLOG.
-
-#define LOG_ASSERT(condition) \
- LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
-#define SYSLOG_ASSERT(condition) \
- SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
-
-#define PLOG(severity) \
- LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity))
-
-#define PLOG_IF(severity, condition) \
- LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
-
-// The actual stream used isn't important.
-#define EAT_STREAM_PARAMETERS \
- true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL) /* NOLINT */
-
-// CHECK dies with a fatal error if condition is not true. It is *not*
-// controlled by NDEBUG, so the check will be executed regardless of
-// compilation mode.
-//
-// We make sure CHECK et al. always evaluates their arguments, as
-// doing CHECK(FunctionWithSideEffect()) is a common idiom.
-
-#define CHECK(condition) \
- LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \
- << "Check failed: " #condition ". "
-
-#define PCHECK(condition) \
- LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
- << "Check failed: " #condition ". "
-
-// Helper macro for binary operators.
-// Don't use this macro directly in your code, use CHECK_EQ et al below.
-//
-// TODO(akalin): Rewrite this so that constructs like if (...)
-// CHECK_EQ(...) else { ... } work properly.
-#define CHECK_OP(name, op, val1, val2) \
- if (std::string* _result = \
- logging::Check##name##Impl((val1), (val2), \
- #val1 " " #op " " #val2)) \
- logging::LogMessage(__FILE__, __LINE__, _result).stream()
-
-// Build the error message string. This is separate from the "Impl"
-// function template because it is not performance critical and so can
-// be out of line, while the "Impl" code should be inline. Caller
-// takes ownership of the returned string.
-template<class t1, class t2>
-std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
- std::ostringstream ss;
- ss << names << " (" << v1 << " vs. " << v2 << ")";
- std::string* msg = new std::string(ss.str());
- return msg;
-}
-
-// MSVC doesn't like complex extern templates and DLLs.
-#if !defined(COMPILER_MSVC)
-// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
-// in logging.cc.
-extern template BASE_EXPORT std::string* MakeCheckOpString<int, int>(
- const int&, const int&, const char* names);
-extern template BASE_EXPORT
-std::string* MakeCheckOpString<unsigned long, unsigned long>(
- const unsigned long&, const unsigned long&, const char* names);
-extern template BASE_EXPORT
-std::string* MakeCheckOpString<unsigned long, unsigned int>(
- const unsigned long&, const unsigned int&, const char* names);
-extern template BASE_EXPORT
-std::string* MakeCheckOpString<unsigned int, unsigned long>(
- const unsigned int&, const unsigned long&, const char* names);
-extern template BASE_EXPORT
-std::string* MakeCheckOpString<std::string, std::string>(
- const std::string&, const std::string&, const char* name);
-#endif
-
-// Helper functions for CHECK_OP macro.
-// The (int, int) specialization works around the issue that the compiler
-// will not instantiate the template version of the function on values of
-// unnamed enum type - see comment below.
-#define DEFINE_CHECK_OP_IMPL(name, op) \
- template <class t1, class t2> \
- inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
- const char* names) { \
- if (v1 op v2) return NULL; \
- else return MakeCheckOpString(v1, v2, names); \
- } \
- inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
- if (v1 op v2) return NULL; \
- else return MakeCheckOpString(v1, v2, names); \
- }
-DEFINE_CHECK_OP_IMPL(EQ, ==)
-DEFINE_CHECK_OP_IMPL(NE, !=)
-DEFINE_CHECK_OP_IMPL(LE, <=)
-DEFINE_CHECK_OP_IMPL(LT, < )
-DEFINE_CHECK_OP_IMPL(GE, >=)
-DEFINE_CHECK_OP_IMPL(GT, > )
-#undef DEFINE_CHECK_OP_IMPL
-
-#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
-#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
-#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
-#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
-#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
-#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
-
-#if defined(NDEBUG)
-#define ENABLE_DLOG 0
-#else
-#define ENABLE_DLOG 1
-#endif
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define DCHECK_IS_ON 0
-#else
-#define DCHECK_IS_ON 1
-#endif
-
-// Definitions for DLOG et al.
-
-#if ENABLE_DLOG
-
-#define DLOG_IS_ON(severity) LOG_IS_ON(severity)
-#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
-#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
-#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition)
-#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition)
-#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition)
-
-#else // ENABLE_DLOG
-
-// If ENABLE_DLOG is off, we want to avoid emitting any references to
-// |condition| (which may reference a variable defined only if NDEBUG
-// is not defined). Contrast this with DCHECK et al., which has
-// different behavior.
-
-#define DLOG_IS_ON(severity) false
-#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
-#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS
-#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
-#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
-#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
-
-#endif // ENABLE_DLOG
-
-// DEBUG_MODE is for uses like
-// if (DEBUG_MODE) foo.CheckThatFoo();
-// instead of
-// #ifndef NDEBUG
-// foo.CheckThatFoo();
-// #endif
-//
-// We tie its state to ENABLE_DLOG.
-enum { DEBUG_MODE = ENABLE_DLOG };
-
-#undef ENABLE_DLOG
-
-#define DLOG(severity) \
- LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity))
-
-#define DPLOG(severity) \
- LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity))
-
-#define DVLOG(verboselevel) DVLOG_IF(verboselevel, VLOG_IS_ON(verboselevel))
-
-#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel))
-
-// Definitions for DCHECK et al.
-
-#if DCHECK_IS_ON
-
-#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
- COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL
-const LogSeverity LOG_DCHECK = LOG_FATAL;
-
-#else // DCHECK_IS_ON
-
-// These are just dummy values.
-#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
- COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO
-const LogSeverity LOG_DCHECK = LOG_INFO;
-
-#endif // DCHECK_IS_ON
-
-// DCHECK et al. make sure to reference |condition| regardless of
-// whether DCHECKs are enabled; this is so that we don't get unused
-// variable warnings if the only use of a variable is in a DCHECK.
-// This behavior is different from DLOG_IF et al.
-
-#define DCHECK(condition) \
- LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \
- << "Check failed: " #condition ". "
-
-#define DPCHECK(condition) \
- LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \
- << "Check failed: " #condition ". "
-
-// Helper macro for binary operators.
-// Don't use this macro directly in your code, use DCHECK_EQ et al below.
-#define DCHECK_OP(name, op, val1, val2) \
- if (DCHECK_IS_ON) \
- if (std::string* _result = \
- logging::Check##name##Impl((val1), (val2), \
- #val1 " " #op " " #val2)) \
- logging::LogMessage( \
- __FILE__, __LINE__, ::logging::LOG_DCHECK, \
- _result).stream()
-
-// Equality/Inequality checks - compare two values, and log a
-// LOG_DCHECK message including the two values when the result is not
-// as expected. The values must have operator<<(ostream, ...)
-// defined.
-//
-// You may append to the error message like so:
-// DCHECK_NE(1, 2) << ": The world must be ending!";
-//
-// We are very careful to ensure that each argument is evaluated exactly
-// once, and that anything which is legal to pass as a function argument is
-// legal here. In particular, the arguments may be temporary expressions
-// which will end up being destroyed at the end of the apparent statement,
-// for example:
-// DCHECK_EQ(string("abc")[1], 'b');
-//
-// WARNING: These may not compile correctly if one of the arguments is a pointer
-// and the other is NULL. To work around this, simply static_cast NULL to the
-// type of the desired pointer.
-
-#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
-#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
-#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
-#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
-#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
-#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
-
-#if defined(NDEBUG) && defined(OS_CHROMEOS)
-#define NOTREACHED() LOG(ERROR) << "NOTREACHED() hit in " << \
- __FUNCTION__ << ". "
-#else
-#define NOTREACHED() DCHECK(false)
-#endif
-
-// Redefine the standard assert to use our nice log files
-#undef assert
-#define assert(x) DLOG_ASSERT(x)
-
-// This class more or less represents a particular log message. You
-// create an instance of LogMessage and then stream stuff to it.
-// When you finish streaming to it, ~LogMessage is called and the
-// full message gets streamed to the appropriate destination.
-//
-// You shouldn't actually use LogMessage's constructor to log things,
-// though. You should use the LOG() macro (and variants thereof)
-// above.
-class BASE_EXPORT LogMessage {
- public:
- // Used for LOG(severity).
- LogMessage(const char* file, int line, LogSeverity severity);
-
- // Used for CHECK_EQ(), etc. Takes ownership of the given string.
- // Implied severity = LOG_FATAL.
- LogMessage(const char* file, int line, std::string* result);
-
- // Used for DCHECK_EQ(), etc. Takes ownership of the given string.
- LogMessage(const char* file, int line, LogSeverity severity,
- std::string* result);
-
- ~LogMessage();
-
- std::ostream& stream() { return stream_; }
-
- private:
- void Init(const char* file, int line);
-
- LogSeverity severity_;
- std::ostringstream stream_;
- size_t message_start_; // Offset of the start of the message (past prefix
- // info).
- // The file and line information passed in to the constructor.
- const char* file_;
- const int line_;
-
-#if defined(OS_WIN)
- // Stores the current value of GetLastError in the constructor and restores
- // it in the destructor by calling SetLastError.
- // This is useful since the LogMessage class uses a lot of Win32 calls
- // that will lose the value of GLE and the code that called the log function
- // will have lost the thread error value when the log call returns.
- class SaveLastError {
- public:
- SaveLastError();
- ~SaveLastError();
-
- unsigned long get_error() const { return last_error_; }
-
- protected:
- unsigned long last_error_;
- };
-
- SaveLastError last_error_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(LogMessage);
-};
-
-// A non-macro interface to the log facility; (useful
-// when the logging level is not a compile-time constant).
-inline void LogAtLevel(int const log_level, std::string const &msg) {
- LogMessage(__FILE__, __LINE__, log_level).stream() << msg;
-}
-
-// This class is used to explicitly ignore values in the conditional
-// logging macros. This avoids compiler warnings like "value computed
-// is not used" and "statement has no effect".
-class LogMessageVoidify {
- public:
- LogMessageVoidify() { }
- // This has to be an operator with a precedence lower than << but
- // higher than ?:
- void operator&(std::ostream&) { }
-};
-
-#if defined(OS_WIN)
-typedef unsigned long SystemErrorCode;
-#elif defined(OS_POSIX)
-typedef int SystemErrorCode;
-#endif
-
-// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
-// pull in windows.h just for GetLastError() and DWORD.
-BASE_EXPORT SystemErrorCode GetLastSystemErrorCode();
-BASE_EXPORT std::string SystemErrorCodeToString(SystemErrorCode error_code);
-
-#if defined(OS_WIN)
-// Appends a formatted system message of the GetLastError() type.
-class BASE_EXPORT Win32ErrorLogMessage {
- public:
- Win32ErrorLogMessage(const char* file,
- int line,
- LogSeverity severity,
- SystemErrorCode err);
-
- // Appends the error message before destructing the encapsulated class.
- ~Win32ErrorLogMessage();
-
- std::ostream& stream() { return log_message_.stream(); }
-
- private:
- SystemErrorCode err_;
- LogMessage log_message_;
-
- DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage);
-};
-#elif defined(OS_POSIX)
-// Appends a formatted system message of the errno type
-class BASE_EXPORT ErrnoLogMessage {
- public:
- ErrnoLogMessage(const char* file,
- int line,
- LogSeverity severity,
- SystemErrorCode err);
-
- // Appends the error message before destructing the encapsulated class.
- ~ErrnoLogMessage();
-
- std::ostream& stream() { return log_message_.stream(); }
-
- private:
- SystemErrorCode err_;
- LogMessage log_message_;
-
- DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage);
-};
-#endif // OS_WIN
-
-// Closes the log file explicitly if open.
-// NOTE: Since the log file is opened as necessary by the action of logging
-// statements, there's no guarantee that it will stay closed
-// after this call.
-BASE_EXPORT void CloseLogFile();
-
-// Async signal safe logging mechanism.
-BASE_EXPORT void RawLog(int level, const char* message);
-
-#define RAW_LOG(level, message) logging::RawLog(logging::LOG_ ## level, message)
-
-#define RAW_CHECK(condition) \
- do { \
- if (!(condition)) \
- logging::RawLog(logging::LOG_FATAL, "Check failed: " #condition "\n"); \
- } while (0)
-
-#if defined(OS_WIN)
-// Returns the default log file path.
-BASE_EXPORT std::wstring GetLogFileFullPath();
-#endif
-
-} // namespace logging
-
-// Note that "The behavior of a C++ program is undefined if it adds declarations
-// or definitions to namespace std or to a namespace within namespace std unless
-// otherwise specified." --C++11[namespace.std]
-//
-// We've checked that this particular definition has the intended behavior on
-// our implementations, but it's prone to breaking in the future, and please
-// don't imitate this in your own definitions without checking with some
-// standard library experts.
-namespace std {
-// These functions are provided as a convenience for logging, which is where we
-// use streams (it is against Google style to use streams in other places). It
-// is designed to allow you to emit non-ASCII Unicode strings to the log file,
-// which is normally ASCII. It is relatively slow, so try not to use it for
-// common cases. Non-ASCII characters will be converted to UTF-8 by these
-// operators.
-BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr);
-inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
- return out << wstr.c_str();
-}
-} // namespace std
-
-// The NOTIMPLEMENTED() macro annotates codepaths which have
-// not been implemented yet.
-//
-// The implementation of this macro is controlled by NOTIMPLEMENTED_POLICY:
-// 0 -- Do nothing (stripped by compiler)
-// 1 -- Warn at compile time
-// 2 -- Fail at compile time
-// 3 -- Fail at runtime (DCHECK)
-// 4 -- [default] LOG(ERROR) at runtime
-// 5 -- LOG(ERROR) at runtime, only once per call-site
-
-#ifndef NOTIMPLEMENTED_POLICY
-#if defined(OS_ANDROID) && defined(OFFICIAL_BUILD)
-#define NOTIMPLEMENTED_POLICY 0
-#else
-// WebView: Hide NOTIMPLEMENTED entirely in Android release branch.
-#define NOTIMPLEMENTED_POLICY 0
-#endif
-#endif
-
-#if defined(COMPILER_GCC)
-// On Linux, with GCC, we can use __PRETTY_FUNCTION__ to get the demangled name
-// of the current function in the NOTIMPLEMENTED message.
-#define NOTIMPLEMENTED_MSG "Not implemented reached in " << __PRETTY_FUNCTION__
-#else
-#define NOTIMPLEMENTED_MSG "NOT IMPLEMENTED"
-#endif
-
-#if NOTIMPLEMENTED_POLICY == 0
-#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS
-#elif NOTIMPLEMENTED_POLICY == 1
-// TODO, figure out how to generate a warning
-#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
-#elif NOTIMPLEMENTED_POLICY == 2
-#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
-#elif NOTIMPLEMENTED_POLICY == 3
-#define NOTIMPLEMENTED() NOTREACHED()
-#elif NOTIMPLEMENTED_POLICY == 4
-#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG
-#elif NOTIMPLEMENTED_POLICY == 5
-#define NOTIMPLEMENTED() do {\
- static bool logged_once = false;\
- LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\
- logged_once = true;\
-} while(0);\
-EAT_STREAM_PARAMETERS
-#endif
-
-#endif // BASE_LOGGING_H_
diff --git a/perfprofd/quipper/base/macros.h b/perfprofd/quipper/base/macros.h
deleted file mode 100644
index be14792b..00000000
--- a/perfprofd/quipper/base/macros.h
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains macros and macro-like constructs (e.g., templates) that
-// are commonly used throughout Chromium source. (It may also contain things
-// that are closely related to things that are commonly used that belong in this
-// file.)
-
-#ifndef BASE_MACROS_H_
-#define BASE_MACROS_H_
-
-#include <stddef.h> // For size_t.
-#include <string.h> // For memcpy.
-
-#include "quipper/base/compiler_specific.h" // For ALLOW_UNUSED.
-
-// Put this in the private: declarations for a class to be uncopyable.
-#define DISALLOW_COPY(TypeName) \
- TypeName(const TypeName&)
-
-// Put this in the private: declarations for a class to be unassignable.
-#define DISALLOW_ASSIGN(TypeName) \
- void operator=(const TypeName&)
-
-// A macro to disallow the copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-// An older, deprecated, politically incorrect name for the above.
-// NOTE: The usage of this macro was banned from our code base, but some
-// third_party libraries are yet using it.
-// TODO(tfarina): Figure out how to fix the usage of this macro in the
-// third_party libraries and get rid of it.
-#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) DISALLOW_COPY_AND_ASSIGN(TypeName)
-
-// A macro to disallow all the implicit constructors, namely the
-// default constructor, copy constructor and operator= functions.
-//
-// This should be used in the private: declarations for a class
-// that wants to prevent anyone from instantiating it. This is
-// especially useful for classes containing only static methods.
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
- TypeName(); \
- DISALLOW_COPY_AND_ASSIGN(TypeName)
-
-// The arraysize(arr) macro returns the # of elements in an array arr.
-// The expression is a compile-time constant, and therefore can be
-// used in defining new arrays, for example. If you use arraysize on
-// a pointer by mistake, you will get a compile-time error.
-//
-// One caveat is that arraysize() doesn't accept any array of an
-// anonymous type or a type defined inside a function. In these rare
-// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
-// due to a limitation in C++'s template system. The limitation might
-// eventually be removed, but it hasn't happened yet.
-
-// This template function declaration is used in defining arraysize.
-// Note that the function doesn't need an implementation, as we only
-// use its type.
-template <typename T, size_t N>
-char (&ArraySizeHelper(T (&array)[N]))[N];
-
-// That gcc wants both of these prototypes seems mysterious. VC, for
-// its part, can't decide which to use (another mystery). Matching of
-// template overloads: the final frontier.
-#ifndef _MSC_VER
-template <typename T, size_t N>
-char (&ArraySizeHelper(const T (&array)[N]))[N];
-#endif
-
-#define arraysize(array) (sizeof(ArraySizeHelper(array)))
-
-// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
-// but can be used on anonymous types or types defined inside
-// functions. It's less safe than arraysize as it accepts some
-// (although not all) pointers. Therefore, you should use arraysize
-// whenever possible.
-//
-// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
-// size_t.
-//
-// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error
-//
-// "warning: division by zero in ..."
-//
-// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
-// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
-//
-// The following comments are on the implementation details, and can
-// be ignored by the users.
-//
-// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
-// the array) and sizeof(*(arr)) (the # of bytes in one array
-// element). If the former is divisible by the latter, perhaps arr is
-// indeed an array, in which case the division result is the # of
-// elements in the array. Otherwise, arr cannot possibly be an array,
-// and we generate a compiler error to prevent the code from
-// compiling.
-//
-// Since the size of bool is implementation-defined, we need to cast
-// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
-// result has type size_t.
-//
-// This macro is not perfect as it wrongfully accepts certain
-// pointers, namely where the pointer size is divisible by the pointee
-// size. Since all our code has to go through a 32-bit compiler,
-// where a pointer is 4 bytes, this means all pointers to a type whose
-// size is 3 or greater than 4 will be (righteously) rejected.
-
-#define ARRAYSIZE_UNSAFE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
- static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
-
-// Use implicit_cast as a safe version of static_cast or const_cast
-// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
-// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
-// a const pointer to Foo).
-// When you use implicit_cast, the compiler checks that the cast is safe.
-// Such explicit implicit_casts are necessary in surprisingly many
-// situations where C++ demands an exact type match instead of an
-// argument type convertible to a target type.
-//
-// The From type can be inferred, so the preferred syntax for using
-// implicit_cast is the same as for static_cast etc.:
-//
-// implicit_cast<ToType>(expr)
-//
-// implicit_cast would have been part of the C++ standard library,
-// but the proposal was submitted too late. It will probably make
-// its way into the language in the future.
-template<typename To, typename From>
-inline To implicit_cast(From const &f) {
- return f;
-}
-
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,
-// content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-
-#undef COMPILE_ASSERT
-#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
-
-// bit_cast<Dest,Source> is a template function that implements the
-// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
-// very low-level functions like the protobuf library and fast math
-// support.
-//
-// float f = 3.14159265358979;
-// int i = bit_cast<int32>(f);
-// // i = 0x40490fdb
-//
-// The classical address-casting method is:
-//
-// // WRONG
-// float f = 3.14159265358979; // WRONG
-// int i = * reinterpret_cast<int*>(&f); // WRONG
-//
-// The address-casting method actually produces undefined behavior
-// according to ISO C++ specification section 3.10 -15 -. Roughly, this
-// section says: if an object in memory has one type, and a program
-// accesses it with a different type, then the result is undefined
-// behavior for most values of "different type".
-//
-// This is true for any cast syntax, either *(int*)&f or
-// *reinterpret_cast<int*>(&f). And it is particularly true for
-// conversions between integral lvalues and floating-point lvalues.
-//
-// The purpose of 3.10 -15- is to allow optimizing compilers to assume
-// that expressions with different types refer to different memory. gcc
-// 4.0.1 has an optimizer that takes advantage of this. So a
-// non-conforming program quietly produces wildly incorrect output.
-//
-// The problem is not the use of reinterpret_cast. The problem is type
-// punning: holding an object in memory of one type and reading its bits
-// back using a different type.
-//
-// The C++ standard is more subtle and complex than this, but that
-// is the basic idea.
-//
-// Anyways ...
-//
-// bit_cast<> calls memcpy() which is blessed by the standard,
-// especially by the example in section 3.9 . Also, of course,
-// bit_cast<> wraps up the nasty logic in one place.
-//
-// Fortunately memcpy() is very fast. In optimized mode, with a
-// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
-// code with the minimal amount of data movement. On a 32-bit system,
-// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
-// compiles to two loads and two stores.
-//
-// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
-//
-// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
-// is likely to surprise you.
-
-template <class Dest, class Source>
-inline Dest bit_cast(const Source& source) {
- COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual);
-
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
-
-// Used to explicitly mark the return value of a function as unused. If you are
-// really sure you don't want to do anything with the return value of a function
-// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:
-//
-// scoped_ptr<MyType> my_var = ...;
-// if (TakeOwnership(my_var.get()) == SUCCESS)
-// ignore_result(my_var.release());
-//
-template<typename T>
-inline void ignore_result(const T&) {
-}
-
-// The following enum should be used only as a constructor argument to indicate
-// that the variable has static storage class, and that the constructor should
-// do nothing to its state. It indicates to the reader that it is legal to
-// declare a static instance of the class, provided the constructor is given
-// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a
-// static variable that has a constructor or a destructor because invocation
-// order is undefined. However, IF the type can be initialized by filling with
-// zeroes (which the loader does for static variables), AND the destructor also
-// does nothing to the storage, AND there are no virtual methods, then a
-// constructor declared as
-// explicit MyClass(base::LinkerInitialized x) {}
-// and invoked as
-// static MyClass my_variable_name(base::LINKER_INITIALIZED);
-namespace base {
-enum LinkerInitialized { LINKER_INITIALIZED };
-
-// Use these to declare and define a static local variable (static T;) so that
-// it is leaked so that its destructors are not called at exit. If you need
-// thread-safe initialization, use base/lazy_instance.h instead.
-#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \
- static type& name = *new type arguments /* NOLINT */
-
-} // base
-
-#endif // BASE_MACROS_H_
diff --git a/perfprofd/quipper/base/port.h b/perfprofd/quipper/base/port.h
deleted file mode 100644
index 58f4969b..00000000
--- a/perfprofd/quipper/base/port.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_PORT_H_
-#define BASE_PORT_H_
-
-#include <stdarg.h>
-#include "quipper/build/build_config.h"
-
-// DEPRECATED: Use ...LL and ...ULL suffixes.
-// TODO(viettrungluu): Delete these. These are only here until |GG_(U)INT64_C|
-// are deleted (some other header files (re)define |GG_(U)INT64_C|, so our
-// definitions of them must exactly match theirs).
-#ifdef COMPILER_MSVC
-#define GG_LONGLONG(x) x##I64
-#define GG_ULONGLONG(x) x##UI64
-#else
-#define GG_LONGLONG(x) x##LL
-#define GG_ULONGLONG(x) x##ULL
-#endif
-
-// DEPRECATED: In Chromium, we force-define __STDC_CONSTANT_MACROS, so you can
-// just use the regular (U)INTn_C macros from <stdint.h>.
-// TODO(viettrungluu): Remove the remaining GG_(U)INTn_C macros.
-#define GG_INT64_C(x) GG_LONGLONG(x)
-#define GG_UINT64_C(x) GG_ULONGLONG(x)
-
-// It's possible for functions that use a va_list, such as StringPrintf, to
-// invalidate the data in it upon use. The fix is to make a copy of the
-// structure before using it and use that copy instead. va_copy is provided
-// for this purpose. MSVC does not provide va_copy, so define an
-// implementation here. It is not guaranteed that assignment is a copy, so the
-// StringUtil.VariableArgsFunc unit test tests this capability.
-#if defined(COMPILER_GCC)
-#define GG_VA_COPY(a, b) (va_copy(a, b))
-#elif defined(COMPILER_MSVC)
-#define GG_VA_COPY(a, b) (a = b)
-#endif
-
-// Define an OS-neutral wrapper for shared library entry points
-#if defined(OS_WIN)
-#define API_CALL __stdcall
-#else
-#define API_CALL
-#endif
-
-#endif // BASE_PORT_H_
diff --git a/perfprofd/quipper/build/build_config.h b/perfprofd/quipper/build/build_config.h
deleted file mode 100644
index 55348460..00000000
--- a/perfprofd/quipper/build/build_config.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file adds defines about the platform we're currently building on.
-// Operating System:
-// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) / OS_NACL
-// Compiler:
-// COMPILER_MSVC / COMPILER_GCC
-// Processor:
-// ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64)
-// ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
-
-#ifndef BUILD_BUILD_CONFIG_H_
-#define BUILD_BUILD_CONFIG_H_
-
-// A set of macros to use for platform detection.
-#if defined(__native_client__)
-// __native_client__ must be first, so that other OS_ defines are not set.
-#define OS_NACL 1
-#elif defined(ANDROID)
-#define OS_ANDROID 1
-#elif defined(__APPLE__)
-// only include TargetConditions after testing ANDROID as some android builds
-// on mac don't have this header available and it's not needed unless the target
-// is really mac/ios.
-#include <TargetConditionals.h>
-#define OS_MACOSX 1
-#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
-#define OS_IOS 1
-#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
-#elif defined(__linux__)
-#define OS_LINUX 1
-// include a system header to pull in features.h for glibc/uclibc macros.
-#include <unistd.h>
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
-// we really are using glibc, not uClibc pretending to be glibc
-#define LIBC_GLIBC 1
-#endif
-#elif defined(_WIN32)
-#define OS_WIN 1
-#define TOOLKIT_VIEWS 1
-#elif defined(__FreeBSD__)
-#define OS_FREEBSD 1
-#elif defined(__OpenBSD__)
-#define OS_OPENBSD 1
-#elif defined(__sun)
-#define OS_SOLARIS 1
-#elif defined(__QNXNTO__)
-#define OS_QNX 1
-#else
-#error Please add support for your platform in build/build_config.h
-#endif
-
-#if defined(USE_OPENSSL) && defined(USE_NSS)
-#error Cannot use both OpenSSL and NSS
-#endif
-
-// For access to standard BSD features, use OS_BSD instead of a
-// more specific macro.
-#if defined(OS_FREEBSD) || defined(OS_OPENBSD)
-#define OS_BSD 1
-#endif
-
-// For access to standard POSIXish features, use OS_POSIX instead of a
-// more specific macro.
-#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \
- defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) || \
- defined(OS_NACL) || defined(OS_QNX)
-#define OS_POSIX 1
-#endif
-
-// Use tcmalloc
-#if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \
- !defined(NO_TCMALLOC)
-#define USE_TCMALLOC 1
-#endif
-
-// Compiler detection.
-#if defined(__GNUC__)
-#define COMPILER_GCC 1
-#elif defined(_MSC_VER)
-#define COMPILER_MSVC 1
-#else
-#error Please add support for your compiler in build/build_config.h
-#endif
-
-// Processor architecture detection. For more info on what's defined, see:
-// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
-// http://www.agner.org/optimize/calling_conventions.pdf
-// or with gcc, run: "echo | gcc -E -dM -"
-#if defined(_M_X64) || defined(__x86_64__)
-#define ARCH_CPU_X86_FAMILY 1
-#define ARCH_CPU_X86_64 1
-#define ARCH_CPU_64_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(_M_IX86) || defined(__i386__)
-#define ARCH_CPU_X86_FAMILY 1
-#define ARCH_CPU_X86 1
-#define ARCH_CPU_32_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__ARMEL__)
-#define ARCH_CPU_ARM_FAMILY 1
-#define ARCH_CPU_ARMEL 1
-#define ARCH_CPU_32_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__aarch64__)
-#define ARCH_CPU_ARM_FAMILY 1
-#define ARCH_CPU_ARM64 1
-#define ARCH_CPU_64_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__pnacl__)
-#define ARCH_CPU_32_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__MIPSEL__)
-#if defined(__LP64__)
-#define ARCH_CPU_MIPS64_FAMILY 1
-#define ARCH_CPU_MIPS64EL 1
-#define ARCH_CPU_64_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#else
-#define ARCH_CPU_MIPS_FAMILY 1
-#define ARCH_CPU_MIPSEL 1
-#define ARCH_CPU_32_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#endif
-#else
-#error Please add support for your architecture in build/build_config.h
-#endif
-
-// Type detection for wchar_t.
-#if defined(OS_WIN)
-#define WCHAR_T_IS_UTF16
-#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
- defined(__WCHAR_MAX__) && \
- (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
-#define WCHAR_T_IS_UTF32
-#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \
- defined(__WCHAR_MAX__) && \
- (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
-// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to
-// compile in this mode (in particular, Chrome doesn't). This is intended for
-// other projects using base who manage their own dependencies and make sure
-// short wchar works for them.
-#define WCHAR_T_IS_UTF16
-#else
-#error Please add support for your compiler in build/build_config.h
-#endif
-
-#if defined(OS_ANDROID)
-// The compiler thinks std::string::const_iterator and "const char*" are
-// equivalent types.
-#define STD_STRING_ITERATOR_IS_CHAR_POINTER
-// The compiler thinks base::string16::const_iterator and "char16*" are
-// equivalent types.
-#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER
-#endif
-
-#endif // BUILD_BUILD_CONFIG_H_
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/perf.h b/perfprofd/quipper/kernel-headers/tools/perf/perf.h
deleted file mode 100644
index e58da9ae..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/perf.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _PERF_PERF_H
-#define _PERF_PERF_H
-#ifdef __i386__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define rmb() asm volatile("lock; addl $0,0(%%esp)" : : : "memory")
-#define cpu_relax() asm volatile("rep; nop" : : : "memory");
-#define CPUINFO_PROC "model name"
-#ifndef __NR_perf_event_open
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define __NR_perf_event_open 336
-#endif
-#endif
-#ifdef __x86_64__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define rmb() asm volatile("lfence" : : : "memory")
-#define cpu_relax() asm volatile("rep; nop" : : : "memory");
-#define CPUINFO_PROC "model name"
-#ifndef __NR_perf_event_open
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define __NR_perf_event_open 298
-#endif
-#endif
-#ifdef __powerpc__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define rmb() asm volatile("sync" : : : "memory")
-#define cpu_relax() asm volatile("" : : : "memory");
-#define CPUINFO_PROC "cpu"
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#ifdef __s390__
-#define rmb() asm volatile("bcr 15,0" : : : "memory")
-#define cpu_relax() asm volatile("" : : : "memory");
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#ifdef __sh__
-#if defined(__SH4A__) || defined(__SH5__)
-#define rmb() asm volatile("synco" : : : "memory")
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#else
-#define rmb() asm volatile("" : : : "memory")
-#endif
-#define cpu_relax() asm volatile("" : : : "memory")
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define CPUINFO_PROC "cpu type"
-#endif
-#ifdef __hppa__
-#define rmb() asm volatile("" : : : "memory")
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define cpu_relax() asm volatile("" : : : "memory");
-#define CPUINFO_PROC "cpu"
-#endif
-#ifdef __sparc__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define rmb() asm volatile("" : : : "memory")
-#define cpu_relax() asm volatile("" : : : "memory")
-#define CPUINFO_PROC "cpu"
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#ifdef __alpha__
-#define rmb() asm volatile("mb" : : : "memory")
-#define cpu_relax() asm volatile("" : : : "memory")
-#define CPUINFO_PROC "cpu model"
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#ifdef __ia64__
-#define rmb() asm volatile("mf" : : : "memory")
-#define cpu_relax() asm volatile("hint @pause" : : : "memory")
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define CPUINFO_PROC "model name"
-#endif
-#ifdef __arm__
-#define rmb() ((void(*) (void)) 0xffff0fa0) ()
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define cpu_relax() asm volatile("" : : : "memory")
-#define CPUINFO_PROC "Processor"
-#endif
-#ifdef __aarch64__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define rmb() asm volatile("dmb ld" : : : "memory")
-#define cpu_relax() asm volatile("yield" : : : "memory")
-#endif
-#ifdef __mips__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define rmb() asm volatile(".set mips2\n\t" "sync\n\t" ".set mips0" : : : "memory")
-#define cpu_relax() asm volatile("" : : : "memory")
-#define CPUINFO_PROC "cpu model"
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#ifdef __arc__
-#define rmb() asm volatile("" : : : "memory")
-#define cpu_relax() rmb()
-#define CPUINFO_PROC "Processor"
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#ifdef __metag__
-#define rmb() asm volatile("" : : : "memory")
-#define cpu_relax() asm volatile("" : : : "memory")
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define CPUINFO_PROC "CPU"
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define PR_TASK_PERF_EVENTS_DISABLE 31
-#define PR_TASK_PERF_EVENTS_ENABLE 32
-#ifndef NSEC_PER_SEC
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NSEC_PER_SEC 1000000000ULL
-#endif
-#ifndef NSEC_PER_USEC
-#define NSEC_PER_USEC 1000ULL
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#define __user
-#define asmlinkage
-#define unlikely(x) __builtin_expect(! ! (x), 0)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define min(x,y) ({ typeof(x) _min1 = (x); typeof(y) _min2 = (y); (void) (& _min1 == & _min2); _min1 < _min2 ? _min1 : _min2; })
-#define MAX_COUNTERS 256
-#define MAX_NR_CPUS 256
-struct ip_callchain {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 nr;
- u64 ips[0];
-};
-struct branch_flags {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 mispred : 1;
- u64 predicted : 1;
- u64 reserved : 62;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct branch_entry {
- u64 from;
- u64 to;
- struct branch_flags flags;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct branch_stack {
- u64 nr;
- struct branch_entry entries[0];
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-enum perf_call_graph_mode {
- CALLCHAIN_NONE,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- CALLCHAIN_FP,
- CALLCHAIN_DWARF
-};
-struct perf_record_opts {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_target target;
- int call_graph;
- bool group;
- bool inherit_stat;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- bool no_delay;
- bool no_inherit;
- bool no_samples;
- bool pipe_output;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- bool raw_samples;
- bool sample_address;
- bool sample_weight;
- bool sample_time;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- bool period;
- unsigned int freq;
- unsigned int mmap_pages;
- unsigned int user_freq;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 branch_stack;
- u64 default_interval;
- u64 user_interval;
- u16 stack_dump_size;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-#endif
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/build-id.h b/perfprofd/quipper/kernel-headers/tools/perf/util/build-id.h
deleted file mode 100644
index b7dbc166..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/build-id.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef PERF_BUILD_ID_H_
-#define PERF_BUILD_ID_H_ 1
-#define BUILD_ID_SIZE 20
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct dso;
-#endif
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/event.h b/perfprofd/quipper/kernel-headers/tools/perf/util/event.h
deleted file mode 100644
index 4d3e3e53..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/event.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef __PERF_RECORD_H
-#define __PERF_RECORD_H
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct mmap_event {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_event_header header;
- u32 pid, tid;
- u64 start;
- u64 len;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 pgoff;
- char filename[PATH_MAX];
-};
-struct mmap2_event {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_event_header header;
- u32 pid, tid;
- u64 start;
- u64 len;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 pgoff;
- u32 maj;
- u32 min;
- u64 ino;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 ino_generation;
- char filename[PATH_MAX];
-};
-struct comm_event {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_event_header header;
- u32 pid, tid;
- char comm[16];
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct fork_event {
- struct perf_event_header header;
- u32 pid, ppid;
- u32 tid, ptid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 time;
-};
-struct lost_event {
- struct perf_event_header header;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 id;
- u64 lost;
-};
-struct read_event {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_event_header header;
- u32 pid, tid;
- u64 value;
- u64 time_enabled;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 time_running;
- u64 id;
-};
-#define PERF_SAMPLE_MASK (PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | PERF_SAMPLE_IDENTIFIER)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct sample_event {
- struct perf_event_header header;
- u64 array[];
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct regs_dump {
- u64 abi;
- u64 * regs;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct stack_dump {
- u16 offset;
- u64 size;
- char * data;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct sample_read_value {
- u64 value;
- u64 id;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct sample_read {
- u64 time_enabled;
- u64 time_running;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- union {
- struct {
- u64 nr;
- struct sample_read_value * values;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- } group;
- struct sample_read_value one;
- };
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct perf_sample {
- u64 ip;
- u32 pid, tid;
- u64 time;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 addr;
- u64 id;
- u64 stream_id;
- u64 period;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 weight;
- u32 cpu;
- u32 raw_size;
- u64 data_src;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- void * raw_data;
- struct ip_callchain * callchain;
- struct branch_stack * branch_stack;
- struct regs_dump user_regs;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct stack_dump user_stack;
- struct sample_read read;
-};
-#define PERF_MEM_DATA_SRC_NONE (PERF_MEM_S(OP, NA) | PERF_MEM_S(LVL, NA) | PERF_MEM_S(SNOOP, NA) | PERF_MEM_S(LOCK, NA) | PERF_MEM_S(TLB, NA))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct build_id_event {
- struct perf_event_header header;
- pid_t pid;
- u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- char filename[];
-};
-enum perf_user_event_type {
- PERF_RECORD_USER_TYPE_START = 64,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- PERF_RECORD_HEADER_ATTR = 64,
- PERF_RECORD_HEADER_EVENT_TYPE = 65,
- PERF_RECORD_HEADER_TRACING_DATA = 66,
- PERF_RECORD_HEADER_BUILD_ID = 67,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- PERF_RECORD_FINISHED_ROUND = 68,
- PERF_RECORD_HEADER_MAX
-};
-struct attr_event {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_event_header header;
- struct perf_event_attr attr;
- u64 id[];
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MAX_EVENT_NAME 64
-struct perf_trace_event_type {
- u64 event_id;
- char name[MAX_EVENT_NAME];
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct event_type_event {
- struct perf_event_header header;
- struct perf_trace_event_type event_type;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct tracing_data_event {
- struct perf_event_header header;
- u32 size;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct throttle_event {
- struct perf_event_header header;
- u64 time;
- u64 id;
- u64 stream_id;
-};
-union perf_event {
- struct perf_event_header header;
- struct mmap_event mmap;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct mmap2_event mmap2;
- struct comm_event comm;
- struct fork_event fork;
- struct lost_event lost;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct read_event read;
- struct sample_event sample;
- struct attr_event attr;
- struct event_type_event event_type;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct tracing_data_event tracing_data;
- struct build_id_event build_id;
-
- struct throttle_event throttle;
-};
-struct perf_tool;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct thread_map;
-typedef int(* perf_event__handler_t) (struct perf_tool * tool, union perf_event * event, struct perf_sample * sample, struct machine * machine);
-struct addr_location;
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/header.h b/perfprofd/quipper/kernel-headers/tools/perf/util/header.h
deleted file mode 100644
index 3aab42fd..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/header.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef __PERF_HEADER_H
-#define __PERF_HEADER_H
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-enum {
- HEADER_RESERVED = 0,
- HEADER_FIRST_FEATURE = 1,
- HEADER_TRACING_DATA = 1,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- HEADER_BUILD_ID,
- HEADER_HOSTNAME,
- HEADER_OSRELEASE,
- HEADER_VERSION,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- HEADER_ARCH,
- HEADER_NRCPUS,
- HEADER_CPUDESC,
- HEADER_CPUID,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- HEADER_TOTAL_MEM,
- HEADER_CMDLINE,
- HEADER_EVENT_DESC,
- HEADER_CPU_TOPOLOGY,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- HEADER_NUMA_TOPOLOGY,
- HEADER_BRANCH_STACK,
- HEADER_PMU_MAPPINGS,
- HEADER_GROUP_DESC,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- HEADER_LAST_FEATURE,
- HEADER_FEAT_BITS = 256,
-};
-enum perf_header_version {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- PERF_HEADER_VERSION_1,
- PERF_HEADER_VERSION_2,
-};
-struct perf_file_section {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 offset;
- u64 size;
-};
-struct perf_file_header {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 magic;
- u64 size;
- u64 attr_size;
- struct perf_file_section attrs;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- struct perf_file_section data;
- struct perf_file_section event_types;
- DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct perf_pipe_file_header {
- u64 magic;
- u64 size;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct perf_header;
-struct perf_session_env {
- char * hostname;
- char * os_release;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- char * version;
- char * arch;
- int nr_cpus_online;
- int nr_cpus_avail;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- char * cpu_desc;
- char * cpuid;
- unsigned long long total_mem;
- int nr_cmdline;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- char * cmdline;
- int nr_sibling_cores;
- char * sibling_cores;
- int nr_sibling_threads;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- char * sibling_threads;
- int nr_numa_nodes;
- char * numa_nodes;
- int nr_pmu_mappings;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- char * pmu_mappings;
- int nr_groups;
-};
-struct perf_header {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- enum perf_header_version version;
- bool needs_swap;
- u64 data_offset;
- u64 data_size;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 feat_offset;
- DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
- struct perf_session_env env;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct perf_evlist;
-struct perf_session;
-#endif
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/bitops.h b/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/bitops.h
deleted file mode 100644
index c6c47683..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/bitops.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _PERF_LINUX_BITOPS_H_
-#define _PERF_LINUX_BITOPS_H_
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#ifndef __WORDSIZE
-#define __WORDSIZE (__SIZEOF_LONG__ * 8)
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BITS_PER_LONG __WORDSIZE
-#define BITS_PER_BYTE 8
-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
-#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
-#define for_each_set_bit(bit,addr,size) for((bit) = find_first_bit((addr), (size)); (bit) < (size); (bit) = find_next_bit((addr), (size), (bit) + 1))
-#define for_each_set_bit_from(bit,addr,size) for((bit) = find_next_bit((addr), (size), (bit)); (bit) < (size); (bit) = find_next_bit((addr), (size), (bit) + 1))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-#if BITS_PER_LONG == 64
-#endif
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/kernel/kernel.h b/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/kernel/kernel.h
deleted file mode 100644
index d589c85d..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/kernel/kernel.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef PERF_LINUX_KERNEL_H_
-#define PERF_LINUX_KERNEL_H_
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define PERF_ALIGN(x,a) __PERF_ALIGN_MASK(x, (typeof(x)) (a) - 1)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define __PERF_ALIGN_MASK(x,mask) (((x) + (mask)) & ~(mask))
-#ifndef offsetof
-#define offsetof(TYPE,MEMBER) ((size_t) & ((TYPE *) 0)->MEMBER)
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#ifndef container_of
-#define container_of(ptr,type,member) ({ const typeof(((type *) 0)->member) * __mptr = (ptr); (type *) ((char *) __mptr - offsetof(type, member)); })
-#endif
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int : - ! ! (e); }))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#ifndef max
-#define max(x,y) ({ typeof(x) _max1 = (x); typeof(y) _max2 = (y); (void) (& _max1 == & _max2); _max1 > _max2 ? _max1 : _max2; })
-#endif
-#ifndef min
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define min(x,y) ({ typeof(x) _min1 = (x); typeof(y) _min2 = (y); (void) (& _min1 == & _min2); _min1 < _min2 ? _min1 : _min2; })
-#endif
-#ifndef roundup
-#define roundup(x,y) (\
-{ const typeof(y) __y = y; (((x) + (__y - 1)) / __y) * __y; \
-} \
-)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#ifndef BUG_ON
-#ifdef NDEBUG
-#define BUG_ON(cond) do { if(cond) { } } while(0)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#else
-#define BUG_ON(cond) assert(! (cond))
-#endif
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define cpu_to_le64(x) (x)
-#define cpu_to_le32(x) (x)
-#ifndef pr_fmt
-#define pr_fmt(fmt) fmt
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#define pr_err(fmt,...) eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warning(fmt,...) eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_info(fmt,...) eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define pr_debug(fmt,...) eprintf(1, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debugN(n,fmt,...) eprintf(n, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debug2(fmt,...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debug3(fmt,...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define pr_debug4(fmt,...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
-#define __round_mask(x,y) ((__typeof__(x)) ((y) - 1))
-#define round_up(x,y) ((((x) - 1) | __round_mask(x, y)) + 1)
-#define round_down(x,y) ((x) & ~__round_mask(x, y))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/types.h b/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/types.h
deleted file mode 100644
index 9f139060..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/include/linux/types.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _PERF_LINUX_TYPES_H_
-#define _PERF_LINUX_TYPES_H_
-#ifndef __bitwise
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define __bitwise
-#endif
-#ifndef __le32
-typedef __u32 __bitwise __le32;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
-#define DECLARE_BITMAP(name,bits) unsigned long (name)[BITS_TO_LONGS(bits)]
-struct list_head {
- struct list_head * next, * prev;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-struct hlist_head {
- struct hlist_node * first;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct hlist_node {
- struct hlist_node * next, * * pprev;
-};
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/target.h b/perfprofd/quipper/kernel-headers/tools/perf/util/target.h
deleted file mode 100644
index e6c3d949..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/target.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _PERF_TARGET_H
-#define _PERF_TARGET_H
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct perf_target {
- const char * pid;
- const char * tid;
- const char * cpu_list;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- const char * uid_str;
- uid_t uid;
- bool system_wide;
- bool uses_mmap;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-enum perf_target_errno {
- PERF_ERRNO_TARGET__SUCCESS = 0,
- __PERF_ERRNO_TARGET__START = - 10000,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START,
- PERF_ERRNO_TARGET__PID_OVERRIDE_UID,
- PERF_ERRNO_TARGET__UID_OVERRIDE_CPU,
- PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM,
- PERF_ERRNO_TARGET__INVALID_UID,
- PERF_ERRNO_TARGET__USER_NOT_FOUND,
- __PERF_ERRNO_TARGET__END,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-enum perf_target_errno perf_target__validate(struct perf_target * target);
-enum perf_target_errno perf_target__parse_uid(struct perf_target * target);
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-
diff --git a/perfprofd/quipper/kernel-headers/tools/perf/util/types.h b/perfprofd/quipper/kernel-headers/tools/perf/util/types.h
deleted file mode 100644
index cf36814f..00000000
--- a/perfprofd/quipper/kernel-headers/tools/perf/util/types.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- *** To edit the content of this header, modify the corresponding
- *** source file (e.g. under external/kernel-headers/original/) then
- *** run bionic/libc/kernel/tools/update_all.py
- ***
- *** Any manual change here will be lost the next time this script will
- *** be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef __PERF_TYPES_H
-#define __PERF_TYPES_H
-typedef uint64_t u64;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-typedef int64_t s64;
-typedef unsigned int u32;
-typedef signed int s32;
-typedef unsigned short u16;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-typedef signed short s16;
-typedef unsigned char u8;
-typedef signed char s8;
-union u64_swap {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- u64 val64;
- u32 val32[2];
-};
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/perf.h b/perfprofd/quipper/original-kernel-headers/tools/perf/perf.h
deleted file mode 100644
index cf20187e..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/perf.h
+++ /dev/null
@@ -1,236 +0,0 @@
-#ifndef _PERF_PERF_H
-#define _PERF_PERF_H
-
-#include <asm/unistd.h>
-
-#if defined(__i386__)
-#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
-#define cpu_relax() asm volatile("rep; nop" ::: "memory");
-#define CPUINFO_PROC "model name"
-#ifndef __NR_perf_event_open
-# define __NR_perf_event_open 336
-#endif
-#endif
-
-#if defined(__x86_64__)
-#define rmb() asm volatile("lfence" ::: "memory")
-#define cpu_relax() asm volatile("rep; nop" ::: "memory");
-#define CPUINFO_PROC "model name"
-#ifndef __NR_perf_event_open
-# define __NR_perf_event_open 298
-#endif
-#endif
-
-#ifdef __powerpc__
-#include "../../arch/powerpc/include/uapi/asm/unistd.h"
-#define rmb() asm volatile ("sync" ::: "memory")
-#define cpu_relax() asm volatile ("" ::: "memory");
-#define CPUINFO_PROC "cpu"
-#endif
-
-#ifdef __s390__
-#define rmb() asm volatile("bcr 15,0" ::: "memory")
-#define cpu_relax() asm volatile("" ::: "memory");
-#endif
-
-#ifdef __sh__
-#if defined(__SH4A__) || defined(__SH5__)
-# define rmb() asm volatile("synco" ::: "memory")
-#else
-# define rmb() asm volatile("" ::: "memory")
-#endif
-#define cpu_relax() asm volatile("" ::: "memory")
-#define CPUINFO_PROC "cpu type"
-#endif
-
-#ifdef __hppa__
-#define rmb() asm volatile("" ::: "memory")
-#define cpu_relax() asm volatile("" ::: "memory");
-#define CPUINFO_PROC "cpu"
-#endif
-
-#ifdef __sparc__
-#define rmb() asm volatile("":::"memory")
-#define cpu_relax() asm volatile("":::"memory")
-#define CPUINFO_PROC "cpu"
-#endif
-
-#ifdef __alpha__
-#define rmb() asm volatile("mb" ::: "memory")
-#define cpu_relax() asm volatile("" ::: "memory")
-#define CPUINFO_PROC "cpu model"
-#endif
-
-#ifdef __ia64__
-#define rmb() asm volatile ("mf" ::: "memory")
-#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
-#define CPUINFO_PROC "model name"
-#endif
-
-#ifdef __arm__
-/*
- * Use the __kuser_memory_barrier helper in the CPU helper page. See
- * arch/arm/kernel/entry-armv.S in the kernel source for details.
- */
-#define rmb() ((void(*)(void))0xffff0fa0)()
-#define cpu_relax() asm volatile("":::"memory")
-#define CPUINFO_PROC "Processor"
-#endif
-
-#ifdef __aarch64__
-#define rmb() asm volatile("dmb ld" ::: "memory")
-#define cpu_relax() asm volatile("yield" ::: "memory")
-#endif
-
-#ifdef __mips__
-#define rmb() asm volatile( \
- ".set mips2\n\t" \
- "sync\n\t" \
- ".set mips0" \
- : /* no output */ \
- : /* no input */ \
- : "memory")
-#define cpu_relax() asm volatile("" ::: "memory")
-#define CPUINFO_PROC "cpu model"
-#endif
-
-#ifdef __arc__
-#define rmb() asm volatile("" ::: "memory")
-#define cpu_relax() rmb()
-#define CPUINFO_PROC "Processor"
-#endif
-
-#ifdef __metag__
-#define rmb() asm volatile("" ::: "memory")
-#define cpu_relax() asm volatile("" ::: "memory")
-#define CPUINFO_PROC "CPU"
-#endif
-
-#include <time.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-
-#include <linux/perf_event.h>
-#include "util/types.h"
-#include <stdbool.h>
-
-/*
- * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all
- * counters in the current task.
- */
-#define PR_TASK_PERF_EVENTS_DISABLE 31
-#define PR_TASK_PERF_EVENTS_ENABLE 32
-
-#ifndef NSEC_PER_SEC
-# define NSEC_PER_SEC 1000000000ULL
-#endif
-#ifndef NSEC_PER_USEC
-# define NSEC_PER_USEC 1000ULL
-#endif
-
-static inline unsigned long long rdclock(void)
-{
- struct timespec ts;
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
-}
-
-/*
- * Pick up some kernel type conventions:
- */
-#define __user
-#define asmlinkage
-
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#define min(x, y) ({ \
- typeof(x) _min1 = (x); \
- typeof(y) _min2 = (y); \
- (void) (&_min1 == &_min2); \
- _min1 < _min2 ? _min1 : _min2; })
-
-extern bool test_attr__enabled;
-void test_attr__init(void);
-void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
- int fd, int group_fd, unsigned long flags);
-
-static inline int
-sys_perf_event_open(struct perf_event_attr *attr,
- pid_t pid, int cpu, int group_fd,
- unsigned long flags)
-{
- int fd;
-
- fd = syscall(__NR_perf_event_open, attr, pid, cpu,
- group_fd, flags);
-
- if (unlikely(test_attr__enabled))
- test_attr__open(attr, pid, cpu, fd, group_fd, flags);
-
- return fd;
-}
-
-#define MAX_COUNTERS 256
-#define MAX_NR_CPUS 256
-
-struct ip_callchain {
- u64 nr;
- u64 ips[0];
-};
-
-struct branch_flags {
- u64 mispred:1;
- u64 predicted:1;
- u64 reserved:62;
-};
-
-struct branch_entry {
- u64 from;
- u64 to;
- struct branch_flags flags;
-};
-
-struct branch_stack {
- u64 nr;
- struct branch_entry entries[0];
-};
-
-extern const char *input_name;
-extern bool perf_host, perf_guest;
-extern const char perf_version_string[];
-
-void pthread__unblock_sigwinch(void);
-
-#include "util/target.h"
-
-enum perf_call_graph_mode {
- CALLCHAIN_NONE,
- CALLCHAIN_FP,
- CALLCHAIN_DWARF
-};
-
-struct perf_record_opts {
- struct perf_target target;
- int call_graph;
- bool group;
- bool inherit_stat;
- bool no_delay;
- bool no_inherit;
- bool no_samples;
- bool pipe_output;
- bool raw_samples;
- bool sample_address;
- bool sample_weight;
- bool sample_time;
- bool period;
- unsigned int freq;
- unsigned int mmap_pages;
- unsigned int user_freq;
- u64 branch_stack;
- u64 default_interval;
- u64 user_interval;
- u16 stack_dump_size;
-};
-
-#endif
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/build-id.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/build-id.h
deleted file mode 100644
index a811f5c6..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/build-id.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef PERF_BUILD_ID_H_
-#define PERF_BUILD_ID_H_ 1
-
-#define BUILD_ID_SIZE 20
-
-#include "tool.h"
-#include "types.h"
-
-extern struct perf_tool build_id__mark_dso_hit_ops;
-struct dso;
-
-int build_id__sprintf(const u8 *build_id, int len, char *bf);
-char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
-
-int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
- struct perf_sample *sample, struct perf_evsel *evsel,
- struct machine *machine);
-
-#endif
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/event.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/event.h
deleted file mode 100644
index c67ecc45..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/event.h
+++ /dev/null
@@ -1,263 +0,0 @@
-#ifndef __PERF_RECORD_H
-#define __PERF_RECORD_H
-
-#include <limits.h>
-#include <stdio.h>
-
-#include "../perf.h"
-#include "map.h"
-#include "build-id.h"
-
-struct mmap_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 start;
- u64 len;
- u64 pgoff;
- char filename[PATH_MAX];
-};
-
-struct mmap2_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 start;
- u64 len;
- u64 pgoff;
- u32 maj;
- u32 min;
- u64 ino;
- u64 ino_generation;
- char filename[PATH_MAX];
-};
-
-struct comm_event {
- struct perf_event_header header;
- u32 pid, tid;
- char comm[16];
-};
-
-struct fork_event {
- struct perf_event_header header;
- u32 pid, ppid;
- u32 tid, ptid;
- u64 time;
-};
-
-struct lost_event {
- struct perf_event_header header;
- u64 id;
- u64 lost;
-};
-
-/*
- * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
- */
-struct read_event {
- struct perf_event_header header;
- u32 pid, tid;
- u64 value;
- u64 time_enabled;
- u64 time_running;
- u64 id;
-};
-
-
-#define PERF_SAMPLE_MASK \
- (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
- PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
- PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \
- PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
- PERF_SAMPLE_IDENTIFIER)
-
-struct sample_event {
- struct perf_event_header header;
- u64 array[];
-};
-
-struct regs_dump {
- u64 abi;
- u64 *regs;
-};
-
-struct stack_dump {
- u16 offset;
- u64 size;
- char *data;
-};
-
-struct sample_read_value {
- u64 value;
- u64 id;
-};
-
-struct sample_read {
- u64 time_enabled;
- u64 time_running;
- union {
- struct {
- u64 nr;
- struct sample_read_value *values;
- } group;
- struct sample_read_value one;
- };
-};
-
-struct perf_sample {
- u64 ip;
- u32 pid, tid;
- u64 time;
- u64 addr;
- u64 id;
- u64 stream_id;
- u64 period;
- u64 weight;
- u32 cpu;
- u32 raw_size;
- u64 data_src;
- void *raw_data;
- struct ip_callchain *callchain;
- struct branch_stack *branch_stack;
- struct regs_dump user_regs;
- struct stack_dump user_stack;
- struct sample_read read;
-};
-
-#define PERF_MEM_DATA_SRC_NONE \
- (PERF_MEM_S(OP, NA) |\
- PERF_MEM_S(LVL, NA) |\
- PERF_MEM_S(SNOOP, NA) |\
- PERF_MEM_S(LOCK, NA) |\
- PERF_MEM_S(TLB, NA))
-
-struct build_id_event {
- struct perf_event_header header;
- pid_t pid;
- u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
- char filename[];
-};
-
-enum perf_user_event_type { /* above any possible kernel type */
- PERF_RECORD_USER_TYPE_START = 64,
- PERF_RECORD_HEADER_ATTR = 64,
- PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */
- PERF_RECORD_HEADER_TRACING_DATA = 66,
- PERF_RECORD_HEADER_BUILD_ID = 67,
- PERF_RECORD_FINISHED_ROUND = 68,
- PERF_RECORD_HEADER_MAX
-};
-
-struct attr_event {
- struct perf_event_header header;
- struct perf_event_attr attr;
- u64 id[];
-};
-
-#define MAX_EVENT_NAME 64
-
-struct perf_trace_event_type {
- u64 event_id;
- char name[MAX_EVENT_NAME];
-};
-
-struct event_type_event {
- struct perf_event_header header;
- struct perf_trace_event_type event_type;
-};
-
-struct tracing_data_event {
- struct perf_event_header header;
- u32 size;
-};
-
-union perf_event {
- struct perf_event_header header;
- struct mmap_event mmap;
- struct mmap2_event mmap2;
- struct comm_event comm;
- struct fork_event fork;
- struct lost_event lost;
- struct read_event read;
- struct sample_event sample;
- struct attr_event attr;
- struct event_type_event event_type;
- struct tracing_data_event tracing_data;
- struct build_id_event build_id;
-};
-
-void perf_event__print_totals(void);
-
-struct perf_tool;
-struct thread_map;
-
-typedef int (*perf_event__handler_t)(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-
-int perf_event__synthesize_thread_map(struct perf_tool *tool,
- struct thread_map *threads,
- perf_event__handler_t process,
- struct machine *machine);
-int perf_event__synthesize_threads(struct perf_tool *tool,
- perf_event__handler_t process,
- struct machine *machine);
-int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
- perf_event__handler_t process,
- struct machine *machine,
- const char *symbol_name);
-
-int perf_event__synthesize_modules(struct perf_tool *tool,
- perf_event__handler_t process,
- struct machine *machine);
-
-int perf_event__process_comm(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-int perf_event__process_lost(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-int perf_event__process_mmap(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-int perf_event__process_mmap2(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-int perf_event__process_fork(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-int perf_event__process_exit(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-int perf_event__process(struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine);
-
-struct addr_location;
-int perf_event__preprocess_sample(const union perf_event *self,
- struct machine *machine,
- struct addr_location *al,
- struct perf_sample *sample);
-
-const char *perf_event__name(unsigned int id);
-
-size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
- u64 sample_regs_user, u64 read_format);
-int perf_event__synthesize_sample(union perf_event *event, u64 type,
- u64 sample_regs_user, u64 read_format,
- const struct perf_sample *sample,
- bool swapped);
-
-size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
-size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
-size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
-size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
-size_t perf_event__fprintf(union perf_event *event, FILE *fp);
-
-#endif /* __PERF_RECORD_H */
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/header.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/header.h
deleted file mode 100644
index 307c9aed..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/header.h
+++ /dev/null
@@ -1,159 +0,0 @@
-#ifndef __PERF_HEADER_H
-#define __PERF_HEADER_H
-
-#include <linux/perf_event.h>
-#include <sys/types.h>
-#include <stdbool.h>
-#include "types.h"
-#include "event.h"
-
-#include <linux/bitmap.h>
-
-enum {
- HEADER_RESERVED = 0, /* always cleared */
- HEADER_FIRST_FEATURE = 1,
- HEADER_TRACING_DATA = 1,
- HEADER_BUILD_ID,
-
- HEADER_HOSTNAME,
- HEADER_OSRELEASE,
- HEADER_VERSION,
- HEADER_ARCH,
- HEADER_NRCPUS,
- HEADER_CPUDESC,
- HEADER_CPUID,
- HEADER_TOTAL_MEM,
- HEADER_CMDLINE,
- HEADER_EVENT_DESC,
- HEADER_CPU_TOPOLOGY,
- HEADER_NUMA_TOPOLOGY,
- HEADER_BRANCH_STACK,
- HEADER_PMU_MAPPINGS,
- HEADER_GROUP_DESC,
- HEADER_LAST_FEATURE,
- HEADER_FEAT_BITS = 256,
-};
-
-enum perf_header_version {
- PERF_HEADER_VERSION_1,
- PERF_HEADER_VERSION_2,
-};
-
-struct perf_file_section {
- u64 offset;
- u64 size;
-};
-
-struct perf_file_header {
- u64 magic;
- u64 size;
- u64 attr_size;
- struct perf_file_section attrs;
- struct perf_file_section data;
- /* event_types is ignored */
- struct perf_file_section event_types;
- DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
-};
-
-struct perf_pipe_file_header {
- u64 magic;
- u64 size;
-};
-
-struct perf_header;
-
-int perf_file_header__read(struct perf_file_header *header,
- struct perf_header *ph, int fd);
-
-struct perf_session_env {
- char *hostname;
- char *os_release;
- char *version;
- char *arch;
- int nr_cpus_online;
- int nr_cpus_avail;
- char *cpu_desc;
- char *cpuid;
- unsigned long long total_mem;
-
- int nr_cmdline;
- char *cmdline;
- int nr_sibling_cores;
- char *sibling_cores;
- int nr_sibling_threads;
- char *sibling_threads;
- int nr_numa_nodes;
- char *numa_nodes;
- int nr_pmu_mappings;
- char *pmu_mappings;
- int nr_groups;
-};
-
-struct perf_header {
- enum perf_header_version version;
- bool needs_swap;
- u64 data_offset;
- u64 data_size;
- u64 feat_offset;
- DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
- struct perf_session_env env;
-};
-
-struct perf_evlist;
-struct perf_session;
-
-int perf_session__read_header(struct perf_session *session);
-int perf_session__write_header(struct perf_session *session,
- struct perf_evlist *evlist,
- int fd, bool at_exit);
-int perf_header__write_pipe(int fd);
-
-void perf_header__set_feat(struct perf_header *header, int feat);
-void perf_header__clear_feat(struct perf_header *header, int feat);
-bool perf_header__has_feat(const struct perf_header *header, int feat);
-
-int perf_header__set_cmdline(int argc, const char **argv);
-
-int perf_header__process_sections(struct perf_header *header, int fd,
- void *data,
- int (*process)(struct perf_file_section *section,
- struct perf_header *ph,
- int feat, int fd, void *data));
-
-int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
-
-int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
- const char *name, bool is_kallsyms, bool is_vdso);
-int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
-
-int perf_event__synthesize_attr(struct perf_tool *tool,
- struct perf_event_attr *attr, u32 ids, u64 *id,
- perf_event__handler_t process);
-int perf_event__synthesize_attrs(struct perf_tool *tool,
- struct perf_session *session,
- perf_event__handler_t process);
-int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
- struct perf_evlist **pevlist);
-
-int perf_event__synthesize_tracing_data(struct perf_tool *tool,
- int fd, struct perf_evlist *evlist,
- perf_event__handler_t process);
-int perf_event__process_tracing_data(struct perf_tool *tool,
- union perf_event *event,
- struct perf_session *session);
-
-int perf_event__synthesize_build_id(struct perf_tool *tool,
- struct dso *pos, u16 misc,
- perf_event__handler_t process,
- struct machine *machine);
-int perf_event__process_build_id(struct perf_tool *tool,
- union perf_event *event,
- struct perf_session *session);
-bool is_perf_magic(u64 magic);
-
-/*
- * arch specific callback
- */
-int get_cpuid(char *buffer, size_t sz);
-
-#endif /* __PERF_HEADER_H */
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/bitops.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/bitops.h
deleted file mode 100644
index 45cf10a5..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/bitops.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#ifndef _PERF_LINUX_BITOPS_H_
-#define _PERF_LINUX_BITOPS_H_
-
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <asm/hweight.h>
-
-#ifndef __WORDSIZE
-#define __WORDSIZE (__SIZEOF_LONG__ * 8)
-#endif
-
-#define BITS_PER_LONG __WORDSIZE
-#define BITS_PER_BYTE 8
-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
-#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
-#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
-
-#define for_each_set_bit(bit, addr, size) \
- for ((bit) = find_first_bit((addr), (size)); \
- (bit) < (size); \
- (bit) = find_next_bit((addr), (size), (bit) + 1))
-
-/* same as for_each_set_bit() but use bit as value to start with */
-#define for_each_set_bit_from(bit, addr, size) \
- for ((bit) = find_next_bit((addr), (size), (bit)); \
- (bit) < (size); \
- (bit) = find_next_bit((addr), (size), (bit) + 1))
-
-static inline void set_bit(int nr, unsigned long *addr)
-{
- addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
-}
-
-static inline void clear_bit(int nr, unsigned long *addr)
-{
- addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
-}
-
-static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
-{
- return ((1UL << (nr % BITS_PER_LONG)) &
- (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
-}
-
-static inline unsigned long hweight_long(unsigned long w)
-{
- return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
-}
-
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static __always_inline unsigned long __ffs(unsigned long word)
-{
- int num = 0;
-
-#if BITS_PER_LONG == 64
- if ((word & 0xffffffff) == 0) {
- num += 32;
- word >>= 32;
- }
-#endif
- if ((word & 0xffff) == 0) {
- num += 16;
- word >>= 16;
- }
- if ((word & 0xff) == 0) {
- num += 8;
- word >>= 8;
- }
- if ((word & 0xf) == 0) {
- num += 4;
- word >>= 4;
- }
- if ((word & 0x3) == 0) {
- num += 2;
- word >>= 2;
- }
- if ((word & 0x1) == 0)
- num += 1;
- return num;
-}
-
-/*
- * Find the first set bit in a memory region.
- */
-static inline unsigned long
-find_first_bit(const unsigned long *addr, unsigned long size)
-{
- const unsigned long *p = addr;
- unsigned long result = 0;
- unsigned long tmp;
-
- while (size & ~(BITS_PER_LONG-1)) {
- if ((tmp = *(p++)))
- goto found;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
-
- tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found:
- return result + __ffs(tmp);
-}
-
-/*
- * Find the next set bit in a memory region.
- */
-static inline unsigned long
-find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + BITOP_WORD(offset);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset %= BITS_PER_LONG;
- if (offset) {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < BITS_PER_LONG)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG-1)) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (BITS_PER_LONG - size));
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-#endif
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/kernel/kernel.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/kernel/kernel.h
deleted file mode 100644
index d8c927c8..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/kernel/kernel.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef PERF_LINUX_KERNEL_H_
-#define PERF_LINUX_KERNEL_H_
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-
-#define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-#define __PERF_ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
-
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-
-#ifndef container_of
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- const typeof(((type *)0)->member) * __mptr = (ptr); \
- (type *)((char *)__mptr - offsetof(type, member)); })
-#endif
-
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
-
-#ifndef max
-#define max(x, y) ({ \
- typeof(x) _max1 = (x); \
- typeof(y) _max2 = (y); \
- (void) (&_max1 == &_max2); \
- _max1 > _max2 ? _max1 : _max2; })
-#endif
-
-#ifndef min
-#define min(x, y) ({ \
- typeof(x) _min1 = (x); \
- typeof(y) _min2 = (y); \
- (void) (&_min1 == &_min2); \
- _min1 < _min2 ? _min1 : _min2; })
-#endif
-
-#ifndef roundup
-#define roundup(x, y) ( \
-{ \
- const typeof(y) __y = y; \
- (((x) + (__y - 1)) / __y) * __y; \
-} \
-)
-#endif
-
-#ifndef BUG_ON
-#ifdef NDEBUG
-#define BUG_ON(cond) do { if (cond) {} } while (0)
-#else
-#define BUG_ON(cond) assert(!(cond))
-#endif
-#endif
-
-/*
- * Both need more care to handle endianness
- * (Don't use bitmap_copy_le() for now)
- */
-#define cpu_to_le64(x) (x)
-#define cpu_to_le32(x) (x)
-
-static inline int
-vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
-{
- int i;
- ssize_t ssize = size;
-
- i = vsnprintf(buf, size, fmt, args);
-
- return (i >= ssize) ? (ssize - 1) : i;
-}
-
-static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
-{
- va_list args;
- ssize_t ssize = size;
- int i;
-
- va_start(args, fmt);
- i = vsnprintf(buf, size, fmt, args);
- va_end(args);
-
- return (i >= ssize) ? (ssize - 1) : i;
-}
-
-static inline unsigned long
-simple_strtoul(const char *nptr, char **endptr, int base)
-{
- return strtoul(nptr, endptr, base);
-}
-
-int eprintf(int level,
- const char *fmt, ...) __attribute__((format(printf, 2, 3)));
-
-#ifndef pr_fmt
-#define pr_fmt(fmt) fmt
-#endif
-
-#define pr_err(fmt, ...) \
- eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warning(fmt, ...) \
- eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_info(fmt, ...) \
- eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debug(fmt, ...) \
- eprintf(1, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debugN(n, fmt, ...) \
- eprintf(n, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
-
-/*
- * This looks more complex than it should be. But we need to
- * get the type for the ~ right in round_down (it needs to be
- * as wide as the result!), and we want to evaluate the macro
- * arguments just once each.
- */
-#define __round_mask(x, y) ((__typeof__(x))((y)-1))
-#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
-#define round_down(x, y) ((x) & ~__round_mask(x, y))
-
-#endif
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/types.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/types.h
deleted file mode 100644
index eb464786..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/include/linux/types.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _PERF_LINUX_TYPES_H_
-#define _PERF_LINUX_TYPES_H_
-
-#include <asm/types.h>
-
-#ifndef __bitwise
-#define __bitwise
-#endif
-
-#ifndef __le32
-typedef __u32 __bitwise __le32;
-#endif
-
-#define DECLARE_BITMAP(name,bits) \
- unsigned long name[BITS_TO_LONGS(bits)]
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next, **pprev;
-};
-
-#endif
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/target.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/target.h
deleted file mode 100644
index a4be8575..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/target.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _PERF_TARGET_H
-#define _PERF_TARGET_H
-
-#include <stdbool.h>
-#include <sys/types.h>
-
-struct perf_target {
- const char *pid;
- const char *tid;
- const char *cpu_list;
- const char *uid_str;
- uid_t uid;
- bool system_wide;
- bool uses_mmap;
-};
-
-enum perf_target_errno {
- PERF_ERRNO_TARGET__SUCCESS = 0,
-
- /*
- * Choose an arbitrary negative big number not to clash with standard
- * errno since SUS requires the errno has distinct positive values.
- * See 'Issue 6' in the link below.
- *
- * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
- */
- __PERF_ERRNO_TARGET__START = -10000,
-
-
- /* for perf_target__validate() */
- PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START,
- PERF_ERRNO_TARGET__PID_OVERRIDE_UID,
- PERF_ERRNO_TARGET__UID_OVERRIDE_CPU,
- PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM,
- PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM,
-
- /* for perf_target__parse_uid() */
- PERF_ERRNO_TARGET__INVALID_UID,
- PERF_ERRNO_TARGET__USER_NOT_FOUND,
-
- __PERF_ERRNO_TARGET__END,
-};
-
-enum perf_target_errno perf_target__validate(struct perf_target *target);
-enum perf_target_errno perf_target__parse_uid(struct perf_target *target);
-
-int perf_target__strerror(struct perf_target *target, int errnum, char *buf,
- size_t buflen);
-
-static inline bool perf_target__has_task(struct perf_target *target)
-{
- return target->tid || target->pid || target->uid_str;
-}
-
-static inline bool perf_target__has_cpu(struct perf_target *target)
-{
- return target->system_wide || target->cpu_list;
-}
-
-static inline bool perf_target__none(struct perf_target *target)
-{
- return !perf_target__has_task(target) && !perf_target__has_cpu(target);
-}
-
-#endif /* _PERF_TARGET_H */
diff --git a/perfprofd/quipper/original-kernel-headers/tools/perf/util/types.h b/perfprofd/quipper/original-kernel-headers/tools/perf/util/types.h
deleted file mode 100644
index c51fa6b7..00000000
--- a/perfprofd/quipper/original-kernel-headers/tools/perf/util/types.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __PERF_TYPES_H
-#define __PERF_TYPES_H
-
-#include <stdint.h>
-
-/*
- * We define u64 as uint64_t for every architecture
- * so that we can print it with "%"PRIx64 without getting warnings.
- */
-typedef uint64_t u64;
-typedef int64_t s64;
-typedef unsigned int u32;
-typedef signed int s32;
-typedef unsigned short u16;
-typedef signed short s16;
-typedef unsigned char u8;
-typedef signed char s8;
-
-union u64_swap {
- u64 val64;
- u32 val32[2];
-};
-
-#endif /* __PERF_TYPES_H */
diff --git a/perfprofd/quipper/perf_internals.h b/perfprofd/quipper/perf_internals.h
deleted file mode 100644
index a779d3c8..00000000
--- a/perfprofd/quipper/perf_internals.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-**
-** Copyright 2015, 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.
-*/
-
-#ifndef PERF_INTERNALS_H
-#define PERF_INTERNALS_H
-
-#include <linux/perf_event.h>
-#include "kernel-headers/tools/perf/util/types.h"
-#include "kernel-headers/tools/perf/util/include/linux/bitops.h"
-#include "kernel-headers/tools/perf/util/include/linux/types.h"
-#include "kernel-headers/tools/perf/util/build-id.h"
-#include "kernel-headers/tools/perf/util/include/linux/kernel/kernel.h"
-#include "kernel-headers/tools/perf/util/header.h"
-#include "kernel-headers/tools/perf/util/event.h"
-#include "kernel-headers/tools/perf/util/target.h"
-#include "kernel-headers/tools/perf/perf.h"
-
-// The first 64 bits of the perf header, used as a perf data file ID tag.
-const uint64_t kPerfMagic = 0x32454c4946524550LL; // "PERFILE2" little-endian
-
-#undef max
-#undef min
-
-//
-// Wrapper class to manage creation/deletion of storage associated
-// with perf_sample structs.
-//
-class PerfSampleCustodian {
- public:
- explicit PerfSampleCustodian(struct perf_sample& sample)
- : sample_(sample) {
- sample.raw_data = NULL;
- sample.callchain = NULL;
- sample.branch_stack = NULL;
- }
- ~PerfSampleCustodian() {
- if (sample_.callchain)
- delete [] sample_.callchain;
- if (sample_.branch_stack)
- delete [] sample_.branch_stack;
- if (sample_.branch_stack)
- delete [] reinterpret_cast<char*>(sample_.raw_data);
- }
- private:
- struct perf_sample& sample_;
-};
-
-typedef perf_event event_t;
-
-//
-// Custom / user-specific records emitted by simpleperf.
-// These need to be kept in sync with the simpleperf sources.
-//
-enum simpleperf_record_type {
- SIMPLE_PERF_RECORD_TYPE_START = 32768,
- SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
- SIMPLE_PERF_RECORD_DSO,
- SIMPLE_PERF_RECORD_SYMBOL,
- SIMPLE_PERF_RECORD_SPLIT,
- SIMPLE_PERF_RECORD_SPLIT_END,
-};
-
-#endif
diff --git a/perfprofd/quipper/perf_parser.cc b/perfprofd/quipper/perf_parser.cc
deleted file mode 100644
index c529d25b..00000000
--- a/perfprofd/quipper/perf_parser.cc
+++ /dev/null
@@ -1,591 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "perf_parser.h"
-
-#include <algorithm>
-#include <cstdio>
-#include <set>
-
-#include "base/logging.h"
-
-#include "address_mapper.h"
-#include "quipper_string.h"
-#include "perf_utils.h"
-
-namespace quipper {
-
-namespace {
-
-struct EventAndTime {
- ParsedEvent* event;
- uint64_t time;
-};
-
-// Returns true if |e1| has an earlier timestamp than |e2|. The args are const
-// pointers instead of references because of the way this function is used when
-// calling std::stable_sort.
-bool CompareParsedEventTimes(const std::unique_ptr<EventAndTime>& e1,
- const std::unique_ptr<EventAndTime>& e2) {
- return (e1->time < e2->time);
-}
-
-// Kernel MMAP entry pid appears as -1
-const uint32_t kKernelPid = UINT32_MAX;
-
-// Name and ID of the kernel swapper process.
-const char kSwapperCommandName[] = "swapper";
-const uint32_t kSwapperPid = 0;
-
-bool IsNullBranchStackEntry(const struct branch_entry& entry) {
- return (!entry.from && !entry.to);
-}
-
-} // namespace
-
-PerfParser::PerfParser()
- : kernel_mapper_(new AddressMapper)
-{}
-
-PerfParser::~PerfParser() {}
-
-PerfParser::PerfParser(const PerfParser::Options& options) {
- options_ = options;
-}
-
-void PerfParser::set_options(const PerfParser::Options& options) {
- options_ = options;
-}
-
-bool PerfParser::ParseRawEvents() {
- process_mappers_.clear();
- parsed_events_.resize(events_.size());
- for (size_t i = 0; i < events_.size(); ++i) {
- ParsedEvent& parsed_event = parsed_events_[i];
- parsed_event.raw_event = events_[i].get();
- }
- MaybeSortParsedEvents();
- if (!ProcessEvents()) {
- return false;
- }
-
- if (!options_.discard_unused_events)
- return true;
-
- // Some MMAP/MMAP2 events' mapped regions will not have any samples. These
- // MMAP/MMAP2 events should be dropped. |parsed_events_| should be
- // reconstructed without these events.
- size_t write_index = 0;
- size_t read_index;
- for (read_index = 0; read_index < parsed_events_.size(); ++read_index) {
- const ParsedEvent& event = parsed_events_[read_index];
- if ((event.raw_event->header.type == PERF_RECORD_MMAP ||
- event.raw_event->header.type == PERF_RECORD_MMAP2) &&
- event.num_samples_in_mmap_region == 0) {
- continue;
- }
- if (read_index != write_index)
- parsed_events_[write_index] = event;
- ++write_index;
- }
- CHECK_LE(write_index, parsed_events_.size());
- parsed_events_.resize(write_index);
-
- // Now regenerate the sorted event list again. These are pointers to events
- // so they must be regenerated after a resize() of the ParsedEvent vector.
- MaybeSortParsedEvents();
-
- return true;
-}
-
-void PerfParser::MaybeSortParsedEvents() {
- if (!(sample_type_ & PERF_SAMPLE_TIME)) {
- parsed_events_sorted_by_time_.resize(parsed_events_.size());
- for (size_t i = 0; i < parsed_events_.size(); ++i) {
- parsed_events_sorted_by_time_[i] = &parsed_events_[i];
- }
- return;
- }
- std::vector<std::unique_ptr<EventAndTime>> events_and_times;
- events_and_times.resize(parsed_events_.size());
- for (size_t i = 0; i < parsed_events_.size(); ++i) {
- std::unique_ptr<EventAndTime> event_and_time(new EventAndTime);
-
- // Store the timestamp and event pointer in an array.
- event_and_time->event = &parsed_events_[i];
-
- struct perf_sample sample_info;
- PerfSampleCustodian custodian(sample_info);
- CHECK(ReadPerfSampleInfo(*parsed_events_[i].raw_event, &sample_info));
- event_and_time->time = sample_info.time;
-
- events_and_times[i] = std::move(event_and_time);
- }
- // Sort the events based on timestamp, and then populate the sorted event
- // vector in sorted order.
- std::stable_sort(events_and_times.begin(), events_and_times.end(),
- CompareParsedEventTimes);
-
- parsed_events_sorted_by_time_.resize(events_and_times.size());
- for (unsigned int i = 0; i < events_and_times.size(); ++i) {
- parsed_events_sorted_by_time_[i] = events_and_times[i]->event;
- }
-}
-
-bool PerfParser::ProcessEvents() {
- memset(&stats_, 0, sizeof(stats_));
-
- stats_.did_remap = false; // Explicitly clear the remap flag.
-
- // Pid 0 is called the swapper process. Even though perf does not record a
- // COMM event for pid 0, we act like we did receive a COMM event for it. Perf
- // does this itself, example:
- // http://lxr.free-electrons.com/source/tools/perf/util/session.c#L1120
- commands_.insert(kSwapperCommandName);
- pidtid_to_comm_map_[std::make_pair(kSwapperPid, kSwapperPid)] =
- &(*commands_.find(kSwapperCommandName));
-
- // NB: Not necessarily actually sorted by time.
- for (unsigned int i = 0; i < parsed_events_sorted_by_time_.size(); ++i) {
- ParsedEvent& parsed_event = *parsed_events_sorted_by_time_[i];
- event_t& event = *parsed_event.raw_event;
- switch (event.header.type) {
- case PERF_RECORD_SAMPLE:
- // SAMPLE doesn't have any fields to log at a fixed,
- // previously-endian-swapped location. This used to log ip.
- VLOG(1) << "SAMPLE";
- ++stats_.num_sample_events;
-
- if (MapSampleEvent(&parsed_event)) {
- ++stats_.num_sample_events_mapped;
- }
- break;
- case PERF_RECORD_MMAP: {
- VLOG(1) << "MMAP: " << event.mmap.filename;
- ++stats_.num_mmap_events;
- // Use the array index of the current mmap event as a unique identifier.
- CHECK(MapMmapEvent(&event.mmap, i)) << "Unable to map MMAP event!";
- // No samples in this MMAP region yet, hopefully.
- parsed_event.num_samples_in_mmap_region = 0;
- DSOInfo dso_info;
- // TODO(sque): Add Build ID as well.
- dso_info.name = event.mmap.filename;
- dso_set_.insert(dso_info);
- break;
- }
- case PERF_RECORD_MMAP2: {
- VLOG(1) << "MMAP2: " << event.mmap2.filename;
- ++stats_.num_mmap_events;
- // Use the array index of the current mmap event as a unique identifier.
- CHECK(MapMmapEvent(&event.mmap2, i)) << "Unable to map MMAP2 event!";
- // No samples in this MMAP region yet, hopefully.
- parsed_event.num_samples_in_mmap_region = 0;
- DSOInfo dso_info;
- // TODO(sque): Add Build ID as well.
- dso_info.name = event.mmap2.filename;
- dso_set_.insert(dso_info);
- break;
- }
- case PERF_RECORD_FORK:
- VLOG(1) << "FORK: " << event.fork.ppid << ":" << event.fork.ptid
- << " -> " << event.fork.pid << ":" << event.fork.tid;
- ++stats_.num_fork_events;
- CHECK(MapForkEvent(event.fork)) << "Unable to map FORK event!";
- break;
- case PERF_RECORD_EXIT:
- // EXIT events have the same structure as FORK events.
- VLOG(1) << "EXIT: " << event.fork.ppid << ":" << event.fork.ptid;
- ++stats_.num_exit_events;
- break;
- case PERF_RECORD_COMM:
- VLOG(1) << "COMM: " << event.comm.pid << ":" << event.comm.tid << ": "
- << event.comm.comm;
- ++stats_.num_comm_events;
- CHECK(MapCommEvent(event.comm));
- commands_.insert(event.comm.comm);
- pidtid_to_comm_map_[std::make_pair(event.comm.pid, event.comm.tid)] =
- &(*commands_.find(event.comm.comm));
- break;
- case PERF_RECORD_LOST:
- case PERF_RECORD_THROTTLE:
- case PERF_RECORD_UNTHROTTLE:
- case PERF_RECORD_READ:
- case PERF_RECORD_MAX:
- VLOG(1) << "Parsed event type: " << event.header.type
- << ". Doing nothing.";
- break;
- case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
- case SIMPLE_PERF_RECORD_DSO:
- case SIMPLE_PERF_RECORD_SYMBOL:
- case SIMPLE_PERF_RECORD_SPLIT:
- case SIMPLE_PERF_RECORD_SPLIT_END:
- break;
- default:
- LOG(ERROR) << "Unknown event type: " << event.header.type;
- return false;
- }
- }
-
- // Print stats collected from parsing.
- DLOG(INFO) << "Parser processed: "
- << stats_.num_mmap_events << " MMAP/MMAP2 events, "
- << stats_.num_comm_events << " COMM events, "
- << stats_.num_fork_events << " FORK events, "
- << stats_.num_exit_events << " EXIT events, "
- << stats_.num_sample_events << " SAMPLE events, "
- << stats_.num_sample_events_mapped << " of these were mapped";
-
- float sample_mapping_percentage =
- static_cast<float>(stats_.num_sample_events_mapped) /
- stats_.num_sample_events * 100.;
- float threshold = options_.sample_mapping_percentage_threshold;
- if (sample_mapping_percentage < threshold) {
- LOG(WARNING) << "Mapped " << static_cast<int>(sample_mapping_percentage)
- << "% of samples, expected at least "
- << static_cast<int>(threshold) << "%";
- return false;
- }
- stats_.did_remap = options_.do_remap;
- return true;
-}
-
-bool PerfParser::MapSampleEvent(ParsedEvent* parsed_event) {
- bool mapping_failed = false;
-
- // Find the associated command.
- if (!(sample_type_ & PERF_SAMPLE_IP && sample_type_ & PERF_SAMPLE_TID))
- return false;
- perf_sample sample_info;
- PerfSampleCustodian custodian(sample_info);
- if (!ReadPerfSampleInfo(*parsed_event->raw_event, &sample_info))
- return false;
- PidTid pidtid = std::make_pair(sample_info.pid, sample_info.tid);
- const auto comm_iter = pidtid_to_comm_map_.find(pidtid);
- if (comm_iter != pidtid_to_comm_map_.end()) {
- parsed_event->set_command(comm_iter->second);
- }
- {
- PidTid pidtid_main = std::make_pair(sample_info.pid, sample_info.pid);
- const auto main_iter = pidtid_to_comm_map_.find(pidtid_main);
- if (main_iter != pidtid_to_comm_map_.end()) {
- parsed_event->set_process_command(main_iter->second);
- }
- }
-
- const uint64_t unmapped_event_ip = sample_info.ip;
-
- // Map the event IP itself.
- if (!MapIPAndPidAndGetNameAndOffset(sample_info.ip,
- sample_info.pid,
- &sample_info.ip,
- &parsed_event->dso_and_offset)) {
- mapping_failed = true;
- }
-
- if (sample_info.callchain &&
- !MapCallchain(sample_info.ip,
- sample_info.pid,
- unmapped_event_ip,
- sample_info.callchain,
- parsed_event)) {
- mapping_failed = true;
- }
-
- if (sample_info.branch_stack &&
- !MapBranchStack(sample_info.pid,
- sample_info.branch_stack,
- parsed_event)) {
- mapping_failed = true;
- }
-
- if (options_.do_remap) {
- // Write the remapped data back to the raw event regardless of
- // whether it was entirely successfully remapped. A single failed
- // remap should not invalidate all the other remapped entries.
- if (!WritePerfSampleInfo(sample_info, parsed_event->raw_event)) {
- LOG(ERROR) << "Failed to write back remapped sample info.";
- return false;
- }
- }
-
- return !mapping_failed;
-}
-
-bool PerfParser::MapCallchain(const uint64_t ip,
- const uint32_t pid,
- const uint64_t original_event_addr,
- struct ip_callchain* callchain,
- ParsedEvent* parsed_event) {
- if (!callchain) {
- LOG(ERROR) << "NULL call stack data.";
- return false;
- }
-
- bool mapping_failed = false;
-
- // If the callchain's length is 0, there is no work to do.
- if (callchain->nr == 0)
- return true;
-
- // Keeps track of whether the current entry is kernel or user.
- parsed_event->callchain.resize(callchain->nr);
- int num_entries_mapped = 0;
- for (unsigned int j = 0; j < callchain->nr; ++j) {
- uint64_t entry = callchain->ips[j];
- // When a callchain context entry is found, do not attempt to symbolize it.
- if (entry >= PERF_CONTEXT_MAX) {
- continue;
- }
- // The sample address has already been mapped so no need to map it.
- if (entry == original_event_addr) {
- callchain->ips[j] = ip;
- continue;
- }
- if (!MapIPAndPidAndGetNameAndOffset(
- entry,
- pid,
- &callchain->ips[j],
- &parsed_event->callchain[num_entries_mapped++])) {
- mapping_failed = true;
- }
- }
- // Not all the entries were mapped. Trim |parsed_event->callchain| to
- // remove unused entries at the end.
- parsed_event->callchain.resize(num_entries_mapped);
-
- return !mapping_failed;
-}
-
-bool PerfParser::MapBranchStack(const uint32_t pid,
- struct branch_stack* branch_stack,
- ParsedEvent* parsed_event) {
- if (!branch_stack) {
- LOG(ERROR) << "NULL branch stack data.";
- return false;
- }
-
- // First, trim the branch stack to remove trailing null entries.
- size_t trimmed_size = 0;
- for (size_t i = 0; i < branch_stack->nr; ++i) {
- // Count the number of non-null entries before the first null entry.
- if (IsNullBranchStackEntry(branch_stack->entries[i])) {
- break;
- }
- ++trimmed_size;
- }
-
- // If a null entry was found, make sure all subsequent null entries are NULL
- // as well.
- for (size_t i = trimmed_size; i < branch_stack->nr; ++i) {
- const struct branch_entry& entry = branch_stack->entries[i];
- if (!IsNullBranchStackEntry(entry)) {
- LOG(ERROR) << "Non-null branch stack entry found after null entry: "
- << reinterpret_cast<void*>(entry.from) << " -> "
- << reinterpret_cast<void*>(entry.to);
- return false;
- }
- }
-
- // Map branch stack addresses.
- parsed_event->branch_stack.resize(trimmed_size);
- for (unsigned int i = 0; i < trimmed_size; ++i) {
- struct branch_entry& entry = branch_stack->entries[i];
- ParsedEvent::BranchEntry& parsed_entry = parsed_event->branch_stack[i];
- if (!MapIPAndPidAndGetNameAndOffset(entry.from,
- pid,
- &entry.from,
- &parsed_entry.from)) {
- return false;
- }
- if (!MapIPAndPidAndGetNameAndOffset(entry.to,
- pid,
- &entry.to,
- &parsed_entry.to)) {
- return false;
- }
- parsed_entry.predicted = entry.flags.predicted;
- // Either predicted or mispredicted, not both. But don't use a CHECK here,
- // just exit gracefully because it's a minor issue.
- if (entry.flags.predicted == entry.flags.mispred) {
- LOG(ERROR) << "Branch stack entry predicted and mispred flags "
- << "both have value " << entry.flags.mispred;
- return false;
- }
- }
-
- return true;
-}
-
-bool PerfParser::MapIPAndPidAndGetNameAndOffset(
- uint64_t ip,
- uint32_t pid,
- uint64_t* new_ip,
- ParsedEvent::DSOAndOffset* dso_and_offset) {
-
- // Attempt to find the synthetic address of the IP sample in this order:
- // 1. Address space of its own process.
- // 2. Address space of the kernel.
-
- uint64_t mapped_addr = 0;
-
- // Sometimes the first event we see is a SAMPLE event and we don't have the
- // time to create an address mapper for a process. Example, for pid 0.
- AddressMapper* mapper = GetOrCreateProcessMapper(pid).first;
- bool mapped = mapper->GetMappedAddress(ip, &mapped_addr);
- if (!mapped) {
- mapper = kernel_mapper_.get();
- mapped = mapper->GetMappedAddress(ip, &mapped_addr);
- }
-
- // TODO(asharif): What should we do when we cannot map a SAMPLE event?
- if (mapped) {
- if (dso_and_offset) {
- uint64_t id = kuint64max;
- CHECK(mapper->GetMappedIDAndOffset(ip, &id, &dso_and_offset->offset_));
- // Make sure the ID points to a valid event.
- CHECK_LE(id, parsed_events_sorted_by_time_.size());
- ParsedEvent* parsed_event = parsed_events_sorted_by_time_[id];
- const event_t* raw_event = parsed_event->raw_event;
-
- DSOInfo dso_info;
- if (raw_event->header.type == PERF_RECORD_MMAP) {
- dso_info.name = raw_event->mmap.filename;
- } else if (raw_event->header.type == PERF_RECORD_MMAP2) {
- dso_info.name = raw_event->mmap2.filename;
- } else {
- LOG(FATAL) << "Expected MMAP or MMAP2 event";
- }
-
- // Find the mmap DSO filename in the set of known DSO names.
- // TODO(sque): take build IDs into account.
- std::set<DSOInfo>::const_iterator dso_iter = dso_set_.find(dso_info);
- CHECK(dso_iter != dso_set_.end());
- dso_and_offset->dso_info_ = &(*dso_iter);
-
- ++parsed_event->num_samples_in_mmap_region;
- }
- if (options_.do_remap)
- *new_ip = mapped_addr;
- }
- return mapped;
-}
-
-bool PerfParser::MapMmapEvent(uint64_t id,
- uint32_t pid,
- uint64_t* p_start,
- uint64_t* p_len,
- uint64_t* p_pgoff)
-{
- // We need to hide only the real kernel addresses. However, to make things
- // more secure, and make the mapping idempotent, we should remap all
- // addresses, both kernel and non-kernel.
- AddressMapper* mapper =
- (pid == kKernelPid ? kernel_mapper_.get() :
- GetOrCreateProcessMapper(pid).first);
-
- uint64_t start = *p_start;
- uint64_t len = *p_len;
- uint64_t pgoff = *p_pgoff;
-
- // |id| == 0 corresponds to the kernel mmap. We have several cases here:
- //
- // For ARM and x86, in sudo mode, pgoff == start, example:
- // start=0x80008200
- // pgoff=0x80008200
- // len =0xfffffff7ff7dff
- //
- // For x86-64, in sudo mode, pgoff is between start and start + len. SAMPLE
- // events lie between pgoff and pgoff + length of the real kernel binary,
- // example:
- // start=0x3bc00000
- // pgoff=0xffffffffbcc00198
- // len =0xffffffff843fffff
- // SAMPLE events will be found after pgoff. For kernels with ASLR, pgoff will
- // be something only visible to the root user, and will be randomized at
- // startup. With |remap| set to true, we should hide pgoff in this case. So we
- // normalize all SAMPLE events relative to pgoff.
- //
- // For non-sudo mode, the kernel will be mapped from 0 to the pointer limit,
- // example:
- // start=0x0
- // pgoff=0x0
- // len =0xffffffff
- if (id == 0) {
- // If pgoff is between start and len, we normalize the event by setting
- // start to be pgoff just like how it is for ARM and x86. We also set len to
- // be a much smaller number (closer to the real length of the kernel binary)
- // because SAMPLEs are actually only seen between |event->pgoff| and
- // |event->pgoff + kernel text size|.
- if (pgoff > start && pgoff < start + len) {
- len = len + start - pgoff;
- start = pgoff;
- }
- // For kernels with ALSR pgoff is critical information that should not be
- // revealed when |remap| is true.
- pgoff = 0;
- }
-
- if (!mapper->MapWithID(start, len, id, pgoff, true)) {
- mapper->DumpToLog();
- return false;
- }
-
- if (options_.do_remap) {
- uint64_t mapped_addr;
- CHECK(mapper->GetMappedAddress(start, &mapped_addr));
- *p_start = mapped_addr;
- *p_len = len;
- *p_pgoff = pgoff;
- }
- return true;
-}
-
-std::pair<AddressMapper*, bool> PerfParser::GetOrCreateProcessMapper(
- uint32_t pid, uint32_t *ppid) {
- const auto& search = process_mappers_.find(pid);
- if (search != process_mappers_.end()) {
- return std::make_pair(search->second.get(), false);
- }
-
- std::unique_ptr<AddressMapper> mapper;
- const auto& parent_mapper = (ppid ? process_mappers_.find(*ppid) : process_mappers_.end());
- if (parent_mapper != process_mappers_.end())
- mapper.reset(new AddressMapper(*parent_mapper->second));
- else
- mapper.reset(new AddressMapper());
-
- const auto inserted =
- process_mappers_.insert(search, std::make_pair(pid, std::move(mapper)));
- return std::make_pair(inserted->second.get(), true);
-}
-
-bool PerfParser::MapCommEvent(const struct comm_event& event) {
- GetOrCreateProcessMapper(event.pid);
- return true;
-}
-
-bool PerfParser::MapForkEvent(const struct fork_event& event) {
- PidTid parent = std::make_pair(event.ppid, event.ptid);
- PidTid child = std::make_pair(event.pid, event.tid);
- if (parent != child &&
- pidtid_to_comm_map_.find(parent) != pidtid_to_comm_map_.end()) {
- pidtid_to_comm_map_[child] = pidtid_to_comm_map_[parent];
- }
-
- const uint32_t pid = event.pid;
-
- // If the parent and child pids are the same, this is just a new thread
- // within the same process, so don't do anything.
- if (event.ppid == pid)
- return true;
-
- uint32_t ppid = event.ppid;
- if (!GetOrCreateProcessMapper(pid, &ppid).second) {
- DLOG(INFO) << "Found an existing process mapper with pid: " << pid;
- }
-
- return true;
-}
-
-} // namespace quipper
diff --git a/perfprofd/quipper/perf_parser.h b/perfprofd/quipper/perf_parser.h
deleted file mode 100644
index 28644832..00000000
--- a/perfprofd/quipper/perf_parser.h
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
-#define CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-
-#include "perf_reader.h"
-#include "perf_utils.h"
-
-namespace quipper {
-
-class AddressMapper;
-
-// A struct containing all relevant info for a mapped DSO, independent of any
-// samples.
-struct DSOInfo {
- string name;
- string build_id;
-
- // Comparator that allows this to be stored in a STL set.
- bool operator<(const DSOInfo& other) const {
- if (name == other.name)
- return build_id < other.build_id;
- return name < other.name;
- }
-};
-
-struct ParsedEvent {
- // TODO(sque): Turn this struct into a class to privatize member variables.
- ParsedEvent() : command_(NULL) {}
-
- // Stores address of an event_t owned by the |PerfReader::events_| vector.
- event_t* raw_event;
-
- // For mmap events, use this to count the number of samples that are in this
- // region.
- uint32_t num_samples_in_mmap_region;
-
- // Command associated with this sample.
- const string* command_;
-
- // Process' name (command where pid = tid for this thread's pid).
- const string* process_command_;
-
- // Accessor for command string.
- const string command() const {
- if (command_)
- return *command_;
- return string();
- }
-
- void set_command(const string* command) {
- command_ = command;
- }
-
- // Accessor for process_command string.
- const string process_command() const {
- if (process_command_)
- return *process_command_;
- return string();
- }
-
- void set_process_command(const string* command) {
- process_command_ = command;
- }
-
- // A struct that contains a DSO + offset pair.
- struct DSOAndOffset {
- const DSOInfo* dso_info_;
- uint64_t offset_;
-
- // Accessor methods.
- const string dso_name() const {
- if (dso_info_)
- return dso_info_->name;
- return string();
- }
- const string build_id() const {
- if (dso_info_)
- return dso_info_->build_id;
- return string();
- }
- uint64_t offset() const {
- return offset_;
- }
-
- DSOAndOffset() : dso_info_(NULL),
- offset_(0) {}
- } dso_and_offset;
-
- // DSO+offset info for callchain.
- std::vector<DSOAndOffset> callchain;
-
- // DSO + offset info for branch stack entries.
- struct BranchEntry {
- bool predicted;
- DSOAndOffset from;
- DSOAndOffset to;
- };
- std::vector<BranchEntry> branch_stack;
-};
-
-struct PerfEventStats {
- // Number of each type of event.
- uint32_t num_sample_events;
- uint32_t num_mmap_events;
- uint32_t num_comm_events;
- uint32_t num_fork_events;
- uint32_t num_exit_events;
-
- // Number of sample events that were successfully mapped using the address
- // mapper. The mapping is recorded regardless of whether the address in the
- // perf sample event itself was assigned the remapped address. The latter is
- // indicated by |did_remap|.
- uint32_t num_sample_events_mapped;
-
- // Whether address remapping was enabled during event parsing.
- bool did_remap;
-};
-
-class PerfParser : public PerfReader {
- public:
- PerfParser();
- ~PerfParser();
-
- struct Options {
- // For synthetic address mapping.
- bool do_remap = false;
- // Set this flag to discard non-sample events that don't have any associated
- // sample events. e.g. MMAP regions with no samples in them.
- bool discard_unused_events = false;
- // When mapping perf sample events, at least this percentage of them must be
- // successfully mapped in order for ProcessEvents() to return true.
- // By default, most samples must be properly mapped in order for sample
- // mapping to be considered successful.
- float sample_mapping_percentage_threshold = 95.0f;
- };
-
- // Constructor that takes in options at PerfParser creation time.
- explicit PerfParser(const Options& options);
-
- // Pass in a struct containing various options.
- void set_options(const Options& options);
-
- // Gets parsed event/sample info from raw event data.
- bool ParseRawEvents();
-
- const std::vector<ParsedEvent>& parsed_events() const {
- return parsed_events_;
- }
-
- // Returns an array of pointers to |parsed_events_| sorted by sample time.
- // The first time this is called, it will create the sorted array.
- const std::vector<ParsedEvent*>& GetEventsSortedByTime() const {
- return parsed_events_sorted_by_time_;
- }
-
- const PerfEventStats& stats() const {
- return stats_;
- }
-
- protected:
- // Defines a type for a pid:tid pair.
- typedef std::pair<uint32_t, uint32_t> PidTid;
-
- // Sort |parsed_events_| by time, storing the results in
- // |parsed_events_sorted_by_time_|.
- // Events can not be sorted by time if PERF_SAMPLE_TIME is not set in
- // attr.sample_type (PerfReader.sample_type_). In that case,
- // |parsed_events_sorted_by_time_| is not actually sorted, but has the same
- // order as |parsed_events_|.
- void MaybeSortParsedEvents();
-
- // Used for processing events. e.g. remapping with synthetic addresses.
- bool ProcessEvents();
- template <typename MMapEventT>
- bool MapMmapEvent(MMapEventT* event, uint64_t id) {
- return MapMmapEvent(id,
- event->pid,
- &event->start,
- &event->len,
- &event->pgoff);
- }
- bool MapMmapEvent(uint64_t id,
- uint32_t pid,
- uint64_t* p_start,
- uint64_t* p_len,
- uint64_t* p_pgoff);
- bool MapForkEvent(const struct fork_event& event);
- bool MapCommEvent(const struct comm_event& event);
-
- // Does a sample event remap and then returns DSO name and offset of sample.
- bool MapSampleEvent(ParsedEvent* parsed_event);
-
- std::vector<ParsedEvent> parsed_events_;
- // See MaybeSortParsedEvents to see why this might not actually be sorted
- // by time:
- std::vector<ParsedEvent*> parsed_events_sorted_by_time_;
-
- Options options_; // Store all option flags as one struct.
-
- // Maps pid/tid to commands.
- std::map<PidTid, const string*> pidtid_to_comm_map_;
-
- // A set to store the actual command strings.
- std::set<string> commands_;
-
- PerfEventStats stats_;
-
- // A set of unique DSOs that may be referenced by multiple events.
- std::set<DSOInfo> dso_set_;
-
- private:
- // Calls MapIPAndPidAndGetNameAndOffset() on the callchain of a sample event.
- bool MapCallchain(const uint64_t ip,
- const uint32_t pid,
- uint64_t original_event_addr,
- struct ip_callchain* callchain,
- ParsedEvent* parsed_event);
-
- // Trims the branch stack for null entries and calls
- // MapIPAndPidAndGetNameAndOffset() on each entry.
- bool MapBranchStack(const uint32_t pid,
- struct branch_stack* branch_stack,
- ParsedEvent* parsed_event);
-
- // This maps a sample event and returns the mapped address, DSO name, and
- // offset within the DSO. This is a private function because the API might
- // change in the future, and we don't want derived classes to be stuck with an
- // obsolete API.
- bool MapIPAndPidAndGetNameAndOffset(
- uint64_t ip,
- uint32_t pid,
- uint64_t* new_ip,
- ParsedEvent::DSOAndOffset* dso_and_offset);
-
- // Create a process mapper for a process. Optionally pass in a parent pid
- // |ppid| from which to copy mappings.
- // Returns (mapper, true) if a new AddressMapper was created, and
- // (mapper, false) if there is an existing mapper.
- std::pair<AddressMapper*, bool> GetOrCreateProcessMapper(uint32_t pid,
- uint32_t *ppid = NULL);
-
- std::unique_ptr<AddressMapper> kernel_mapper_;
- std::map<uint32_t, std::unique_ptr<AddressMapper>> process_mappers_;
-
- DISALLOW_COPY_AND_ASSIGN(PerfParser);
-};
-
-} // namespace quipper
-
-#endif // CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
diff --git a/perfprofd/quipper/perf_reader.cc b/perfprofd/quipper/perf_reader.cc
deleted file mode 100644
index d0cc9b60..00000000
--- a/perfprofd/quipper/perf_reader.cc
+++ /dev/null
@@ -1,1708 +0,0 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "perf_reader.h"
-
-#include <byteswap.h>
-#include <limits.h>
-
-#include <bitset>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <vector>
-
-#define LOG_TAG "perf_reader"
-
-#include "base/logging.h"
-
-#include "quipper_string.h"
-#include "perf_utils.h"
-
-namespace quipper {
-
-struct BufferWithSize {
- char* ptr;
- size_t size;
-};
-
-// If the buffer is read-only, it is not sufficient to mark the previous struct
-// as const, as this only means that the pointer cannot be changed, and says
-// nothing about the contents of the buffer. So, we need another struct.
-struct ConstBufferWithSize {
- const char* ptr;
- size_t size;
-};
-
-namespace {
-
-// The type of the number of string data, found in the command line metadata in
-// the perf data file.
-typedef u32 num_string_data_type;
-
-// Types of the event desc fields that are not found in other structs.
-typedef u32 event_desc_num_events;
-typedef u32 event_desc_attr_size;
-typedef u32 event_desc_num_unique_ids;
-
-// The type of the number of nodes field in NUMA topology.
-typedef u32 numa_topology_num_nodes_type;
-
-// A mask that is applied to metadata_mask_ in order to get a mask for
-// only the metadata supported by quipper.
-const uint32_t kSupportedMetadataMask =
- 1 << HEADER_TRACING_DATA |
- 1 << HEADER_BUILD_ID |
- 1 << HEADER_HOSTNAME |
- 1 << HEADER_OSRELEASE |
- 1 << HEADER_VERSION |
- 1 << HEADER_ARCH |
- 1 << HEADER_NRCPUS |
- 1 << HEADER_CPUDESC |
- 1 << HEADER_CPUID |
- 1 << HEADER_TOTAL_MEM |
- 1 << HEADER_CMDLINE |
- 1 << HEADER_EVENT_DESC |
- 1 << HEADER_CPU_TOPOLOGY |
- 1 << HEADER_NUMA_TOPOLOGY |
- 1 << HEADER_BRANCH_STACK;
-
-// By default, the build ID event has PID = -1.
-const uint32_t kDefaultBuildIDEventPid = static_cast<uint32_t>(-1);
-
-template <class T>
-void ByteSwap(T* input) {
- switch (sizeof(T)) {
- case sizeof(uint8_t):
- LOG(WARNING) << "Attempting to byte swap on a single byte.";
- break;
- case sizeof(uint16_t):
- *input = bswap_16(*input);
- break;
- case sizeof(uint32_t):
- *input = bswap_32(*input);
- break;
- case sizeof(uint64_t):
- *input = bswap_64(*input);
- break;
- default:
- LOG(FATAL) << "Invalid size for byte swap: " << sizeof(T) << " bytes";
- break;
- }
-}
-
-u64 MaybeSwap(u64 value, bool swap) {
- if (swap)
- return bswap_64(value);
- return value;
-}
-
-u32 MaybeSwap(u32 value, bool swap) {
- if (swap)
- return bswap_32(value);
- return value;
-}
-
-u8 ReverseByte(u8 x) {
- x = (x & 0xf0) >> 4 | (x & 0x0f) << 4; // exchange nibbles
- x = (x & 0xcc) >> 2 | (x & 0x33) << 2; // exchange pairs
- x = (x & 0xaa) >> 1 | (x & 0x55) << 1; // exchange neighbors
- return x;
-}
-
-// If field points to the start of a bitfield padded to len bytes, this
-// performs an endian swap of the bitfield, assuming the compiler that produced
-// it conforms to the same ABI (bitfield layout is not completely specified by
-// the language).
-void SwapBitfieldOfBits(u8* field, size_t len) {
- for (size_t i = 0; i < len; i++) {
- field[i] = ReverseByte(field[i]);
- }
-}
-
-// The code currently assumes that the compiler will not add any padding to the
-// various structs. These CHECKs make sure that this is true.
-void CheckNoEventHeaderPadding() {
- perf_event_header header;
- CHECK_EQ(sizeof(header),
- sizeof(header.type) + sizeof(header.misc) + sizeof(header.size));
-}
-
-void CheckNoPerfEventAttrPadding() {
- perf_event_attr attr;
- CHECK_EQ(sizeof(attr),
- (reinterpret_cast<u64>(&attr.__reserved_2) -
- reinterpret_cast<u64>(&attr)) +
- sizeof(attr.__reserved_2));
-}
-
-void CheckNoEventTypePadding() {
- perf_trace_event_type event_type;
- CHECK_EQ(sizeof(event_type),
- sizeof(event_type.event_id) + sizeof(event_type.name));
-}
-
-void CheckNoBuildIDEventPadding() {
- build_id_event event;
- CHECK_EQ(sizeof(event),
- sizeof(event.header.type) + sizeof(event.header.misc) +
- sizeof(event.header.size) + sizeof(event.pid) +
- sizeof(event.build_id));
-}
-
-// Creates/updates a build id event with |build_id| and |filename|.
-// Passing "" to |build_id| or |filename| will leave the corresponding field
-// unchanged (in which case |event| must be non-null).
-// If |event| is null or is not large enough, a new event will be created.
-// In this case, if |event| is non-null, it will be freed.
-// Otherwise, updates the fields of the existing event.
-// |new_misc| indicates kernel vs user space, and is only used to fill in the
-// |header.misc| field of new events.
-// In either case, returns a pointer to the event containing the updated data,
-// or NULL in the case of a failure.
-build_id_event* CreateOrUpdateBuildID(const string& build_id,
- const string& filename,
- uint16_t new_misc,
- build_id_event* event) {
- // When creating an event from scratch, build id and filename must be present.
- if (!event && (build_id.empty() || filename.empty()))
- return NULL;
- size_t new_len = GetUint64AlignedStringLength(
- filename.empty() ? event->filename : filename);
-
- // If event is null, or we don't have enough memory, allocate more memory, and
- // switch the new pointer with the existing pointer.
- size_t new_size = sizeof(*event) + new_len;
- if (!event || new_size > event->header.size) {
- build_id_event* new_event = CallocMemoryForBuildID(new_size);
-
- if (event) {
- // Copy over everything except the filename and free the event.
- // It is guaranteed that we are changing the filename - otherwise, the old
- // size and the new size would be equal.
- *new_event = *event;
- free(event);
- } else {
- // Fill in the fields appropriately.
- new_event->header.type = HEADER_BUILD_ID;
- new_event->header.misc = new_misc;
- new_event->pid = kDefaultBuildIDEventPid;
- }
- event = new_event;
- }
-
- // Here, event is the pointer to the build_id_event that we are keeping.
- // Update the event's size, build id, and filename.
- if (!build_id.empty() &&
- !StringToHex(build_id, event->build_id, arraysize(event->build_id))) {
- free(event);
- return NULL;
- }
-
- if (!filename.empty())
- CHECK_GT(snprintf(event->filename, new_len, "%s", filename.c_str()), 0);
-
- event->header.size = new_size;
- return event;
-}
-
-// Reads |size| bytes from |buffer| into |dest| and advances |src_offset|.
-bool ReadDataFromBuffer(const ConstBufferWithSize& buffer,
- size_t size,
- const string& value_name,
- size_t* src_offset,
- void* dest) {
- size_t end_offset = *src_offset + size / sizeof(*buffer.ptr);
- if (buffer.size < end_offset) {
- LOG(ERROR) << "Not enough bytes to read " << value_name
- << ". Requested " << size << " bytes";
- return false;
- }
- memcpy(dest, buffer.ptr + *src_offset, size);
- *src_offset = end_offset;
- return true;
-}
-
-// Reads a CStringWithLength from |buffer| into |dest|, and advances the offset.
-bool ReadStringFromBuffer(const ConstBufferWithSize& buffer,
- bool is_cross_endian,
- size_t* offset,
- CStringWithLength* dest) {
- if (!ReadDataFromBuffer(buffer, sizeof(dest->len), "string length",
- offset, &dest->len)) {
- return false;
- }
- if (is_cross_endian)
- ByteSwap(&dest->len);
-
- if (buffer.size < *offset + dest->len) {
- LOG(ERROR) << "Not enough bytes to read string";
- return false;
- }
- dest->str = string(buffer.ptr + *offset);
- *offset += dest->len / sizeof(*buffer.ptr);
- return true;
-}
-
-// Read read info from perf data. Corresponds to sample format type
-// PERF_SAMPLE_READ.
-const uint64_t* ReadReadInfo(const uint64_t* array,
- bool swap_bytes,
- uint64_t read_format,
- struct perf_sample* sample) {
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
- sample->read.time_enabled = *array++;
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
- sample->read.time_running = *array++;
- if (read_format & PERF_FORMAT_ID)
- sample->read.one.id = *array++;
-
- if (swap_bytes) {
- ByteSwap(&sample->read.time_enabled);
- ByteSwap(&sample->read.time_running);
- ByteSwap(&sample->read.one.id);
- }
-
- return array;
-}
-
-// Read call chain info from perf data. Corresponds to sample format type
-// PERF_SAMPLE_CALLCHAIN.
-const uint64_t* ReadCallchain(const uint64_t* array,
- bool swap_bytes,
- struct perf_sample* sample) {
- // Make sure there is no existing allocated memory in |sample->callchain|.
- CHECK_EQ(static_cast<void*>(NULL), sample->callchain);
-
- // The callgraph data consists of a uint64_t value |nr| followed by |nr|
- // addresses.
- uint64_t callchain_size = *array++;
- if (swap_bytes)
- ByteSwap(&callchain_size);
- struct ip_callchain* callchain =
- reinterpret_cast<struct ip_callchain*>(new uint64_t[callchain_size + 1]);
- callchain->nr = callchain_size;
- for (size_t i = 0; i < callchain_size; ++i) {
- callchain->ips[i] = *array++;
- if (swap_bytes)
- ByteSwap(&callchain->ips[i]);
- }
- sample->callchain = callchain;
-
- return array;
-}
-
-// Read raw info from perf data. Corresponds to sample format type
-// PERF_SAMPLE_RAW.
-const uint64_t* ReadRawData(const uint64_t* array,
- bool swap_bytes,
- struct perf_sample* sample) {
- // First read the size.
- const uint32_t* ptr = reinterpret_cast<const uint32_t*>(array);
- sample->raw_size = *ptr++;
- if (swap_bytes)
- ByteSwap(&sample->raw_size);
-
- // Allocate space for and read the raw data bytes.
- sample->raw_data = new uint8_t[sample->raw_size];
- memcpy(sample->raw_data, ptr, sample->raw_size);
-
- // Determine the bytes that were read, and align to the next 64 bits.
- int bytes_read = AlignSize(sizeof(sample->raw_size) + sample->raw_size,
- sizeof(uint64_t));
- array += bytes_read / sizeof(uint64_t);
-
- return array;
-}
-
-// Read call chain info from perf data. Corresponds to sample format type
-// PERF_SAMPLE_CALLCHAIN.
-const uint64_t* ReadBranchStack(const uint64_t* array,
- bool swap_bytes,
- struct perf_sample* sample) {
- // Make sure there is no existing allocated memory in
- // |sample->branch_stack|.
- CHECK_EQ(static_cast<void*>(NULL), sample->branch_stack);
-
- // The branch stack data consists of a uint64_t value |nr| followed by |nr|
- // branch_entry structs.
- uint64_t branch_stack_size = *array++;
- if (swap_bytes)
- ByteSwap(&branch_stack_size);
- struct branch_stack* branch_stack =
- reinterpret_cast<struct branch_stack*>(
- new uint8_t[sizeof(uint64_t) +
- branch_stack_size * sizeof(struct branch_entry)]);
- branch_stack->nr = branch_stack_size;
- for (size_t i = 0; i < branch_stack_size; ++i) {
- memcpy(&branch_stack->entries[i], array, sizeof(struct branch_entry));
- array += sizeof(struct branch_entry) / sizeof(*array);
- if (swap_bytes) {
- ByteSwap(&branch_stack->entries[i].from);
- ByteSwap(&branch_stack->entries[i].to);
- }
- }
- sample->branch_stack = branch_stack;
-
- return array;
-}
-
-size_t ReadPerfSampleFromData(const perf_event_type event_type,
- const uint64_t* array,
- const uint64_t sample_fields,
- const uint64_t read_format,
- bool swap_bytes,
- const perf_event_attr &attr0,
- size_t n_attrs,
- struct perf_sample* sample) {
- const uint64_t* initial_array_ptr = array;
-
- union {
- uint32_t val32[sizeof(uint64_t) / sizeof(uint32_t)];
- uint64_t val64;
- };
-
- // See structure for PERF_RECORD_SAMPLE in kernel/perf_event.h
- // and compare sample_id when sample_id_all is set.
-
- // NB: For sample_id, sample_fields has already been masked to the set
- // of fields in that struct by GetSampleFieldsForEventType. That set
- // of fields is mostly in the same order as PERF_RECORD_SAMPLE, with
- // the exception of PERF_SAMPLE_IDENTIFIER.
-
- // PERF_SAMPLE_IDENTIFIER is in a different location depending on
- // if this is a SAMPLE event or the sample_id of another event.
- if (event_type == PERF_RECORD_SAMPLE) {
- // { u64 id; } && PERF_SAMPLE_IDENTIFIER
- if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
- sample->id = MaybeSwap(*array++, swap_bytes);
- }
- }
-
- // { u64 ip; } && PERF_SAMPLE_IP
- if (sample_fields & PERF_SAMPLE_IP) {
- sample->ip = MaybeSwap(*array++, swap_bytes);
- }
-
- // { u32 pid, tid; } && PERF_SAMPLE_TID
- if (sample_fields & PERF_SAMPLE_TID) {
- val64 = *array++;
- sample->pid = MaybeSwap(val32[0], swap_bytes);
- sample->tid = MaybeSwap(val32[1], swap_bytes);
- }
-
- // { u64 time; } && PERF_SAMPLE_TIME
- if (sample_fields & PERF_SAMPLE_TIME) {
- sample->time = MaybeSwap(*array++, swap_bytes);
- }
-
- // { u64 addr; } && PERF_SAMPLE_ADDR
- if (sample_fields & PERF_SAMPLE_ADDR) {
- sample->addr = MaybeSwap(*array++, swap_bytes);
- }
-
- // { u64 id; } && PERF_SAMPLE_ID
- if (sample_fields & PERF_SAMPLE_ID) {
- sample->id = MaybeSwap(*array++, swap_bytes);
- }
-
- // { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
- if (sample_fields & PERF_SAMPLE_STREAM_ID) {
- sample->stream_id = MaybeSwap(*array++, swap_bytes);
- }
-
- // { u32 cpu, res; } && PERF_SAMPLE_CPU
- if (sample_fields & PERF_SAMPLE_CPU) {
- val64 = *array++;
- sample->cpu = MaybeSwap(val32[0], swap_bytes);
- // sample->res = MaybeSwap(*val32[1], swap_bytes); // not implemented?
- }
-
- // This is the location of PERF_SAMPLE_IDENTIFIER in struct sample_id.
- if (event_type != PERF_RECORD_SAMPLE) {
- // { u64 id; } && PERF_SAMPLE_IDENTIFIER
- if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
- sample->id = MaybeSwap(*array++, swap_bytes);
- }
- }
-
- //
- // The remaining fields are only in PERF_RECORD_SAMPLE
- //
-
- // { u64 period; } && PERF_SAMPLE_PERIOD
- if (sample_fields & PERF_SAMPLE_PERIOD) {
- sample->period = MaybeSwap(*array++, swap_bytes);
- }
-
- // { struct read_format values; } && PERF_SAMPLE_READ
- if (sample_fields & PERF_SAMPLE_READ) {
- // TODO(cwp-team): support grouped read info.
- if (read_format & PERF_FORMAT_GROUP)
- return 0;
- array = ReadReadInfo(array, swap_bytes, read_format, sample);
- }
-
- // { u64 nr,
- // u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
- if (sample_fields & PERF_SAMPLE_CALLCHAIN) {
- array = ReadCallchain(array, swap_bytes, sample);
- }
-
- // { u32 size;
- // char data[size];}&& PERF_SAMPLE_RAW
- if (sample_fields & PERF_SAMPLE_RAW) {
- array = ReadRawData(array, swap_bytes, sample);
- }
-
- // { u64 nr;
- // { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
- if (sample_fields & PERF_SAMPLE_BRANCH_STACK) {
- array = ReadBranchStack(array, swap_bytes, sample);
- }
-
- // { u64 abi,
- // u64 regs[nr]; } && PERF_SAMPLE_REGS_USER
- if (sample_fields & PERF_SAMPLE_REGS_USER) {
- uint64_t abi = MaybeSwap(*array++, swap_bytes);
- if (abi != 0) {
- assert(n_attrs == 1);
- uint64_t reg_mask = attr0.sample_regs_user;
- size_t bit_nr = 0;
- for (size_t i = 0; i < 64; ++i) {
- if ((reg_mask >> i) & 1) {
- bit_nr++;
- }
- }
- array += bit_nr;
- }
- }
-
- // { u64 size,
- // u64 regs[nr]; } && PERF_SAMPLE_STACK_USER
- if (sample_fields & PERF_SAMPLE_STACK_USER) {
- uint64_t size = MaybeSwap(*array++, swap_bytes);
- if (size != 0) {
- array += (size / sizeof(uint64_t));
- array += 1; // for dyn_size
- }
- }
-
- static const u64 kUnimplementedSampleFields =
- PERF_SAMPLE_WEIGHT |
- PERF_SAMPLE_DATA_SRC |
- PERF_SAMPLE_TRANSACTION;
-
- if (sample_fields & kUnimplementedSampleFields) {
- LOG(WARNING) << "Unimplemented sample fields 0x"
- << std::hex << (sample_fields & kUnimplementedSampleFields);
- }
-
- if (sample_fields & ~(PERF_SAMPLE_MAX-1)) {
- LOG(WARNING) << "Unrecognized sample fields 0x"
- << std::hex << (sample_fields & ~(PERF_SAMPLE_MAX-1));
- }
-
- return (array - initial_array_ptr) * sizeof(uint64_t);
-}
-
-size_t WritePerfSampleToData(const perf_event_type event_type,
- const struct perf_sample& sample,
- const uint64_t sample_fields,
- const uint64_t read_format,
- uint64_t* array) {
- const uint64_t* initial_array_ptr = array;
-
- union {
- uint32_t val32[sizeof(uint64_t) / sizeof(uint32_t)];
- uint64_t val64;
- };
-
- // See notes at the top of ReadPerfSampleFromData regarding the structure
- // of PERF_RECORD_SAMPLE, sample_id, and PERF_SAMPLE_IDENTIFIER, as they
- // all apply here as well.
-
- // PERF_SAMPLE_IDENTIFIER is in a different location depending on
- // if this is a SAMPLE event or the sample_id of another event.
- if (event_type == PERF_RECORD_SAMPLE) {
- // { u64 id; } && PERF_SAMPLE_IDENTIFIER
- if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
- *array++ = sample.id;
- }
- }
-
- // { u64 ip; } && PERF_SAMPLE_IP
- if (sample_fields & PERF_SAMPLE_IP) {
- *array++ = sample.ip;
- }
-
- // { u32 pid, tid; } && PERF_SAMPLE_TID
- if (sample_fields & PERF_SAMPLE_TID) {
- val32[0] = sample.pid;
- val32[1] = sample.tid;
- *array++ = val64;
- }
-
- // { u64 time; } && PERF_SAMPLE_TIME
- if (sample_fields & PERF_SAMPLE_TIME) {
- *array++ = sample.time;
- }
-
- // { u64 addr; } && PERF_SAMPLE_ADDR
- if (sample_fields & PERF_SAMPLE_ADDR) {
- *array++ = sample.addr;
- }
-
- // { u64 id; } && PERF_SAMPLE_ID
- if (sample_fields & PERF_SAMPLE_ID) {
- *array++ = sample.id;
- }
-
- // { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
- if (sample_fields & PERF_SAMPLE_STREAM_ID) {
- *array++ = sample.stream_id;
- }
-
- // { u32 cpu, res; } && PERF_SAMPLE_CPU
- if (sample_fields & PERF_SAMPLE_CPU) {
- val32[0] = sample.cpu;
- // val32[1] = sample.res; // not implemented?
- val32[1] = 0;
- *array++ = val64;
- }
-
- // This is the location of PERF_SAMPLE_IDENTIFIER in struct sample_id.
- if (event_type != PERF_RECORD_SAMPLE) {
- // { u64 id; } && PERF_SAMPLE_IDENTIFIER
- if (sample_fields & PERF_SAMPLE_IDENTIFIER) {
- *array++ = sample.id;
- }
- }
-
- //
- // The remaining fields are only in PERF_RECORD_SAMPLE
- //
-
- // { u64 period; } && PERF_SAMPLE_PERIOD
- if (sample_fields & PERF_SAMPLE_PERIOD) {
- *array++ = sample.period;
- }
-
- // { struct read_format values; } && PERF_SAMPLE_READ
- if (sample_fields & PERF_SAMPLE_READ) {
- // TODO(cwp-team): support grouped read info.
- if (read_format & PERF_FORMAT_GROUP)
- return 0;
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
- *array++ = sample.read.time_enabled;
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
- *array++ = sample.read.time_running;
- if (read_format & PERF_FORMAT_ID)
- *array++ = sample.read.one.id;
- }
-
- // { u64 nr,
- // u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
- if (sample_fields & PERF_SAMPLE_CALLCHAIN) {
- if (!sample.callchain) {
- LOG(ERROR) << "Expecting callchain data, but none was found.";
- } else {
- *array++ = sample.callchain->nr;
- for (size_t i = 0; i < sample.callchain->nr; ++i)
- *array++ = sample.callchain->ips[i];
- }
- }
-
- // { u32 size;
- // char data[size];}&& PERF_SAMPLE_RAW
- if (sample_fields & PERF_SAMPLE_RAW) {
- uint32_t* ptr = reinterpret_cast<uint32_t*>(array);
- *ptr++ = sample.raw_size;
- memcpy(ptr, sample.raw_data, sample.raw_size);
-
- // Update the data read pointer after aligning to the next 64 bytes.
- int num_bytes = AlignSize(sizeof(sample.raw_size) + sample.raw_size,
- sizeof(uint64_t));
- array += num_bytes / sizeof(uint64_t);
- }
-
- // { u64 nr;
- // { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
- if (sample_fields & PERF_SAMPLE_BRANCH_STACK) {
- if (!sample.branch_stack) {
- LOG(ERROR) << "Expecting branch stack data, but none was found.";
- } else {
- *array++ = sample.branch_stack->nr;
- for (size_t i = 0; i < sample.branch_stack->nr; ++i) {
- *array++ = sample.branch_stack->entries[i].from;
- *array++ = sample.branch_stack->entries[i].to;
- memcpy(array++, &sample.branch_stack->entries[i].flags,
- sizeof(uint64_t));
- }
- }
- }
-
- //
- // Unsupported sample types.
- //
- CHECK(!(sample_fields & PERF_SAMPLE_STACK_USER|PERF_SAMPLE_REGS_USER));
-
- return (array - initial_array_ptr) * sizeof(uint64_t);
-}
-
-} // namespace
-
-PerfReader::~PerfReader() {
- // Free allocated memory.
- for (size_t i = 0; i < build_id_events_.size(); ++i)
- if (build_id_events_[i])
- free(build_id_events_[i]);
-}
-
-void PerfReader::PerfizeBuildIDString(string* build_id) {
- build_id->resize(kBuildIDStringLength, '0');
-}
-
-void PerfReader::UnperfizeBuildIDString(string* build_id) {
- const size_t kPaddingSize = 8;
- const string kBuildIDPadding = string(kPaddingSize, '0');
-
- // Remove kBuildIDPadding from the end of build_id until we cannot remove any
- // more, or removing more would cause the build id to be empty.
- while (build_id->size() > kPaddingSize &&
- build_id->substr(build_id->size() - kPaddingSize) == kBuildIDPadding) {
- build_id->resize(build_id->size() - kPaddingSize);
- }
-}
-
-bool PerfReader::ReadFile(const string& filename) {
- std::vector<char> data;
- if (!ReadFileToData(filename, &data))
- return false;
- return ReadFromVector(data);
-}
-
-bool PerfReader::ReadFromVector(const std::vector<char>& data) {
- return ReadFromPointer(&data[0], data.size());
-}
-
-bool PerfReader::ReadFromString(const string& str) {
- return ReadFromPointer(str.c_str(), str.size());
-}
-
-bool PerfReader::ReadFromPointer(const char* perf_data, size_t size) {
- const ConstBufferWithSize data = { perf_data, size };
-
- if (data.size == 0)
- return false;
- if (!ReadHeader(data))
- return false;
-
- // Check if it is normal perf data.
- if (header_.size == sizeof(header_)) {
- DLOG(INFO) << "Perf data is in normal format.";
- metadata_mask_ = header_.adds_features[0];
- return (ReadAttrs(data) && ReadEventTypes(data) && ReadData(data)
- && ReadMetadata(data));
- }
-
- // Otherwise it is piped data.
- LOG(ERROR) << "Internal error: no support for piped data";
- return false;
-}
-
-bool PerfReader::Localize(
- const std::map<string, string>& build_ids_to_filenames) {
- std::map<string, string> perfized_build_ids_to_filenames;
- std::map<string, string>::const_iterator it;
- for (it = build_ids_to_filenames.begin();
- it != build_ids_to_filenames.end();
- ++it) {
- string build_id = it->first;
- PerfizeBuildIDString(&build_id);
- perfized_build_ids_to_filenames[build_id] = it->second;
- }
-
- std::map<string, string> filename_map;
- for (size_t i = 0; i < build_id_events_.size(); ++i) {
- build_id_event* event = build_id_events_[i];
- string build_id = HexToString(event->build_id, kBuildIDArraySize);
- if (perfized_build_ids_to_filenames.find(build_id) ==
- perfized_build_ids_to_filenames.end()) {
- continue;
- }
-
- string new_name = perfized_build_ids_to_filenames.at(build_id);
- filename_map[string(event->filename)] = new_name;
- build_id_event* new_event = CreateOrUpdateBuildID("", new_name, 0, event);
- CHECK(new_event);
- build_id_events_[i] = new_event;
- }
-
- LocalizeUsingFilenames(filename_map);
- return true;
-}
-
-bool PerfReader::LocalizeUsingFilenames(
- const std::map<string, string>& filename_map) {
- LocalizeMMapFilenames(filename_map);
- for (size_t i = 0; i < build_id_events_.size(); ++i) {
- build_id_event* event = build_id_events_[i];
- string old_name = event->filename;
-
- if (filename_map.find(event->filename) != filename_map.end()) {
- const string& new_name = filename_map.at(old_name);
- build_id_event* new_event = CreateOrUpdateBuildID("", new_name, 0, event);
- CHECK(new_event);
- build_id_events_[i] = new_event;
- }
- }
- return true;
-}
-
-void PerfReader::GetFilenames(std::vector<string>* filenames) const {
- std::set<string> filename_set;
- GetFilenamesAsSet(&filename_set);
- filenames->clear();
- filenames->insert(filenames->begin(), filename_set.begin(),
- filename_set.end());
-}
-
-void PerfReader::GetFilenamesAsSet(std::set<string>* filenames) const {
- filenames->clear();
- for (size_t i = 0; i < events_.size(); ++i) {
- const event_t& event = *events_[i];
- if (event.header.type == PERF_RECORD_MMAP)
- filenames->insert(event.mmap.filename);
- if (event.header.type == PERF_RECORD_MMAP2)
- filenames->insert(event.mmap2.filename);
- }
-}
-
-void PerfReader::GetFilenamesToBuildIDs(
- std::map<string, string>* filenames_to_build_ids) const {
- filenames_to_build_ids->clear();
- for (size_t i = 0; i < build_id_events_.size(); ++i) {
- const build_id_event& event = *build_id_events_[i];
- string build_id = HexToString(event.build_id, kBuildIDArraySize);
- (*filenames_to_build_ids)[event.filename] = build_id;
- }
-}
-
-bool PerfReader::IsSupportedEventType(uint32_t type) {
- switch (type) {
- case PERF_RECORD_SAMPLE:
- case PERF_RECORD_MMAP:
- case PERF_RECORD_MMAP2:
- case PERF_RECORD_FORK:
- case PERF_RECORD_EXIT:
- case PERF_RECORD_COMM:
- case PERF_RECORD_LOST:
- case PERF_RECORD_THROTTLE:
- case PERF_RECORD_UNTHROTTLE:
- case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
- case SIMPLE_PERF_RECORD_DSO:
- case SIMPLE_PERF_RECORD_SYMBOL:
- case SIMPLE_PERF_RECORD_SPLIT:
- case SIMPLE_PERF_RECORD_SPLIT_END:
- return true;
- case PERF_RECORD_READ:
- case PERF_RECORD_MAX:
- return false;
- default:
- LOG(FATAL) << "Unknown event type " << type;
- return false;
- }
-}
-
-bool PerfReader::ReadPerfSampleInfo(const event_t& event,
- struct perf_sample* sample) const {
- CHECK(sample);
-
- if (!IsSupportedEventType(event.header.type)) {
- LOG(ERROR) << "Unsupported event type " << event.header.type;
- return false;
- }
-
- // We want to completely ignore these records
- if (event.header.type == SIMPLE_PERF_RECORD_KERNEL_SYMBOL ||
- event.header.type == SIMPLE_PERF_RECORD_DSO ||
- event.header.type == SIMPLE_PERF_RECORD_SYMBOL ||
- event.header.type == SIMPLE_PERF_RECORD_SPLIT ||
- event.header.type == SIMPLE_PERF_RECORD_SPLIT_END)
- return true;
-
- uint64_t sample_format = GetSampleFieldsForEventType(event.header.type,
- sample_type_);
- uint64_t offset = GetPerfSampleDataOffset(event);
- size_t size_read = ReadPerfSampleFromData(
- static_cast<perf_event_type>(event.header.type),
- reinterpret_cast<const uint64_t*>(&event) + offset / sizeof(uint64_t),
- sample_format,
- read_format_,
- is_cross_endian_,
- attrs_[0].attr,
- attrs_.size(),
- sample);
-
- size_t expected_size = event.header.size - offset;
- if (size_read != expected_size) {
- LOG(ERROR) << "Read " << size_read << " bytes, expected "
- << expected_size << " bytes.";
- }
-
- return (size_read == expected_size);
-}
-
-bool PerfReader::WritePerfSampleInfo(const perf_sample& sample,
- event_t* event) const {
- CHECK(event);
-
- if (!IsSupportedEventType(event->header.type)) {
- LOG(ERROR) << "Unsupported event type " << event->header.type;
- return false;
- }
-
- uint64_t sample_format = GetSampleFieldsForEventType(event->header.type,
- sample_type_);
- uint64_t offset = GetPerfSampleDataOffset(*event);
-
- size_t expected_size = event->header.size - offset;
- memset(reinterpret_cast<uint8_t*>(event) + offset, 0, expected_size);
- size_t size_written = WritePerfSampleToData(
- static_cast<perf_event_type>(event->header.type),
- sample,
- sample_format,
- read_format_,
- reinterpret_cast<uint64_t*>(event) + offset / sizeof(uint64_t));
- if (size_written != expected_size) {
- LOG(ERROR) << "Wrote " << size_written << " bytes, expected "
- << expected_size << " bytes.";
- }
-
- return (size_written == expected_size);
-}
-
-bool PerfReader::ReadHeader(const ConstBufferWithSize& data) {
- CheckNoEventHeaderPadding();
- size_t offset = 0;
- if (!ReadDataFromBuffer(data, sizeof(piped_header_), "header magic",
- &offset, &piped_header_)) {
- return false;
- }
- if (piped_header_.magic != kPerfMagic &&
- piped_header_.magic != bswap_64(kPerfMagic)) {
- LOG(ERROR) << "Read wrong magic. Expected: 0x" << std::hex << kPerfMagic
- << " or 0x" << std::hex << bswap_64(kPerfMagic)
- << " Got: 0x" << std::hex << piped_header_.magic;
- return false;
- }
- is_cross_endian_ = (piped_header_.magic != kPerfMagic);
- if (is_cross_endian_)
- ByteSwap(&piped_header_.size);
-
- // Header can be a piped header.
- if (piped_header_.size == sizeof(piped_header_))
- return true;
-
- // Re-read full header
- offset = 0;
- if (!ReadDataFromBuffer(data, sizeof(header_), "header data",
- &offset, &header_)) {
- return false;
- }
- if (is_cross_endian_)
- ByteSwap(&header_.size);
-
- DLOG(INFO) << "event_types.size: " << header_.event_types.size;
- DLOG(INFO) << "event_types.offset: " << header_.event_types.offset;
-
- return true;
-}
-
-bool PerfReader::ReadAttrs(const ConstBufferWithSize& data) {
- size_t num_attrs = header_.attrs.size / header_.attr_size;
- size_t offset = header_.attrs.offset;
- for (size_t i = 0; i < num_attrs; i++) {
- if (!ReadAttr(data, &offset))
- return false;
- }
- return true;
-}
-
-bool PerfReader::ReadAttr(const ConstBufferWithSize& data, size_t* offset) {
- PerfFileAttr attr;
- if (!ReadEventAttr(data, offset, &attr.attr))
- return false;
-
- perf_file_section ids;
- if (!ReadDataFromBuffer(data, sizeof(ids), "ID section info", offset, &ids))
- return false;
- if (is_cross_endian_) {
- ByteSwap(&ids.offset);
- ByteSwap(&ids.size);
- }
-
- size_t num_ids = ids.size / sizeof(decltype(attr.ids)::value_type);
- // Convert the offset from u64 to size_t.
- size_t ids_offset = ids.offset;
- if (!ReadUniqueIDs(data, num_ids, &ids_offset, &attr.ids))
- return false;
- attrs_.push_back(attr);
- return true;
-}
-
-u32 PerfReader::ReadPerfEventAttrSize(const ConstBufferWithSize& data,
- size_t attr_offset) {
- static_assert(std::is_same<decltype(perf_event_attr::size), u32>::value,
- "ReadPerfEventAttrSize return type should match "
- "perf_event_attr.size");
- u32 attr_size;
- size_t attr_size_offset = attr_offset + offsetof(perf_event_attr, size);
- if (!ReadDataFromBuffer(data, sizeof(perf_event_attr::size),
- "attr.size", &attr_size_offset, &attr_size)) {
- return kuint32max;
- }
- return MaybeSwap(attr_size, is_cross_endian_);
-}
-
-bool PerfReader::ReadEventAttr(const ConstBufferWithSize& data, size_t* offset,
- perf_event_attr* attr) {
- CheckNoPerfEventAttrPadding();
-
- std::memset(attr, 0, sizeof(*attr));
- //*attr = {0};
-
- // read just size first
- u32 attr_size = ReadPerfEventAttrSize(data, *offset);
- if (attr_size == kuint32max) {
- return false;
- }
-
- // now read the the struct.
- if (!ReadDataFromBuffer(data, attr_size, "attribute", offset,
- reinterpret_cast<char*>(attr))) {
- return false;
- }
-
- if (is_cross_endian_) {
- // Depending on attr->size, some of these might not have actually been
- // read. This is okay: they are zero.
- ByteSwap(&attr->type);
- ByteSwap(&attr->size);
- ByteSwap(&attr->config);
- ByteSwap(&attr->sample_period);
- ByteSwap(&attr->sample_type);
- ByteSwap(&attr->read_format);
-
- // NB: This will also reverse precise_ip : 2 as if it was two fields:
- auto *const bitfield_start = &attr->read_format + 1;
- SwapBitfieldOfBits(reinterpret_cast<u8*>(bitfield_start),
- sizeof(u64));
- // ... So swap it back:
- const auto tmp = attr->precise_ip;
- attr->precise_ip = (tmp & 0x2) >> 1 | (tmp & 0x1) << 1;
-
- ByteSwap(&attr->wakeup_events); // union with wakeup_watermark
- ByteSwap(&attr->bp_type);
- ByteSwap(&attr->bp_addr); // union with config1
- ByteSwap(&attr->bp_len); // union with config2
- ByteSwap(&attr->branch_sample_type);
- ByteSwap(&attr->sample_regs_user);
- ByteSwap(&attr->sample_stack_user);
- }
-
- CHECK_EQ(attr_size, attr->size);
- // The actual perf_event_attr data size might be different from the size of
- // the struct definition. Check against perf_event_attr's |size| field.
- attr->size = sizeof(*attr);
-
- // Assign sample type if it hasn't been assigned, otherwise make sure all
- // subsequent attributes have the same sample type bits set.
- if (sample_type_ == 0) {
- sample_type_ = attr->sample_type;
- } else {
- CHECK_EQ(sample_type_, attr->sample_type)
- << "Event type sample format does not match sample format of other "
- << "event type.";
- }
-
- if (read_format_ == 0) {
- read_format_ = attr->read_format;
- } else {
- CHECK_EQ(read_format_, attr->read_format)
- << "Event type read format does not match read format of other event "
- << "types.";
- }
-
- return true;
-}
-
-bool PerfReader::ReadUniqueIDs(const ConstBufferWithSize& data, size_t num_ids,
- size_t* offset, std::vector<u64>* ids) {
- ids->resize(num_ids);
- for (size_t j = 0; j < num_ids; j++) {
- if (!ReadDataFromBuffer(data, sizeof(ids->at(j)), "ID", offset,
- &ids->at(j))) {
- return false;
- }
- if (is_cross_endian_)
- ByteSwap(&ids->at(j));
- }
- return true;
-}
-
-bool PerfReader::ReadEventTypes(const ConstBufferWithSize& data) {
- size_t num_event_types = header_.event_types.size /
- sizeof(struct perf_trace_event_type);
- CHECK_EQ(sizeof(perf_trace_event_type) * num_event_types,
- header_.event_types.size);
- size_t offset = header_.event_types.offset;
- for (size_t i = 0; i < num_event_types; ++i) {
- if (!ReadEventType(data, &offset))
- return false;
- }
- return true;
-}
-
-bool PerfReader::ReadEventType(const ConstBufferWithSize& data,
- size_t* offset) {
- CheckNoEventTypePadding();
- perf_trace_event_type type;
- memset(&type, 0, sizeof(type));
- if (!ReadDataFromBuffer(data, sizeof(type.event_id), "event id",
- offset, &type.event_id)) {
- return false;
- }
- const char* event_name = reinterpret_cast<const char*>(data.ptr + *offset);
- CHECK_GT(snprintf(type.name, sizeof(type.name), "%s", event_name), 0);
- *offset += sizeof(type.name);
- event_types_.push_back(type);
- return true;
-}
-
-bool PerfReader::ReadData(const ConstBufferWithSize& data) {
- u64 data_remaining_bytes = header_.data.size;
- size_t offset = header_.data.offset;
- while (data_remaining_bytes != 0) {
- if (data.size < offset) {
- LOG(ERROR) << "Not enough data to read a perf event.";
- return false;
- }
-
- const event_t* event = reinterpret_cast<const event_t*>(data.ptr + offset);
- if (!ReadPerfEventBlock(*event))
- return false;
- data_remaining_bytes -= event->header.size;
- offset += event->header.size;
- }
-
- DLOG(INFO) << "Number of events stored: "<< events_.size();
- return true;
-}
-
-bool PerfReader::ReadMetadata(const ConstBufferWithSize& data) {
- size_t offset = header_.data.offset + header_.data.size;
-
- for (u32 type = HEADER_FIRST_FEATURE; type != HEADER_LAST_FEATURE; ++type) {
- if ((metadata_mask_ & (1 << type)) == 0)
- continue;
-
- if (data.size < offset) {
- LOG(ERROR) << "Not enough data to read offset and size of metadata.";
- return false;
- }
-
- u64 metadata_offset, metadata_size;
- if (!ReadDataFromBuffer(data, sizeof(metadata_offset), "metadata offset",
- &offset, &metadata_offset) ||
- !ReadDataFromBuffer(data, sizeof(metadata_size), "metadata size",
- &offset, &metadata_size)) {
- return false;
- }
-
- if (data.size < metadata_offset + metadata_size) {
- LOG(ERROR) << "Not enough data to read metadata.";
- return false;
- }
-
- switch (type) {
- case HEADER_TRACING_DATA:
- if (!ReadTracingMetadata(data, metadata_offset, metadata_size)) {
- return false;
- }
- break;
- case HEADER_BUILD_ID:
- if (!ReadBuildIDMetadata(data, type, metadata_offset, metadata_size))
- return false;
- break;
- case HEADER_HOSTNAME:
- case HEADER_OSRELEASE:
- case HEADER_VERSION:
- case HEADER_ARCH:
- case HEADER_CPUDESC:
- case HEADER_CPUID:
- case HEADER_CMDLINE:
- if (!ReadStringMetadata(data, type, metadata_offset, metadata_size))
- return false;
- break;
- case HEADER_NRCPUS:
- if (!ReadUint32Metadata(data, type, metadata_offset, metadata_size))
- return false;
- break;
- case HEADER_TOTAL_MEM:
- if (!ReadUint64Metadata(data, type, metadata_offset, metadata_size))
- return false;
- break;
- case HEADER_EVENT_DESC:
- break;
- case HEADER_CPU_TOPOLOGY:
- if (!ReadCPUTopologyMetadata(data, type, metadata_offset, metadata_size))
- return false;
- break;
- case HEADER_NUMA_TOPOLOGY:
- if (!ReadNUMATopologyMetadata(data, type, metadata_offset, metadata_size))
- return false;
- break;
- case HEADER_PMU_MAPPINGS:
- // ignore for now
- continue;
- case HEADER_BRANCH_STACK:
- continue;
- default: LOG(INFO) << "Unsupported metadata type: " << type;
- break;
- }
- }
-
- // Event type events are optional in some newer versions of perf. They
- // contain the same information that is already in |attrs_|. Make sure the
- // number of event types matches the number of attrs, but only if there are
- // event type events present.
- if (event_types_.size() > 0) {
- if (event_types_.size() != attrs_.size()) {
- LOG(ERROR) << "Mismatch between number of event type events and attr "
- << "events: " << event_types_.size() << " vs "
- << attrs_.size();
- return false;
- }
- metadata_mask_ |= (1 << HEADER_EVENT_DESC);
- }
- return true;
-}
-
-bool PerfReader::ReadBuildIDMetadata(const ConstBufferWithSize& data, u32 /*type*/,
- size_t offset, size_t size) {
- CheckNoBuildIDEventPadding();
- while (size > 0) {
- // Make sure there is enough data for everything but the filename.
- if (data.size < offset + sizeof(build_id_event) / sizeof(*data.ptr)) {
- LOG(ERROR) << "Not enough bytes to read build id event";
- return false;
- }
-
- const build_id_event* temp_ptr =
- reinterpret_cast<const build_id_event*>(data.ptr + offset);
- u16 event_size = temp_ptr->header.size;
- if (is_cross_endian_)
- ByteSwap(&event_size);
-
- // Make sure there is enough data for the rest of the event.
- if (data.size < offset + event_size / sizeof(*data.ptr)) {
- LOG(ERROR) << "Not enough bytes to read build id event";
- return false;
- }
-
- // Allocate memory for the event and copy over the bytes.
- build_id_event* event = CallocMemoryForBuildID(event_size);
- if (!ReadDataFromBuffer(data, event_size, "build id event",
- &offset, event)) {
- return false;
- }
- if (is_cross_endian_) {
- ByteSwap(&event->header.type);
- ByteSwap(&event->header.misc);
- ByteSwap(&event->header.size);
- ByteSwap(&event->pid);
- }
- size -= event_size;
-
- // Perf tends to use more space than necessary, so fix the size.
- event->header.size =
- sizeof(*event) + GetUint64AlignedStringLength(event->filename);
- build_id_events_.push_back(event);
- }
-
- return true;
-}
-
-bool PerfReader::ReadStringMetadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size) {
- PerfStringMetadata str_data;
- str_data.type = type;
-
- size_t start_offset = offset;
- // Skip the number of string data if it is present.
- if (NeedsNumberOfStringData(type))
- offset += sizeof(num_string_data_type) / sizeof(*data.ptr);
-
- while ((offset - start_offset) < size) {
- CStringWithLength single_string;
- if (!ReadStringFromBuffer(data, is_cross_endian_, &offset, &single_string))
- return false;
- str_data.data.push_back(single_string);
- }
-
- string_metadata_.push_back(str_data);
- return true;
-}
-
-bool PerfReader::ReadUint32Metadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size) {
- PerfUint32Metadata uint32_data;
- uint32_data.type = type;
-
- size_t start_offset = offset;
- while (size > offset - start_offset) {
- uint32_t item;
- if (!ReadDataFromBuffer(data, sizeof(item), "uint32_t data", &offset,
- &item))
- return false;
-
- if (is_cross_endian_)
- ByteSwap(&item);
-
- uint32_data.data.push_back(item);
- }
-
- uint32_metadata_.push_back(uint32_data);
- return true;
-}
-
-bool PerfReader::ReadUint64Metadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size) {
- PerfUint64Metadata uint64_data;
- uint64_data.type = type;
-
- size_t start_offset = offset;
- while (size > offset - start_offset) {
- uint64_t item;
- if (!ReadDataFromBuffer(data, sizeof(item), "uint64_t data", &offset,
- &item))
- return false;
-
- if (is_cross_endian_)
- ByteSwap(&item);
-
- uint64_data.data.push_back(item);
- }
-
- uint64_metadata_.push_back(uint64_data);
- return true;
-}
-
-bool PerfReader::ReadCPUTopologyMetadata(
- const ConstBufferWithSize& data, u32 /*type*/, size_t offset, size_t /*size*/) {
- num_siblings_type num_core_siblings;
- if (!ReadDataFromBuffer(data, sizeof(num_core_siblings), "num cores",
- &offset, &num_core_siblings)) {
- return false;
- }
- if (is_cross_endian_)
- ByteSwap(&num_core_siblings);
-
- cpu_topology_.core_siblings.resize(num_core_siblings);
- for (size_t i = 0; i < num_core_siblings; ++i) {
- if (!ReadStringFromBuffer(data, is_cross_endian_, &offset,
- &cpu_topology_.core_siblings[i])) {
- return false;
- }
- }
-
- num_siblings_type num_thread_siblings;
- if (!ReadDataFromBuffer(data, sizeof(num_thread_siblings), "num threads",
- &offset, &num_thread_siblings)) {
- return false;
- }
- if (is_cross_endian_)
- ByteSwap(&num_thread_siblings);
-
- cpu_topology_.thread_siblings.resize(num_thread_siblings);
- for (size_t i = 0; i < num_thread_siblings; ++i) {
- if (!ReadStringFromBuffer(data, is_cross_endian_, &offset,
- &cpu_topology_.thread_siblings[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-bool PerfReader::ReadNUMATopologyMetadata(
- const ConstBufferWithSize& data, u32 /*type*/, size_t offset, size_t /*size*/) {
- numa_topology_num_nodes_type num_nodes;
- if (!ReadDataFromBuffer(data, sizeof(num_nodes), "num nodes",
- &offset, &num_nodes)) {
- return false;
- }
- if (is_cross_endian_)
- ByteSwap(&num_nodes);
-
- for (size_t i = 0; i < num_nodes; ++i) {
- PerfNodeTopologyMetadata node;
- if (!ReadDataFromBuffer(data, sizeof(node.id), "node id",
- &offset, &node.id) ||
- !ReadDataFromBuffer(data, sizeof(node.total_memory),
- "node total memory", &offset,
- &node.total_memory) ||
- !ReadDataFromBuffer(data, sizeof(node.free_memory),
- "node free memory", &offset, &node.free_memory) ||
- !ReadStringFromBuffer(data, is_cross_endian_, &offset,
- &node.cpu_list)) {
- return false;
- }
- if (is_cross_endian_) {
- ByteSwap(&node.id);
- ByteSwap(&node.total_memory);
- ByteSwap(&node.free_memory);
- }
- numa_topology_.push_back(node);
- }
- return true;
-}
-
-bool PerfReader::ReadTracingMetadata(
- const ConstBufferWithSize& data, size_t offset, size_t size) {
- size_t tracing_data_offset = offset;
- tracing_data_.resize(size);
- return ReadDataFromBuffer(data, tracing_data_.size(), "tracing_data",
- &tracing_data_offset, tracing_data_.data());
-}
-
-bool PerfReader::ReadTracingMetadataEvent(
- const ConstBufferWithSize& data, size_t offset) {
- // TRACING_DATA's header.size is a lie. It is the size of only the event
- // struct. The size of the data is in the event struct, and followed
- // immediately by the tracing header data.
-
- // Make a copy of the event (but not the tracing data)
- tracing_data_event tracing_event =
- *reinterpret_cast<const tracing_data_event*>(data.ptr + offset);
-
- if (is_cross_endian_) {
- ByteSwap(&tracing_event.header.type);
- ByteSwap(&tracing_event.header.misc);
- ByteSwap(&tracing_event.header.size);
- ByteSwap(&tracing_event.size);
- }
-
- return ReadTracingMetadata(data, offset + tracing_event.header.size,
- tracing_event.size);
-}
-
-bool PerfReader::ReadAttrEventBlock(const ConstBufferWithSize& data,
- size_t offset, size_t size) {
- const size_t initial_offset = offset;
- PerfFileAttr attr;
- if (!ReadEventAttr(data, &offset, &attr.attr))
- return false;
-
- // attr.attr.size has been upgraded to the current size of perf_event_attr.
- const size_t actual_attr_size = offset - initial_offset;
-
- const size_t num_ids =
- (size - actual_attr_size) / sizeof(decltype(attr.ids)::value_type);
- if (!ReadUniqueIDs(data, num_ids, &offset, &attr.ids))
- return false;
-
- // Event types are found many times in the perf data file.
- // Only add this event type if it is not already present.
- for (size_t i = 0; i < attrs_.size(); ++i) {
- if (attrs_[i].ids[0] == attr.ids[0])
- return true;
- }
- attrs_.push_back(attr);
- return true;
-}
-
-// When this method is called, |event| is a reference to the bytes in the data
-// vector that contains the entire perf.data file. As a result, we need to be
-// careful to only copy event.header.size bytes.
-// In particular, something like
-// event_t event_copy = event;
-// would be bad, because it would read past the end of the event, and possibly
-// pass the end of the data vector as well.
-bool PerfReader::ReadPerfEventBlock(const event_t& event) {
- u16 size = event.header.size;
- if (is_cross_endian_)
- ByteSwap(&size);
-
- //
- // Upstream linux perf limits the size of an event record to 2^16 bytes,
- // however simpleperf includes extensions to support larger (2^32) record
- // sizes via a split record scheme (the larger records are split up
- // into chunks and then embedded into a series of SIMPLE_PERF_RECORD_SPLIT
- // records followed by a terminating SIMPLE_PERF_RECORD_SPLIT_END record.
- // At the moment none of the larger records are of interest to perfprofd, so
- // the main thing we're doing here is ignoring/bypassing them.
- //
- if (event.header.type == SIMPLE_PERF_RECORD_KERNEL_SYMBOL ||
- event.header.type == SIMPLE_PERF_RECORD_DSO ||
- event.header.type == SIMPLE_PERF_RECORD_SYMBOL ||
- event.header.type == SIMPLE_PERF_RECORD_SPLIT ||
- event.header.type == SIMPLE_PERF_RECORD_SPLIT_END)
- size = sizeof(event_t);
- else if (size > sizeof(event_t)) {
- LOG(INFO) << "Data size: " << size << " sizeof(event_t): "
- << sizeof(event_t);
- return false;
- }
-
- // Copy only the part of the event that is needed.
- malloced_unique_ptr<event_t> event_copy(CallocMemoryForEvent(size));
- memcpy(event_copy.get(), &event, size);
- if (is_cross_endian_) {
- ByteSwap(&event_copy->header.type);
- ByteSwap(&event_copy->header.misc);
- ByteSwap(&event_copy->header.size);
- }
-
- uint32_t type = event_copy->header.type;
- if (is_cross_endian_) {
- switch (type) {
- case PERF_RECORD_SAMPLE:
- break;
- case PERF_RECORD_MMAP:
- ByteSwap(&event_copy->mmap.pid);
- ByteSwap(&event_copy->mmap.tid);
- ByteSwap(&event_copy->mmap.start);
- ByteSwap(&event_copy->mmap.len);
- ByteSwap(&event_copy->mmap.pgoff);
- break;
- case PERF_RECORD_MMAP2:
- ByteSwap(&event_copy->mmap2.pid);
- ByteSwap(&event_copy->mmap2.tid);
- ByteSwap(&event_copy->mmap2.start);
- ByteSwap(&event_copy->mmap2.len);
- ByteSwap(&event_copy->mmap2.pgoff);
- ByteSwap(&event_copy->mmap2.maj);
- ByteSwap(&event_copy->mmap2.min);
- ByteSwap(&event_copy->mmap2.ino);
- ByteSwap(&event_copy->mmap2.ino_generation);
- break;
- case PERF_RECORD_FORK:
- case PERF_RECORD_EXIT:
- ByteSwap(&event_copy->fork.pid);
- ByteSwap(&event_copy->fork.tid);
- ByteSwap(&event_copy->fork.ppid);
- ByteSwap(&event_copy->fork.ptid);
- break;
- case PERF_RECORD_COMM:
- ByteSwap(&event_copy->comm.pid);
- ByteSwap(&event_copy->comm.tid);
- break;
- case PERF_RECORD_LOST:
- ByteSwap(&event_copy->lost.id);
- ByteSwap(&event_copy->lost.lost);
- break;
- case PERF_RECORD_READ:
- ByteSwap(&event_copy->read.pid);
- ByteSwap(&event_copy->read.tid);
- ByteSwap(&event_copy->read.value);
- ByteSwap(&event_copy->read.time_enabled);
- ByteSwap(&event_copy->read.time_running);
- ByteSwap(&event_copy->read.id);
- break;
- case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
- break;
- default:
- LOG(FATAL) << "Unknown event type: " << type;
- }
- }
-
- events_.push_back(std::move(event_copy));
-
- return true;
-}
-
-size_t PerfReader::GetNumMetadata() const {
- // This is just the number of 1s in the binary representation of the metadata
- // mask. However, make sure to only use supported metadata, and don't include
- // branch stack (since it doesn't have an entry in the metadata section).
- uint64_t new_mask = metadata_mask_;
- new_mask &= kSupportedMetadataMask & ~(1 << HEADER_BRANCH_STACK);
- std::bitset<sizeof(new_mask) * CHAR_BIT> bits(new_mask);
- return bits.count();
-}
-
-size_t PerfReader::GetEventDescMetadataSize() const {
- size_t size = 0;
- if (event_types_.empty()) {
- return size;
- }
- if (metadata_mask_ & (1 << HEADER_EVENT_DESC)) {
- if (event_types_.size() > 0 && event_types_.size() != attrs_.size()) {
- LOG(ERROR) << "Mismatch between number of event type events and attr "
- << "events: " << event_types_.size() << " vs "
- << attrs_.size();
- return size;
- }
- size += sizeof(event_desc_num_events) + sizeof(event_desc_attr_size);
- CStringWithLength dummy;
- for (size_t i = 0; i < attrs_.size(); ++i) {
- size += sizeof(perf_event_attr) + sizeof(dummy.len);
- size += sizeof(event_desc_num_unique_ids);
- size += GetUint64AlignedStringLength(event_types_[i].name) * sizeof(char);
- size += attrs_[i].ids.size() * sizeof(attrs_[i].ids[0]);
- }
- }
- return size;
-}
-
-size_t PerfReader::GetBuildIDMetadataSize() const {
- size_t size = 0;
- for (size_t i = 0; i < build_id_events_.size(); ++i)
- size += build_id_events_[i]->header.size;
- return size;
-}
-
-size_t PerfReader::GetStringMetadataSize() const {
- size_t size = 0;
- for (size_t i = 0; i < string_metadata_.size(); ++i) {
- const PerfStringMetadata& metadata = string_metadata_[i];
- if (NeedsNumberOfStringData(metadata.type))
- size += sizeof(num_string_data_type);
-
- for (size_t j = 0; j < metadata.data.size(); ++j) {
- const CStringWithLength& str = metadata.data[j];
- size += sizeof(str.len) + (str.len * sizeof(char));
- }
- }
- return size;
-}
-
-size_t PerfReader::GetUint32MetadataSize() const {
- size_t size = 0;
- for (size_t i = 0; i < uint32_metadata_.size(); ++i) {
- const PerfUint32Metadata& metadata = uint32_metadata_[i];
- size += metadata.data.size() * sizeof(metadata.data[0]);
- }
- return size;
-}
-
-size_t PerfReader::GetUint64MetadataSize() const {
- size_t size = 0;
- for (size_t i = 0; i < uint64_metadata_.size(); ++i) {
- const PerfUint64Metadata& metadata = uint64_metadata_[i];
- size += metadata.data.size() * sizeof(metadata.data[0]);
- }
- return size;
-}
-
-size_t PerfReader::GetCPUTopologyMetadataSize() const {
- // Core siblings.
- size_t size = sizeof(num_siblings_type);
- for (size_t i = 0; i < cpu_topology_.core_siblings.size(); ++i) {
- const CStringWithLength& str = cpu_topology_.core_siblings[i];
- size += sizeof(str.len) + (str.len * sizeof(char));
- }
-
- // Thread siblings.
- size += sizeof(num_siblings_type);
- for (size_t i = 0; i < cpu_topology_.thread_siblings.size(); ++i) {
- const CStringWithLength& str = cpu_topology_.thread_siblings[i];
- size += sizeof(str.len) + (str.len * sizeof(char));
- }
-
- return size;
-}
-
-size_t PerfReader::GetNUMATopologyMetadataSize() const {
- size_t size = sizeof(numa_topology_num_nodes_type);
- for (size_t i = 0; i < numa_topology_.size(); ++i) {
- const PerfNodeTopologyMetadata& node = numa_topology_[i];
- size += sizeof(node.id);
- size += sizeof(node.total_memory) + sizeof(node.free_memory);
- size += sizeof(node.cpu_list.len) + node.cpu_list.len * sizeof(char);
- }
- return size;
-}
-
-bool PerfReader::NeedsNumberOfStringData(u32 type) const {
- return type == HEADER_CMDLINE;
-}
-
-bool PerfReader::LocalizeMMapFilenames(
- const std::map<string, string>& filename_map) {
- // Search for mmap/mmap2 events for which the filename needs to be updated.
- for (size_t i = 0; i < events_.size(); ++i) {
- string filename;
- size_t size_of_fixed_event_parts;
- event_t* event = events_[i].get();
- if (event->header.type == PERF_RECORD_MMAP) {
- filename = string(event->mmap.filename);
- size_of_fixed_event_parts =
- sizeof(event->mmap) - sizeof(event->mmap.filename);
- } else if (event->header.type == PERF_RECORD_MMAP2) {
- filename = string(event->mmap2.filename);
- size_of_fixed_event_parts =
- sizeof(event->mmap2) - sizeof(event->mmap2.filename);
- } else {
- continue;
- }
-
- const auto it = filename_map.find(filename);
- if (it == filename_map.end()) // not found
- continue;
-
- const string& new_filename = it->second;
- size_t old_len = GetUint64AlignedStringLength(filename);
- size_t new_len = GetUint64AlignedStringLength(new_filename);
- size_t old_offset = GetPerfSampleDataOffset(*event);
- size_t sample_size = event->header.size - old_offset;
-
- int size_change = new_len - old_len;
- size_t new_size = event->header.size + size_change;
- size_t new_offset = old_offset + size_change;
-
- if (size_change > 0) {
- // Allocate memory for a new event.
- event_t* old_event = event;
- malloced_unique_ptr<event_t> new_event(CallocMemoryForEvent(new_size));
-
- // Copy over everything except filename and sample info.
- memcpy(new_event.get(), old_event, size_of_fixed_event_parts);
-
- // Copy over the sample info to the correct location.
- char* old_addr = reinterpret_cast<char*>(old_event);
- char* new_addr = reinterpret_cast<char*>(new_event.get());
- memcpy(new_addr + new_offset, old_addr + old_offset, sample_size);
-
- events_[i] = std::move(new_event);
- event = events_[i].get();
- } else if (size_change < 0) {
- // Move the perf sample data to its new location.
- // Since source and dest could overlap, use memmove instead of memcpy.
- char* start_addr = reinterpret_cast<char*>(event);
- memmove(start_addr + new_offset, start_addr + old_offset, sample_size);
- }
-
- // Copy over the new filename and fix the size of the event.
- char *event_filename = nullptr;
- if (event->header.type == PERF_RECORD_MMAP) {
- event_filename = event->mmap.filename;
- } else if (event->header.type == PERF_RECORD_MMAP2) {
- event_filename = event->mmap2.filename;
- } else {
- LOG(FATAL) << "Unexpected event type"; // Impossible
- }
- CHECK_GT(snprintf(event_filename, new_filename.size() + 1, "%s",
- new_filename.c_str()),
- 0);
- event->header.size = new_size;
- }
-
- return true;
-}
-
-} // namespace quipper
diff --git a/perfprofd/quipper/perf_reader.h b/perfprofd/quipper/perf_reader.h
deleted file mode 100644
index 82163726..00000000
--- a/perfprofd/quipper/perf_reader.h
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMIUMOS_WIDE_PROFILING_PERF_READER_H_
-#define CHROMIUMOS_WIDE_PROFILING_PERF_READER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <set>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include "base/macros.h"
-
-#include "perf_internals.h"
-#include "quipper_string.h"
-#include "perf_utils.h"
-
-namespace quipper {
-
-struct PerfFileAttr {
- struct perf_event_attr attr;
- std::vector<u64> ids;
-};
-
-// Based on code in tools/perf/util/header.c, the metadata are of the following
-// formats:
-
-// Based on kernel/perf_internals.h
-const size_t kBuildIDArraySize = 20;
-const size_t kBuildIDStringLength = kBuildIDArraySize * 2;
-
-struct CStringWithLength {
- u32 len;
- string str;
-};
-
-struct PerfStringMetadata {
- u32 type;
- std::vector<CStringWithLength> data;
-};
-
-struct PerfUint32Metadata {
- u32 type;
- std::vector<uint32_t> data;
-};
-
-struct PerfUint64Metadata {
- u32 type;
- std::vector<uint64_t> data;
-};
-
-typedef u32 num_siblings_type;
-
-struct PerfCPUTopologyMetadata {
- std::vector<CStringWithLength> core_siblings;
- std::vector<CStringWithLength> thread_siblings;
-};
-
-struct PerfNodeTopologyMetadata {
- u32 id;
- u64 total_memory;
- u64 free_memory;
- CStringWithLength cpu_list;
-};
-
-struct BufferWithSize;
-struct ConstBufferWithSize;
-
-class PerfReader {
- public:
- PerfReader() : sample_type_(0),
- read_format_(0),
- is_cross_endian_(0) {}
- ~PerfReader();
-
- // Makes |build_id| fit the perf format, by either truncating it or adding
- // zeros to the end so that it has length kBuildIDStringLength.
- static void PerfizeBuildIDString(string* build_id);
-
- // Changes |build_id| to the best guess of what the build id was before going
- // through perf. Specifically, it keeps removing trailing sequences of four
- // zero bytes (or eight '0' characters) until there are no more such
- // sequences, or the build id would be empty if the process were repeated.
- static void UnperfizeBuildIDString(string* build_id);
-
- bool ReadFile(const string& filename);
- bool ReadFromVector(const std::vector<char>& data);
- bool ReadFromString(const string& str);
- bool ReadFromPointer(const char* perf_data, size_t size);
-
- // TODO(rohinmshah): GetSize should not use RegenerateHeader (so that it can
- // be const). Ideally, RegenerateHeader would be deleted and instead of
- // having out_header_ as an instance variable, it would be computed
- // dynamically whenever needed.
-
- // Returns the size in bytes that would be written by any of the methods that
- // write the entire perf data file (WriteFile, WriteToPointer, etc).
- size_t GetSize();
-
- bool WriteFile(const string& filename);
- bool WriteToVector(std::vector<char>* data);
- bool WriteToString(string* str);
- bool WriteToPointer(char* buffer, size_t size);
-
- bool RegenerateHeader();
-
- // Stores the mapping from filenames to build ids in build_id_events_.
- // Returns true on success.
- // Note: If |filenames_to_build_ids| contains a mapping for a filename for
- // which there is already a build_id_event in build_id_events_, a duplicate
- // build_id_event will be created, and the old build_id_event will NOT be
- // deleted.
- bool InjectBuildIDs(const std::map<string, string>& filenames_to_build_ids);
-
- // Replaces existing filenames with filenames from |build_ids_to_filenames|
- // by joining on build ids. If a build id in |build_ids_to_filenames| is not
- // present in this parser, it is ignored.
- bool Localize(const std::map<string, string>& build_ids_to_filenames);
-
- // Same as Localize, but joins on filenames instead of build ids.
- bool LocalizeUsingFilenames(const std::map<string, string>& filename_map);
-
- // Stores a list of unique filenames found in MMAP/MMAP2 events into
- // |filenames|. Any existing data in |filenames| will be lost.
- void GetFilenames(std::vector<string>* filenames) const;
- void GetFilenamesAsSet(std::set<string>* filenames) const;
-
- // Uses build id events to populate |filenames_to_build_ids|.
- // Any existing data in |filenames_to_build_ids| will be lost.
- // Note: A filename returned by GetFilenames need not be present in this map,
- // since there may be no build id event corresponding to the MMAP/MMAP2.
- void GetFilenamesToBuildIDs(
- std::map<string, string>* filenames_to_build_ids) const;
-
- static bool IsSupportedEventType(uint32_t type);
-
- // If a program using PerfReader calls events(), it could work with the
- // resulting events by importing kernel/perf_internals.h. This would also
- // apply to other forms of data (attributes, event types, build ids, etc.)
- // However, there is no easy way to work with the sample info within events.
- // The following two methods have been added for this purpose.
-
- // Extracts from a perf event |event| info about the perf sample that
- // contains the event. Stores info in |sample|.
- bool ReadPerfSampleInfo(const event_t& event,
- struct perf_sample* sample) const;
- // Writes |sample| info back to a perf event |event|.
- bool WritePerfSampleInfo(const perf_sample& sample,
- event_t* event) const;
-
- // Accessor funcs.
- const std::vector<PerfFileAttr>& attrs() const {
- return attrs_;
- }
-
- const std::vector<malloced_unique_ptr<event_t>>& events() const {
- return events_;
- }
-
- const std::vector<perf_trace_event_type>& event_types() const {
- return event_types_;
- }
-
- const std::vector<build_id_event*>& build_id_events() const {
- return build_id_events_;
- }
-
- const std::vector<char>& tracing_data() const {
- return tracing_data_;
- }
-
- protected:
- bool ReadHeader(const ConstBufferWithSize& data);
-
- bool ReadAttrs(const ConstBufferWithSize& data);
- bool ReadAttr(const ConstBufferWithSize& data, size_t* offset);
- bool ReadEventAttr(const ConstBufferWithSize& data, size_t* offset,
- perf_event_attr* attr);
- bool ReadUniqueIDs(const ConstBufferWithSize& data, size_t num_ids,
- size_t* offset, std::vector<u64>* ids);
-
- bool ReadEventTypes(const ConstBufferWithSize& data);
- bool ReadEventType(const ConstBufferWithSize& data, size_t* offset);
-
- bool ReadData(const ConstBufferWithSize& data);
-
- // Reads metadata in normal mode.
- bool ReadMetadata(const ConstBufferWithSize& data);
- bool ReadTracingMetadata(const ConstBufferWithSize& data,
- size_t offset, size_t size);
- bool ReadBuildIDMetadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size);
- bool ReadStringMetadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size);
- bool ReadUint32Metadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size);
- bool ReadUint64Metadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size);
- bool ReadCPUTopologyMetadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size);
- bool ReadNUMATopologyMetadata(const ConstBufferWithSize& data, u32 type,
- size_t offset, size_t size);
-
- // Read perf data from piped perf output data.
- bool ReadPipedData(const ConstBufferWithSize& data);
- bool ReadTracingMetadataEvent(const ConstBufferWithSize& data, size_t offset);
-
- // Like WriteToPointer, but does not check if the buffer is large enough.
- bool WriteToPointerWithoutCheckingSize(char* buffer, size_t size);
-
- bool WriteHeader(const BufferWithSize& data) const;
- bool WriteAttrs(const BufferWithSize& data) const;
- bool WriteEventTypes(const BufferWithSize& data) const;
- bool WriteData(const BufferWithSize& data) const;
- bool WriteMetadata(const BufferWithSize& data) const;
-
- // For writing the various types of metadata.
- bool WriteBuildIDMetadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
- bool WriteStringMetadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
- bool WriteUint32Metadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
- bool WriteUint64Metadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
- bool WriteEventDescMetadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
- bool WriteCPUTopologyMetadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
- bool WriteNUMATopologyMetadata(u32 type, size_t* offset,
- const BufferWithSize& data) const;
-
- // For reading event blocks within piped perf data.
- bool ReadAttrEventBlock(const ConstBufferWithSize& data, size_t offset,
- size_t size);
- bool ReadPerfEventBlock(const event_t& event);
-
- // Returns the number of types of metadata stored.
- size_t GetNumMetadata() const;
-
- // For computing the sizes of the various types of metadata.
- size_t GetBuildIDMetadataSize() const;
- size_t GetStringMetadataSize() const;
- size_t GetUint32MetadataSize() const;
- size_t GetUint64MetadataSize() const;
- size_t GetEventDescMetadataSize() const;
- size_t GetCPUTopologyMetadataSize() const;
- size_t GetNUMATopologyMetadataSize() const;
-
- // Returns true if we should write the number of strings for the string
- // metadata of type |type|.
- bool NeedsNumberOfStringData(u32 type) const;
-
- // Replaces existing filenames in MMAP/MMAP2 events based on |filename_map|.
- // This method does not change |build_id_events_|.
- bool LocalizeMMapFilenames(const std::map<string, string>& filename_map);
-
- std::vector<PerfFileAttr> attrs_;
- std::vector<perf_trace_event_type> event_types_;
- std::vector<malloced_unique_ptr<event_t>> events_;
- std::vector<build_id_event*> build_id_events_;
- std::vector<PerfStringMetadata> string_metadata_;
- std::vector<PerfUint32Metadata> uint32_metadata_;
- std::vector<PerfUint64Metadata> uint64_metadata_;
- PerfCPUTopologyMetadata cpu_topology_;
- std::vector<PerfNodeTopologyMetadata> numa_topology_;
- std::vector<char> tracing_data_;
- uint64_t sample_type_;
- uint64_t read_format_;
- uint64_t metadata_mask_;
-
- // Indicates that the perf data being read is from machine with a different
- // endianness than the current machine.
- bool is_cross_endian_;
-
- private:
- u32 ReadPerfEventAttrSize(const ConstBufferWithSize& data,
- size_t attr_offset);
-
- // The file header is either a normal header or a piped header.
- union {
- struct perf_file_header header_;
- struct perf_pipe_file_header piped_header_;
- };
- struct perf_file_header out_header_;
-
- DISALLOW_COPY_AND_ASSIGN(PerfReader);
-};
-
-} // namespace quipper
-
-#endif // CHROMIUMOS_WIDE_PROFILING_PERF_READER_H_
diff --git a/perfprofd/quipper/perf_utils.cc b/perfprofd/quipper/perf_utils.cc
deleted file mode 100644
index 710d6ce3..00000000
--- a/perfprofd/quipper/perf_utils.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#define LOG_TAG "perf_reader"
-
-#include "perf_utils.h"
-
-#include <sys/stat.h>
-
-#include <cctype>
-#include <cstddef>
-#include <cstdlib>
-#include <cstring>
-#include <fstream> // NOLINT(readability/streams)
-#include <iomanip>
-#include <sstream>
-
-#include "base/logging.h"
-#include "base/macros.h"
-
-namespace {
-
-// Number of hex digits in a byte.
-const int kNumHexDigitsInByte = 2;
-
-} // namespace
-
-namespace quipper {
-
-event_t* CallocMemoryForEvent(size_t size) {
- event_t* event = reinterpret_cast<event_t*>(calloc(1, size));
- CHECK(event);
- return event;
-}
-
-build_id_event* CallocMemoryForBuildID(size_t size) {
- build_id_event* event = reinterpret_cast<build_id_event*>(calloc(1, size));
- CHECK(event);
- return event;
-}
-
-string HexToString(const u8* array, size_t length) {
- // Convert the bytes to hex digits one at a time.
- // There will be kNumHexDigitsInByte hex digits, and 1 char for NUL.
- char buffer[kNumHexDigitsInByte + 1];
- string result = "";
- for (size_t i = 0; i < length; ++i) {
- snprintf(buffer, sizeof(buffer), "%02x", array[i]);
- result += buffer;
- }
- return result;
-}
-
-bool StringToHex(const string& str, u8* array, size_t length) {
- const int kHexRadix = 16;
- char* err;
- // Loop through kNumHexDigitsInByte characters at a time (to get one byte)
- // Stop when there are no more characters, or the array has been filled.
- for (size_t i = 0;
- (i + 1) * kNumHexDigitsInByte <= str.size() && i < length;
- ++i) {
- string one_byte = str.substr(i * kNumHexDigitsInByte, kNumHexDigitsInByte);
- array[i] = strtol(one_byte.c_str(), &err, kHexRadix);
- if (*err)
- return false;
- }
- return true;
-}
-
-uint64_t AlignSize(uint64_t size, uint32_t align_size) {
- return ((size + align_size - 1) / align_size) * align_size;
-}
-
-// In perf data, strings are packed into the smallest number of 8-byte blocks
-// possible, including the null terminator.
-// e.g.
-// "0123" -> 5 bytes -> packed into 8 bytes
-// "0123456" -> 8 bytes -> packed into 8 bytes
-// "01234567" -> 9 bytes -> packed into 16 bytes
-// "0123456789abcd" -> 15 bytes -> packed into 16 bytes
-// "0123456789abcde" -> 16 bytes -> packed into 16 bytes
-// "0123456789abcdef" -> 17 bytes -> packed into 24 bytes
-//
-// Returns the size of the 8-byte-aligned memory for storing |string|.
-size_t GetUint64AlignedStringLength(const string& str) {
- return AlignSize(str.size() + 1, sizeof(uint64_t));
-}
-
-uint64_t GetSampleFieldsForEventType(uint32_t event_type,
- uint64_t sample_type) {
- uint64_t mask = kuint64max;
- switch (event_type) {
- case PERF_RECORD_MMAP:
- case PERF_RECORD_LOST:
- case PERF_RECORD_COMM:
- case PERF_RECORD_EXIT:
- case PERF_RECORD_THROTTLE:
- case PERF_RECORD_UNTHROTTLE:
- case PERF_RECORD_FORK:
- case PERF_RECORD_READ:
- case PERF_RECORD_MMAP2:
- // See perf_event.h "struct" sample_id and sample_id_all.
- mask = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ID |
- PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER;
- break;
- case PERF_RECORD_SAMPLE:
- case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
- break;
- default:
- LOG(FATAL) << "Unknown event type " << event_type;
- }
- return sample_type & mask;
-}
-
-uint64_t GetPerfSampleDataOffset(const event_t& event) {
- uint64_t offset = kuint64max;
- switch (event.header.type) {
- case PERF_RECORD_SAMPLE:
- offset = offsetof(event_t, sample.array);
- break;
- case PERF_RECORD_MMAP:
- offset = sizeof(event.mmap) - sizeof(event.mmap.filename) +
- GetUint64AlignedStringLength(event.mmap.filename);
- break;
- case PERF_RECORD_FORK:
- case PERF_RECORD_EXIT:
- offset = sizeof(event.fork);
- break;
- case PERF_RECORD_COMM:
- offset = sizeof(event.comm) - sizeof(event.comm.comm) +
- GetUint64AlignedStringLength(event.comm.comm);
- break;
- case PERF_RECORD_LOST:
- offset = sizeof(event.lost);
- break;
- case PERF_RECORD_THROTTLE:
- case PERF_RECORD_UNTHROTTLE:
- offset = sizeof(event.throttle);
- break;
- case PERF_RECORD_READ:
- offset = sizeof(event.read);
- break;
- case PERF_RECORD_MMAP2:
- offset = sizeof(event.mmap2) - sizeof(event.mmap2.filename) +
- GetUint64AlignedStringLength(event.mmap2.filename);
- break;
- case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
- offset = 0;
- break;
- default:
- LOG(FATAL) << "Unknown/unsupported event type " << event.header.type;
- break;
- }
- // Make sure the offset was valid
- CHECK_NE(offset, kuint64max);
- CHECK_EQ(offset % sizeof(uint64_t), 0U);
- return offset;
-}
-
-bool ReadFileToData(const string& filename, std::vector<char>* data) {
- std::ifstream in(filename.c_str(), std::ios::binary);
- if (!in.good()) {
- LOG(ERROR) << "Failed to open file " << filename;
- return false;
- }
- in.seekg(0, in.end);
- size_t length = in.tellg();
- in.seekg(0, in.beg);
- data->resize(length);
-
- in.read(&(*data)[0], length);
-
- if (!in.good()) {
- LOG(ERROR) << "Error reading from file " << filename;
- return false;
- }
- return true;
-}
-
-bool WriteDataToFile(const std::vector<char>& data, const string& filename) {
- std::ofstream out(filename.c_str(), std::ios::binary);
- out.seekp(0, std::ios::beg);
- out.write(&data[0], data.size());
- return out.good();
-}
-
-} // namespace quipper
diff --git a/perfprofd/quipper/perf_utils.h b/perfprofd/quipper/perf_utils.h
deleted file mode 100644
index 66f1d9ec..00000000
--- a/perfprofd/quipper/perf_utils.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMIUMOS_WIDE_PROFILING_UTILS_H_
-#define CHROMIUMOS_WIDE_PROFILING_UTILS_H_
-
-#include <stdint.h>
-#include <stdlib.h> // for free()
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-
-#include "perf_internals.h"
-#include "quipper_string.h"
-
-namespace quipper {
-
-struct FreeDeleter {
- inline void operator()(void* pointer) {
- free(pointer);
- }
-};
-
-template <typename T>
-using malloced_unique_ptr = std::unique_ptr<T, FreeDeleter>;
-
-// Given a valid open file handle |fp|, returns the size of the file.
-int64_t GetFileSizeFromHandle(FILE* fp);
-
-event_t* CallocMemoryForEvent(size_t size);
-event_t* ReallocMemoryForEvent(event_t* event, size_t new_size);
-
-build_id_event* CallocMemoryForBuildID(size_t size);
-
-bool FileToBuffer(const string& filename, std::vector<char>* contents);
-
-template <typename CharContainer>
-bool BufferToFile(const string& filename, const CharContainer& contents) {
- FILE* fp = fopen(filename.c_str(), "wb");
- if (!fp)
- return false;
- // Do not write anything if |contents| contains nothing. fopen will create
- // an empty file.
- if (!contents.empty()) {
- CHECK_EQ(fwrite(contents.data(),
- sizeof(typename CharContainer::value_type),
- contents.size(),
- fp),
- contents.size());
- }
- fclose(fp);
- return true;
-}
-
-uint64_t Md5Prefix(const string& input);
-uint64_t Md5Prefix(const std::vector<char>& input);
-
-// Returns a string that represents |array| in hexadecimal.
-string HexToString(const u8* array, size_t length);
-
-// Converts |str| to a hexadecimal number, stored in |array|. Returns true on
-// success. Only stores up to |length| bytes - if there are more characters in
-// the string, they are ignored (but the function may still return true).
-bool StringToHex(const string& str, u8* array, size_t length);
-
-// Adjust |size| to blocks of |align_size|. i.e. returns the smallest multiple
-// of |align_size| that can fit |size|.
-uint64_t AlignSize(uint64_t size, uint32_t align_size);
-
-// Given a general perf sample format |sample_type|, return the fields of that
-// format that are present in a sample for an event of type |event_type|.
-//
-// e.g. FORK and EXIT events have the fields {time, pid/tid, cpu, id}.
-// Given a sample type with fields {ip, time, pid/tid, and period}, return
-// the intersection of these two field sets: {time, pid/tid}.
-//
-// All field formats are bitfields, as defined by enum perf_event_sample_format
-// in kernel/perf_event.h.
-uint64_t GetSampleFieldsForEventType(uint32_t event_type, uint64_t sample_type);
-
-// Returns the offset in bytes within a perf event structure at which the raw
-// perf sample data is located.
-uint64_t GetPerfSampleDataOffset(const event_t& event);
-
-// Returns the size of the 8-byte-aligned memory for storing |string|.
-size_t GetUint64AlignedStringLength(const string& str);
-
-// Returns true iff the file exists.
-bool FileExists(const string& filename);
-
-// Reads the contents of a file into |data|. Returns true on success, false if
-// it fails.
-bool ReadFileToData(const string& filename, std::vector<char>* data);
-
-// Writes contents of |data| to a file with name |filename|, overwriting any
-// existing file. Returns true on success, false if it fails.
-bool WriteDataToFile(const std::vector<char>& data, const string& filename);
-
-// Executes |command| and stores stdout output in |output|. Returns true on
-// success, false otherwise.
-bool RunCommandAndGetStdout(const string& command, std::vector<char>* output);
-
-// Trim leading and trailing whitespace from |str|.
-void TrimWhitespace(string* str);
-
-} // namespace quipper
-
-#endif // CHROMIUMOS_WIDE_PROFILING_UTILS_H_
diff --git a/perfprofd/quipper/quipper_string.h b/perfprofd/quipper/quipper_string.h
deleted file mode 100644
index 7b0ad1e8..00000000
--- a/perfprofd/quipper/quipper_string.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUIPPER_STRING_
-#define QUIPPER_STRING_
-
-#ifndef HAS_GLOBAL_STRING
-using std::string;
-using std::stringstream;
-#endif
-
-#endif // QUIPPER_STRING_
diff --git a/perfprofd/quipper/quipper_test.h b/perfprofd/quipper/quipper_test.h
deleted file mode 100644
index 85e8aea1..00000000
--- a/perfprofd/quipper/quipper_test.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUIPPER_TEST_H_
-#define QUIPPER_TEST_H_
-
-#include <gtest/gtest.h>
-
-#endif // QUIPPER_TEST_H_
diff --git a/perfprofd/quipper_helper.h b/perfprofd/quipper_helper.h
new file mode 100644
index 00000000..d72bd405
--- /dev/null
+++ b/perfprofd/quipper_helper.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 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 <iterator>
+
+#include "perf_data.pb.h"
+
+namespace android {
+namespace perfprofd {
+namespace quipper {
+
+template<typename Iterator, typename Predicate>
+class FilteredIterator {
+ public:
+ using value_type = typename std::iterator_traits<Iterator>::value_type;
+ using difference_type = typename std::iterator_traits<Iterator>::difference_type;
+ using reference = typename std::iterator_traits<Iterator>::reference;
+ using pointer = typename std::iterator_traits<Iterator>::pointer;
+
+ FilteredIterator(const Iterator& begin, const Iterator& end, const Predicate& pred)
+ : iter_(begin), end_(end), pred_(pred) {
+ filter();
+ }
+
+ reference operator*() const {
+ return *iter_;
+ }
+ pointer operator->() const {
+ return std::addressof(*iter_);
+ }
+
+ FilteredIterator& operator++() {
+ ++iter_;
+ filter();
+ return *this;
+ }
+
+ FilteredIterator end() {
+ return FilteredIterator(end_, end_, pred_);
+ }
+
+ bool operator==(const FilteredIterator& rhs) const {
+ return iter_ == rhs.iter_;
+ }
+ bool operator!=(const FilteredIterator& rhs) const {
+ return !(operator==(rhs));
+ }
+
+private:
+ void filter() {
+ while (iter_ != end_ && !pred_(*iter_)) {
+ ++iter_;
+ }
+ }
+
+ Iterator iter_;
+ Iterator end_;
+ Predicate pred_;
+};
+
+template <typename Predicate>
+using EventFilteredIterator = FilteredIterator<
+ decltype(static_cast<::quipper::PerfDataProto*>(nullptr)->events().begin()),
+ Predicate>;
+
+struct CommEventPredicate {
+ bool operator()(const ::quipper::PerfDataProto_PerfEvent& evt) {
+ return evt.has_comm_event();
+ }
+};
+struct CommEventIterator : public EventFilteredIterator<CommEventPredicate> {
+ explicit CommEventIterator(const ::quipper::PerfDataProto& proto)
+ : EventFilteredIterator<CommEventPredicate>(proto.events().begin(),
+ proto.events().end(),
+ CommEventPredicate()) {
+ }
+};
+
+struct MmapEventPredicate {
+ bool operator()(const ::quipper::PerfDataProto_PerfEvent& evt) {
+ return evt.has_mmap_event();
+ }
+};
+struct MmapEventIterator : public EventFilteredIterator<MmapEventPredicate> {
+ explicit MmapEventIterator(const ::quipper::PerfDataProto& proto)
+ : EventFilteredIterator<MmapEventPredicate>(proto.events().begin(),
+ proto.events().end(),
+ MmapEventPredicate()) {
+ }
+};
+
+struct SampleEventPredicate {
+ bool operator()(const ::quipper::PerfDataProto_PerfEvent& evt) {
+ return evt.has_sample_event();
+ }
+};
+struct SampleEventIterator : public EventFilteredIterator<SampleEventPredicate> {
+ explicit SampleEventIterator(const ::quipper::PerfDataProto& proto)
+ : EventFilteredIterator<SampleEventPredicate>(proto.events().begin(),
+ proto.events().end(),
+ SampleEventPredicate()) {
+ }
+};
+
+struct ForkEventPredicate {
+ bool operator()(const ::quipper::PerfDataProto_PerfEvent& evt) {
+ return evt.has_fork_event();
+ }
+};
+struct ForkEventIterator : public EventFilteredIterator<ForkEventPredicate> {
+ explicit ForkEventIterator(const ::quipper::PerfDataProto& proto)
+ : EventFilteredIterator<ForkEventPredicate>(proto.events().begin(),
+ proto.events().end(),
+ ForkEventPredicate()) {
+ }
+};
+
+struct ExitEventPredicate {
+ bool operator()(const ::quipper::PerfDataProto_PerfEvent& evt) {
+ return evt.has_exit_event();
+ }
+};
+struct ExitEventIterator : public EventFilteredIterator<ExitEventPredicate> {
+ explicit ExitEventIterator(const ::quipper::PerfDataProto& proto)
+ : EventFilteredIterator<ExitEventPredicate>(proto.events().begin(),
+ proto.events().end(),
+ ExitEventPredicate()) {
+ }
+};
+
+} // namespace quipper
+} // namespace perfprofd
+} // namespace android
diff --git a/perfprofd/symbolizer.cc b/perfprofd/symbolizer.cc
index 3f7ea4d1..2be6f96c 100644
--- a/perfprofd/symbolizer.cc
+++ b/perfprofd/symbolizer.cc
@@ -80,6 +80,11 @@ struct SimpleperfSymbolizer : public Symbolizer {
dsos.emplace(dso, std::move(data));
}
+ bool GetMinExecutableVAddr(const std::string& dso, uint64_t* addr) override {
+ ElfStatus status = ReadMinExecutableVirtualAddressFromElfFile(dso, BuildId(), addr);
+ return status == ElfStatus::NO_ERROR;
+ }
+
std::unordered_map<std::string, SymbolMap> dsos;
};
diff --git a/perfprofd/symbolizer.h b/perfprofd/symbolizer.h
index 87e8a25e..10771595 100644
--- a/perfprofd/symbolizer.h
+++ b/perfprofd/symbolizer.h
@@ -25,6 +25,7 @@ namespace perfprofd {
struct Symbolizer {
virtual ~Symbolizer() {}
virtual std::string Decode(const std::string& dso, uint64_t address) = 0;
+ virtual bool GetMinExecutableVAddr(const std::string& dso, uint64_t* addr) = 0;
};
std::unique_ptr<Symbolizer> CreateELFSymbolizer();
diff --git a/perfprofd/tests/Android.bp b/perfprofd/tests/Android.bp
index 861ef3a4..7d0b7061 100644
--- a/perfprofd/tests/Android.bp
+++ b/perfprofd/tests/Android.bp
@@ -2,16 +2,9 @@
cc_defaults {
name: "perfprofd_test_defaults",
-
- cflags: [
- "-Wall",
- "-Werror",
- "-O0",
- "-g",
- ],
- cppflags: [
- "-Wno-sign-compare",
- "-Wno-unused-parameter",
+ defaults: [
+ "perfprofd_defaults",
+ "perfprofd_debug_defaults",
],
strip: {
@@ -28,17 +21,38 @@ cc_test {
"perfprofd_test_defaults",
],
test_suites: ["device-tests"],
+ host_supported: true,
stl: "libc++",
static_libs: [
- "libperfprofdcore",
+ "libperfprofdcored",
"libsimpleperf_elf_read",
"libbase",
+ "libutils",
+ "libz",
],
shared_libs: [
"libprotobuf-cpp-lite",
"liblog",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ host: {
+ host_ldlibs: [
+ "-lncurses",
+ ],
+ },
+
+ // The live tests require simpleperf.
+ android: {
+ required: [
+ "simpleperf",
+ ],
+ },
+
+ },
srcs: [
"perfprofd_test.cc",
],
diff --git a/perfprofd/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc
index d6a8f219..61eb09d2 100644
--- a/perfprofd/tests/perfprofd_test.cc
+++ b/perfprofd/tests/perfprofd_test.cc
@@ -17,6 +17,7 @@
#include <algorithm>
#include <cctype>
#include <functional>
+#include <iterator>
#include <memory>
#include <mutex>
#include <regex>
@@ -31,20 +32,25 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
-#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/test_utils.h>
#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>
+#include <zlib.h>
#include "config.h"
#include "configreader.h"
+#include "map_utils.h"
#include "perfprofdcore.h"
+#include "quipper_helper.h"
#include "symbolizer.h"
-#include "perf_profile.pb.h"
-#include "google/protobuf/text_format.h"
+#include "perfprofd_record.pb.h"
+
+using namespace android::perfprofd::quipper;
+
+static_assert(android::base::kEnableDChecks, "Expected DCHECKs to be enabled");
//
// Set to argv[0] on startup
@@ -68,18 +74,32 @@ class TestLogHelper {
std::unique_lock<std::mutex> ul(lock_);
return android::base::Join(test_log_messages_, delimiter);
}
+ template <typename Predicate>
+ std::string JoinTestLog(const char* delimiter, Predicate pred) {
+ std::unique_lock<std::mutex> ul(lock_);
+ std::vector<std::string> tmp;
+ std::copy_if(test_log_messages_.begin(),
+ test_log_messages_.end(),
+ std::back_inserter(tmp),
+ pred);
+ return android::base::Join(tmp, delimiter);
+ }
private:
- void TestLogFunction(LogId log_id ATTRIBUTE_UNUSED,
+ void TestLogFunction(LogId log_id,
LogSeverity severity,
const char* tag,
- const char* file ATTRIBUTE_UNUSED,
- unsigned int line ATTRIBUTE_UNUSED,
+ const char* file,
+ unsigned int line,
const char* message) {
std::unique_lock<std::mutex> ul(lock_);
constexpr char log_characters[] = "VDIWEFF";
char severity_char = log_characters[severity];
test_log_messages_.push_back(android::base::StringPrintf("%c: %s", severity_char, message));
+
+ if (severity >= LogSeverity::FATAL_WITHOUT_ABORT) {
+ android::base::StderrLogger(log_id, severity, tag, file, line, message);
+ }
}
private:
@@ -144,6 +164,7 @@ static std::string replaceAll(const std::string &str,
//
// Replace occurrences of special variables in the string.
//
+#ifdef __ANDROID__
static std::string expandVars(const std::string &str) {
#ifdef __LP64__
return replaceAll(str, "$NATIVE_TESTS", "/data/nativetest64");
@@ -151,6 +172,7 @@ static std::string expandVars(const std::string &str) {
return replaceAll(str, "$NATIVE_TESTS", "/data/nativetest");
#endif
}
+#endif
class PerfProfdTest : public testing::Test {
protected:
@@ -182,7 +204,15 @@ class PerfProfdTest : public testing::Test {
const char* testpoint,
bool exactMatch = false) {
std::string sqexp = squeezeWhite(expected, "expected");
- std::string sqact = squeezeWhite(test_logger.JoinTestLog(" "), "actual");
+
+ // Strip out JIT errors.
+ std::regex jit_regex("E: Failed to open ELF file: [^ ]*ashmem/dalvik-jit-code-cache.*");
+ auto strip_jit = [&](const std::string& str) {
+ std::smatch jit_match;
+ return !std::regex_match(str, jit_match, jit_regex);
+ };
+ std::string sqact = squeezeWhite(test_logger.JoinTestLog(" ", strip_jit), "actual");
+
if (exactMatch) {
EXPECT_STREQ(sqexp.c_str(), sqact.c_str());
} else {
@@ -340,8 +370,8 @@ static std::string encoded_file_path(const std::string& dest_dir,
}
static void readEncodedProfile(const std::string& dest_dir,
- const char *testpoint,
- wireless_android_play_playlog::AndroidPerfProfile &encodedProfile)
+ bool compressed,
+ android::perfprofd::PerfprofdRecord& encodedProfile)
{
struct stat statb;
int perf_data_stat_result = stat(encoded_file_path(dest_dir, 0).c_str(), &statb);
@@ -356,40 +386,56 @@ static void readEncodedProfile(const std::string& dest_dir,
ASSERT_EQ(1, items_read);
fclose(ifp);
- // decode
- encodedProfile.ParseFromString(encoded);
-}
-
-static std::string encodedLoadModuleToString(const wireless_android_play_playlog::LoadModule &lm)
-{
- std::stringstream ss;
- ss << "name: \"" << lm.name() << "\"\n";
- if (lm.build_id() != "") {
- ss << "build_id: \"" << lm.build_id() << "\"\n";
- }
- for (const auto& symbol : lm.symbol()) {
- ss << "symbol: \"" << symbol << "\"\n";
- }
- return ss.str();
-}
+ // uncompress
+ if (compressed && !encoded.empty()) {
+ z_stream stream;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ {
+ constexpr int kWindowBits = 15;
+ constexpr int kGzipEncoding = 16;
+ int init_result = inflateInit2(&stream, kWindowBits | kGzipEncoding);
+ if (init_result != Z_OK) {
+ LOG(ERROR) << "Could not initialize libz stream " << init_result;
+ return;
+ }
+ }
-static std::string encodedModuleSamplesToString(const wireless_android_play_playlog::LoadModuleSamples &mod)
-{
- std::stringstream ss;
-
- ss << "load_module_id: " << mod.load_module_id() << "\n";
- for (size_t k = 0; k < mod.address_samples_size(); k++) {
- const auto &sample = mod.address_samples(k);
- ss << " address_samples {\n";
- for (size_t l = 0; l < mod.address_samples(k).address_size();
- l++) {
- auto address = mod.address_samples(k).address(l);
- ss << " address: " << address << "\n";
+ std::string buf;
+ buf.reserve(2 * encoded.size());
+ stream.avail_in = encoded.size();
+ stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(encoded.data()));
+
+ int result;
+ do {
+ uint8_t chunk[1024];
+ stream.next_out = static_cast<Bytef*>(chunk);
+ stream.avail_out = arraysize(chunk);
+
+ result = inflate(&stream, 0);
+ const size_t amount = arraysize(chunk) - stream.avail_out;
+ if (amount > 0) {
+ if (buf.capacity() - buf.size() < amount) {
+ buf.reserve(buf.capacity() + 64u * 1024u);
+ CHECK_LE(amount, buf.capacity() - buf.size());
+ }
+ size_t index = buf.size();
+ buf.resize(buf.size() + amount);
+ memcpy(reinterpret_cast<uint8_t*>(const_cast<char*>(buf.data())) + index, chunk, amount);
+ }
+ } while (result == Z_OK);
+ inflateEnd(&stream);
+ if (result != Z_STREAM_END) {
+ LOG(ERROR) << "Finished with not-Z_STREAM_END " << result;
+ return;
}
- ss << " count: " << sample.count() << "\n";
- ss << " }\n";
+ encoded = buf;
}
- return ss.str();
+
+ // decode
+ encodedProfile.ParseFromString(encoded);
}
#define RAW_RESULT(x) #x
@@ -527,7 +573,11 @@ TEST_F(PerfProfdTest, BadPerfRun)
runner.addToConfig("main_loop_iterations=1");
runner.addToConfig("use_fixed_seed=1");
runner.addToConfig("collection_interval=100");
+#ifdef __ANDROID__
runner.addToConfig("perf_path=/system/bin/false");
+#else
+ runner.addToConfig("perf_path=/bin/false");
+#endif
// Create semaphore file
runner.create_semaphore_file();
@@ -596,11 +646,193 @@ TEST_F(PerfProfdTest, ProfileCollectionAnnotations)
// completed booted, will be on charger, and will not have the camera
// active.
EXPECT_FALSE(get_booting());
+#ifdef __ANDROID__
EXPECT_TRUE(get_charging());
+#endif
EXPECT_FALSE(get_camera_active());
}
-TEST_F(PerfProfdTest, BasicRunWithCannedPerf)
+namespace {
+
+template <typename Iterator>
+size_t CountEvents(const quipper::PerfDataProto& proto) {
+ size_t count = 0;
+ for (Iterator it(proto); it != it.end(); ++it) {
+ count++;
+ }
+ return count;
+}
+
+size_t CountCommEvents(const quipper::PerfDataProto& proto) {
+ return CountEvents<CommEventIterator>(proto);
+}
+size_t CountMmapEvents(const quipper::PerfDataProto& proto) {
+ return CountEvents<MmapEventIterator>(proto);
+}
+size_t CountSampleEvents(const quipper::PerfDataProto& proto) {
+ return CountEvents<SampleEventIterator>(proto);
+}
+size_t CountForkEvents(const quipper::PerfDataProto& proto) {
+ return CountEvents<ForkEventIterator>(proto);
+}
+size_t CountExitEvents(const quipper::PerfDataProto& proto) {
+ return CountEvents<ExitEventIterator>(proto);
+}
+
+std::string CreateStats(const quipper::PerfDataProto& proto) {
+ std::ostringstream oss;
+ oss << "Mmap events: " << CountMmapEvents(proto) << std::endl;
+ oss << "Sample events: " << CountSampleEvents(proto) << std::endl;
+ oss << "Comm events: " << CountCommEvents(proto) << std::endl;
+ oss << "Fork events: " << CountForkEvents(proto) << std::endl;
+ oss << "Exit events: " << CountExitEvents(proto) << std::endl;
+ return oss.str();
+}
+
+std::string FormatSampleEvent(const quipper::PerfDataProto_SampleEvent& sample) {
+ std::ostringstream oss;
+ if (sample.has_pid()) {
+ oss << "pid=" << sample.pid();
+ }
+ if (sample.has_tid()) {
+ oss << " tid=" << sample.tid();
+ }
+ if (sample.has_ip()) {
+ oss << " ip=" << sample.ip();
+ }
+ if (sample.has_addr()) {
+ oss << " addr=" << sample.addr();
+ }
+ if (sample.callchain_size() > 0) {
+ oss << " callchain=";
+ for (uint64_t cc : sample.callchain()) {
+ oss << "->" << cc;
+ }
+ }
+ return oss.str();
+}
+
+}
+
+struct BasicRunWithCannedPerf : PerfProfdTest {
+ void VerifyBasicCannedProfile(const android::perfprofd::PerfprofdRecord& encodedProfile) {
+ ASSERT_TRUE(encodedProfile.has_perf_data()) << test_logger.JoinTestLog(" ");
+ const quipper::PerfDataProto& perf_data = encodedProfile.perf_data();
+
+ // Expect 21108 events.
+ EXPECT_EQ(21108, perf_data.events_size()) << CreateStats(perf_data);
+
+ EXPECT_EQ(48, CountMmapEvents(perf_data)) << CreateStats(perf_data);
+ EXPECT_EQ(19986, CountSampleEvents(perf_data)) << CreateStats(perf_data);
+ EXPECT_EQ(1033, CountCommEvents(perf_data)) << CreateStats(perf_data);
+ EXPECT_EQ(15, CountForkEvents(perf_data)) << CreateStats(perf_data);
+ EXPECT_EQ(26, CountExitEvents(perf_data)) << CreateStats(perf_data);
+
+ if (HasNonfatalFailure()) {
+ FAIL();
+ }
+
+ {
+ MmapEventIterator mmap(perf_data);
+ constexpr std::pair<const char*, uint64_t> kMmapEvents[] = {
+ std::make_pair("[kernel.kallsyms]_text", 0),
+ std::make_pair("/system/lib/libc.so", 3067412480u),
+ std::make_pair("/system/vendor/lib/libdsutils.so", 3069911040u),
+ std::make_pair("/system/lib/libc.so", 3067191296u),
+ std::make_pair("/system/lib/libc++.so", 3069210624u),
+ std::make_pair("/data/dalvik-cache/arm/system@framework@boot.oat", 1900048384u),
+ std::make_pair("/system/lib/libjavacore.so", 2957135872u),
+ std::make_pair("/system/vendor/lib/libqmi_encdec.so", 3006644224u),
+ std::make_pair("/data/dalvik-cache/arm/system@framework@wifi-service.jar@classes.dex",
+ 3010351104u),
+ std::make_pair("/system/lib/libart.so", 3024150528u),
+ std::make_pair("/system/lib/libz.so", 3056410624u),
+ std::make_pair("/system/lib/libicui18n.so", 3057610752u),
+ };
+ for (auto& pair : kMmapEvents) {
+ EXPECT_STREQ(pair.first, mmap->mmap_event().filename().c_str());
+ EXPECT_EQ(pair.second, mmap->mmap_event().start()) << pair.first;
+ ++mmap;
+ }
+ }
+
+ {
+ CommEventIterator comm(perf_data);
+ constexpr const char* kCommEvents[] = {
+ "init", "kthreadd", "ksoftirqd/0", "kworker/u:0H", "migration/0", "khelper",
+ "netns", "modem_notifier", "smd_channel_clo", "smsm_cb_wq", "rpm-smd", "kworker/u:1H",
+ };
+ for (auto str : kCommEvents) {
+ EXPECT_STREQ(str, comm->comm_event().comm().c_str());
+ ++comm;
+ }
+ }
+
+ {
+ SampleEventIterator samples(perf_data);
+ constexpr const char* kSampleEvents[] = {
+ "pid=0 tid=0 ip=3222720196",
+ "pid=0 tid=0 ip=3222910876",
+ "pid=0 tid=0 ip=3222910876",
+ "pid=0 tid=0 ip=3222910876",
+ "pid=0 tid=0 ip=3222910876",
+ "pid=0 tid=0 ip=3222910876",
+ "pid=0 tid=0 ip=3222910876",
+ "pid=3 tid=3 ip=3231975108",
+ "pid=5926 tid=5926 ip=3231964952",
+ "pid=5926 tid=5926 ip=3225342428",
+ "pid=5926 tid=5926 ip=3223841448",
+ "pid=5926 tid=5926 ip=3069807920",
+ };
+ for (auto str : kSampleEvents) {
+ EXPECT_STREQ(str, FormatSampleEvent(samples->sample_event()).c_str());
+ ++samples;
+ }
+
+ // Skip some samples.
+ for (size_t i = 0; i != 5000; ++i) {
+ ++samples;
+ }
+ constexpr const char* kSampleEvents2[] = {
+ "pid=5938 tid=5938 ip=3069630992",
+ "pid=5938 tid=5938 ip=3069626616",
+ "pid=5938 tid=5938 ip=3069626636",
+ "pid=5938 tid=5938 ip=3069637212",
+ "pid=5938 tid=5938 ip=3069637208",
+ "pid=5938 tid=5938 ip=3069637252",
+ "pid=5938 tid=5938 ip=3069346040",
+ "pid=5938 tid=5938 ip=3069637128",
+ "pid=5938 tid=5938 ip=3069626616",
+ };
+ for (auto str : kSampleEvents2) {
+ EXPECT_STREQ(str, FormatSampleEvent(samples->sample_event()).c_str());
+ ++samples;
+ }
+
+ // Skip some samples.
+ for (size_t i = 0; i != 5000; ++i) {
+ ++samples;
+ }
+ constexpr const char* kSampleEvents3[] = {
+ "pid=5938 tid=5938 ip=3069912036",
+ "pid=5938 tid=5938 ip=3069637260",
+ "pid=5938 tid=5938 ip=3069631024",
+ "pid=5938 tid=5938 ip=3069346064",
+ "pid=5938 tid=5938 ip=3069637356",
+ "pid=5938 tid=5938 ip=3069637144",
+ "pid=5938 tid=5938 ip=3069912036",
+ "pid=5938 tid=5938 ip=3069912036",
+ "pid=5938 tid=5938 ip=3069631244",
+ };
+ for (auto str : kSampleEvents3) {
+ EXPECT_STREQ(str, FormatSampleEvent(samples->sample_event()).c_str());
+ ++samples;
+ }
+ }
+ }
+};
+
+TEST_F(BasicRunWithCannedPerf, Basic)
{
//
// Verify the portion of the daemon that reads and encodes
@@ -616,6 +848,10 @@ TEST_F(PerfProfdTest, BasicRunWithCannedPerf)
config_reader.overrideUnsignedEntry("collect_cpu_utilization", 0);
config_reader.overrideUnsignedEntry("collect_charging_state", 0);
config_reader.overrideUnsignedEntry("collect_camera_active", 0);
+
+ // Disable compression.
+ config_reader.overrideUnsignedEntry("compress", 0);
+
PerfProfdRunner::LoggingConfig config;
config_reader.FillConfig(&config);
@@ -625,60 +861,13 @@ TEST_F(PerfProfdTest, BasicRunWithCannedPerf)
ASSERT_EQ(OK_PROFILE_COLLECTION, result) << test_logger.JoinTestLog(" ");
// Read and decode the resulting perf.data.encoded file
- wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
- readEncodedProfile(dest_dir,
- "BasicRunWithCannedPerf",
- encodedProfile);
-
- // Expect 48 programs
- EXPECT_EQ(48, encodedProfile.programs_size());
-
- // Check a couple of load modules
- { const auto &lm0 = encodedProfile.load_modules(0);
- std::string act_lm0 = encodedLoadModuleToString(lm0);
- std::string sqact0 = squeezeWhite(act_lm0, "actual for lm 0");
- const std::string expected_lm0 = RAW_RESULT(
- name: "/data/app/com.google.android.apps.plus-1/lib/arm/libcronet.so"
- );
- std::string sqexp0 = squeezeWhite(expected_lm0, "expected_lm0");
- EXPECT_STREQ(sqexp0.c_str(), sqact0.c_str());
- }
- { const auto &lm9 = encodedProfile.load_modules(9);
- std::string act_lm9 = encodedLoadModuleToString(lm9);
- std::string sqact9 = squeezeWhite(act_lm9, "actual for lm 9");
- const std::string expected_lm9 = RAW_RESULT(
- name: "/system/lib/libandroid_runtime.so" build_id: "8164ed7b3a8b8f5a220d027788922510"
- );
- std::string sqexp9 = squeezeWhite(expected_lm9, "expected_lm9");
- EXPECT_STREQ(sqexp9.c_str(), sqact9.c_str());
- }
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, false, encodedProfile);
- // Examine some of the samples now
- { const auto &p1 = encodedProfile.programs(9);
- const auto &lm1 = p1.modules(0);
- std::string act_lm1 = encodedModuleSamplesToString(lm1);
- std::string sqact1 = squeezeWhite(act_lm1, "actual for lm1");
- const std::string expected_lm1 = RAW_RESULT(
- load_module_id: 9 address_samples { address: 296100 count: 1 }
- );
- std::string sqexp1 = squeezeWhite(expected_lm1, "expected_lm1");
- EXPECT_STREQ(sqexp1.c_str(), sqact1.c_str());
- }
- { const auto &p1 = encodedProfile.programs(11);
- const auto &lm2 = p1.modules(0);
- std::string act_lm2 = encodedModuleSamplesToString(lm2);
- std::string sqact2 = squeezeWhite(act_lm2, "actual for lm2");
- const std::string expected_lm2 = RAW_RESULT(
- load_module_id: 2
- address_samples { address: 28030244 count: 1 }
- address_samples { address: 29657840 count: 1 }
- );
- std::string sqexp2 = squeezeWhite(expected_lm2, "expected_lm2");
- EXPECT_STREQ(sqexp2.c_str(), sqact2.c_str());
- }
+ VerifyBasicCannedProfile(encodedProfile);
}
-TEST_F(PerfProfdTest, BasicRunWithCannedPerfWithSymbolizer)
+TEST_F(BasicRunWithCannedPerf, Compressed)
{
//
// Verify the portion of the daemon that reads and encodes
@@ -694,6 +883,45 @@ TEST_F(PerfProfdTest, BasicRunWithCannedPerfWithSymbolizer)
config_reader.overrideUnsignedEntry("collect_cpu_utilization", 0);
config_reader.overrideUnsignedEntry("collect_charging_state", 0);
config_reader.overrideUnsignedEntry("collect_camera_active", 0);
+
+ // Enable compression.
+ config_reader.overrideUnsignedEntry("compress", 1);
+
+ PerfProfdRunner::LoggingConfig config;
+ config_reader.FillConfig(&config);
+
+ // Kick off encoder and check return code
+ PROFILE_RESULT result =
+ encode_to_proto(input_perf_data, encoded_file_path(dest_dir, 0).c_str(), config, 0, nullptr);
+ ASSERT_EQ(OK_PROFILE_COLLECTION, result) << test_logger.JoinTestLog(" ");
+
+ // Read and decode the resulting perf.data.encoded file
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, true, encodedProfile);
+
+ VerifyBasicCannedProfile(encodedProfile);
+}
+
+TEST_F(BasicRunWithCannedPerf, WithSymbolizer)
+{
+ //
+ // Verify the portion of the daemon that reads and encodes
+ // perf.data files. Here we run the encoder on a canned perf.data
+ // file and verify that the resulting protobuf contains what
+ // we think it should contain.
+ //
+ std::string input_perf_data(test_dir);
+ input_perf_data += "/canned.perf.data";
+
+ // Set up config to avoid these annotations (they are tested elsewhere)
+ ConfigReader config_reader;
+ config_reader.overrideUnsignedEntry("collect_cpu_utilization", 0);
+ config_reader.overrideUnsignedEntry("collect_charging_state", 0);
+ config_reader.overrideUnsignedEntry("collect_camera_active", 0);
+
+ // Disable compression.
+ config_reader.overrideUnsignedEntry("compress", 0);
+
PerfProfdRunner::LoggingConfig config;
config_reader.FillConfig(&config);
@@ -702,6 +930,10 @@ TEST_F(PerfProfdTest, BasicRunWithCannedPerfWithSymbolizer)
std::string Decode(const std::string& dso, uint64_t address) override {
return dso + "@" + std::to_string(address);
}
+ bool GetMinExecutableVAddr(const std::string& dso, uint64_t* addr) override {
+ *addr = 4096;
+ return true;
+ }
};
TestSymbolizer test_symbolizer;
PROFILE_RESULT result =
@@ -713,59 +945,37 @@ TEST_F(PerfProfdTest, BasicRunWithCannedPerfWithSymbolizer)
ASSERT_EQ(OK_PROFILE_COLLECTION, result);
// Read and decode the resulting perf.data.encoded file
- wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
- readEncodedProfile(dest_dir,
- "BasicRunWithCannedPerf",
- encodedProfile);
-
- // Expect 45 programs
- EXPECT_EQ(48, encodedProfile.programs_size());
-
- // Check a couple of load modules
- { const auto &lm0 = encodedProfile.load_modules(0);
- std::string act_lm0 = encodedLoadModuleToString(lm0);
- std::string sqact0 = squeezeWhite(act_lm0, "actual for lm 0");
- const std::string expected_lm0 = RAW_RESULT(
- name: "/data/app/com.google.android.apps.plus-1/lib/arm/libcronet.so"
- symbol: "/data/app/com.google.android.apps.plus-1/lib/arm/libcronet.so@310106"
- symbol: "/data/app/com.google.android.apps.plus-1/lib/arm/libcronet.so@1949952"
- );
- std::string sqexp0 = squeezeWhite(expected_lm0, "expected_lm0");
- EXPECT_STREQ(sqexp0.c_str(), sqact0.c_str());
- }
- { const auto &lm9 = encodedProfile.load_modules(9);
- std::string act_lm9 = encodedLoadModuleToString(lm9);
- std::string sqact9 = squeezeWhite(act_lm9, "actual for lm 9");
- const std::string expected_lm9 = RAW_RESULT(
- name: "/system/lib/libandroid_runtime.so" build_id: "8164ed7b3a8b8f5a220d027788922510"
- );
- std::string sqexp9 = squeezeWhite(expected_lm9, "expected_lm9");
- EXPECT_STREQ(sqexp9.c_str(), sqact9.c_str());
- }
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, false, encodedProfile);
- // Examine some of the samples now
- { const auto &p1 = encodedProfile.programs(9);
- const auto &lm1 = p1.modules(0);
- std::string act_lm1 = encodedModuleSamplesToString(lm1);
- std::string sqact1 = squeezeWhite(act_lm1, "actual for lm1");
- const std::string expected_lm1 = RAW_RESULT(
- load_module_id: 9 address_samples { address: 296100 count: 1 }
- );
- std::string sqexp1 = squeezeWhite(expected_lm1, "expected_lm1");
- EXPECT_STREQ(sqexp1.c_str(), sqact1.c_str());
- }
- { const auto &p1 = encodedProfile.programs(11);
- const auto &lm2 = p1.modules(0);
- std::string act_lm2 = encodedModuleSamplesToString(lm2);
- std::string sqact2 = squeezeWhite(act_lm2, "actual for lm2");
- const std::string expected_lm2 = RAW_RESULT(
- load_module_id: 2
- address_samples { address: 18446744073709551615 count: 1 }
- address_samples { address: 18446744073709551614 count: 1 }
- );
- std::string sqexp2 = squeezeWhite(expected_lm2, "expected_lm2");
- EXPECT_STREQ(sqexp2.c_str(), sqact2.c_str());
- }
+ VerifyBasicCannedProfile(encodedProfile);
+
+ auto find_symbol = [&](const std::string& filename)
+ -> const android::perfprofd::PerfprofdRecord_SymbolInfo* {
+ for (auto& symbol_info : encodedProfile.symbol_info()) {
+ if (symbol_info.filename() == filename) {
+ return &symbol_info;
+ }
+ }
+ return nullptr;
+ };
+ auto all_filenames = [&]() {
+ std::ostringstream oss;
+ for (auto& symbol_info : encodedProfile.symbol_info()) {
+ oss << " " << symbol_info.filename();
+ }
+ return oss.str();
+ };
+
+ EXPECT_TRUE(find_symbol("/data/app/com.google.android.apps.plus-1/lib/arm/libcronet.so")
+ != nullptr) << all_filenames() << test_logger.JoinTestLog("\n");
+ EXPECT_TRUE(find_symbol("/data/dalvik-cache/arm/system@framework@wifi-service.jar@classes.dex")
+ != nullptr) << all_filenames();
+ EXPECT_TRUE(find_symbol("/data/dalvik-cache/arm/data@app@com.google.android.gms-2@base.apk@"
+ "classes.dex")
+ != nullptr) << all_filenames();
+ EXPECT_TRUE(find_symbol("/data/dalvik-cache/arm/system@framework@boot.oat") != nullptr)
+ << all_filenames();
}
TEST_F(PerfProfdTest, CallchainRunWithCannedPerf)
@@ -781,6 +991,10 @@ TEST_F(PerfProfdTest, CallchainRunWithCannedPerf)
config_reader.overrideUnsignedEntry("collect_cpu_utilization", 0);
config_reader.overrideUnsignedEntry("collect_charging_state", 0);
config_reader.overrideUnsignedEntry("collect_camera_active", 0);
+
+ // Disable compression.
+ config_reader.overrideUnsignedEntry("compress", 0);
+
PerfProfdRunner::LoggingConfig config;
config_reader.FillConfig(&config);
@@ -790,62 +1004,60 @@ TEST_F(PerfProfdTest, CallchainRunWithCannedPerf)
ASSERT_EQ(OK_PROFILE_COLLECTION, result);
// Read and decode the resulting perf.data.encoded file
- wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
- readEncodedProfile(dest_dir,
- "BasicRunWithCannedPerf",
- encodedProfile);
-
-
- // Expect 3 programs 8 load modules
- EXPECT_EQ(3, encodedProfile.programs_size());
- EXPECT_EQ(8, encodedProfile.load_modules_size());
-
- // Check a couple of load modules
- { const auto &lm0 = encodedProfile.load_modules(0);
- std::string act_lm0 = encodedLoadModuleToString(lm0);
- std::string sqact0 = squeezeWhite(act_lm0, "actual for lm 0");
- const std::string expected_lm0 = RAW_RESULT(
- name: "/system/bin/dex2oat"
- build_id: "ee12bd1a1de39422d848f249add0afc4"
- );
- std::string sqexp0 = squeezeWhite(expected_lm0, "expected_lm0");
- EXPECT_STREQ(sqexp0.c_str(), sqact0.c_str());
- }
- { const auto &lm1 = encodedProfile.load_modules(1);
- std::string act_lm1 = encodedLoadModuleToString(lm1);
- std::string sqact1 = squeezeWhite(act_lm1, "actual for lm 1");
- const std::string expected_lm1 = RAW_RESULT(
- name: "/system/bin/linker"
- build_id: "a36715f673a4a0aa76ef290124c516cc"
- );
- std::string sqexp1 = squeezeWhite(expected_lm1, "expected_lm1");
- EXPECT_STREQ(sqexp1.c_str(), sqact1.c_str());
- }
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, false, encodedProfile);
- // Examine some of the samples now
- { const auto &p0 = encodedProfile.programs(1);
- const auto &lm1 = p0.modules(0);
- std::string act_lm1 = encodedModuleSamplesToString(lm1);
- std::string sqact1 = squeezeWhite(act_lm1, "actual for lm1");
- const std::string expected_lm1 = RAW_RESULT(
- load_module_id: 0
- address_samples { address: 108552 count: 2 }
- );
- std::string sqexp1 = squeezeWhite(expected_lm1, "expected_lm1");
- EXPECT_STREQ(sqexp1.c_str(), sqact1.c_str());
- }
- { const auto &p4 = encodedProfile.programs(2);
- const auto &lm2 = p4.modules(1);
- std::string act_lm2 = encodedModuleSamplesToString(lm2);
- std::string sqact2 = squeezeWhite(act_lm2, "actual for lm2");
- const std::string expected_lm2 = RAW_RESULT(
- load_module_id: 2 address_samples { address: 403913 count: 1 } address_samples { address: 840761 count: 1 } address_samples { address: 846481 count: 1 } address_samples { address: 999053 count: 1 } address_samples { address: 1012959 count: 1 } address_samples { address: 1524309 count: 1 } address_samples { address: 1580779 count: 1 } address_samples { address: 4287986288 count: 1 }
- );
- std::string sqexp2 = squeezeWhite(expected_lm2, "expected_lm2");
- EXPECT_STREQ(sqexp2.c_str(), sqact2.c_str());
+
+ ASSERT_TRUE(encodedProfile.has_perf_data());
+ const quipper::PerfDataProto& perf_data = encodedProfile.perf_data();
+
+ // Expect 21108 events.
+ EXPECT_EQ(2224, perf_data.events_size()) << CreateStats(perf_data);
+
+ {
+ SampleEventIterator samples(perf_data);
+ constexpr const char* kSampleEvents[] = {
+ "0: pid=6225 tid=6225 ip=18446743798834668032 callchain=->18446744073709551488->"
+ "18446743798834668032->18446743798834782596->18446743798834784624->"
+ "18446743798835055136->18446743798834788016->18446743798834789192->"
+ "18446743798834789512->18446743798834790216->18446743798833756776",
+ "1: pid=6225 tid=6225 ip=18446743798835685700 callchain=->18446744073709551488->"
+ "18446743798835685700->18446743798835688704->18446743798835650964->"
+ "18446743798834612104->18446743798834612276->18446743798835055528->"
+ "18446743798834788016->18446743798834789192->18446743798834789512->"
+ "18446743798834790216->18446743798833756776",
+ "2: pid=6225 tid=6225 ip=18446743798835055804 callchain=->18446744073709551488->"
+ "18446743798835055804->18446743798834788016->18446743798834789192->"
+ "18446743798834789512->18446743798834790216->18446743798833756776",
+ "3: pid=6225 tid=6225 ip=18446743798835991212 callchain=->18446744073709551488->"
+ "18446743798835991212->18446743798834491060->18446743798834675572->"
+ "18446743798834676516->18446743798834612172->18446743798834612276->"
+ "18446743798835056664->18446743798834788016->18446743798834789192->"
+ "18446743798834789512->18446743798834790216->18446743798833756776",
+ "4: pid=6225 tid=6225 ip=18446743798844881108 callchain=->18446744073709551488->"
+ "18446743798844881108->18446743798834836140->18446743798834846384->"
+ "18446743798834491100->18446743798834675572->18446743798834676516->"
+ "18446743798834612172->18446743798834612276->18446743798835056784->"
+ "18446743798834788016->18446743798834789192->18446743798834789512->"
+ "18446743798834790216->18446743798833756776",
+ };
+ size_t cmp_index = 0;
+ for (size_t index = 0; samples != samples.end(); ++samples, ++index) {
+ if (samples->sample_event().callchain_size() > 0) {
+ std::ostringstream oss;
+ oss << index << ": " << FormatSampleEvent(samples->sample_event());
+ EXPECT_STREQ(kSampleEvents[cmp_index], oss.str().c_str());
+ cmp_index++;
+ if (cmp_index == arraysize(kSampleEvents)) {
+ break;
+ }
+ }
+ }
}
}
+#ifdef __ANDROID__
+
TEST_F(PerfProfdTest, BasicRunWithLivePerf)
{
//
@@ -866,6 +1078,9 @@ TEST_F(PerfProfdTest, BasicRunWithLivePerf)
// Avoid the symbolizer for spurious messages.
runner.addToConfig("use_elf_symbolizer=0");
+ // Disable compression.
+ runner.addToConfig("compress=0");
+
// Create semaphore file
runner.create_semaphore_file();
@@ -876,12 +1091,12 @@ TEST_F(PerfProfdTest, BasicRunWithLivePerf)
ASSERT_EQ(0, daemon_main_return_code);
// Read and decode the resulting perf.data.encoded file
- wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
- readEncodedProfile(dest_dir, "BasicRunWithLivePerf", encodedProfile);
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, false, encodedProfile);
// Examine what we get back. Since it's a live profile, we can't
// really do much in terms of verifying the contents.
- EXPECT_LT(0, encodedProfile.programs_size());
+ EXPECT_LT(0, encodedProfile.perf_data().events_size());
// Verify log contents
const std::string expected = std::string(
@@ -918,6 +1133,10 @@ TEST_F(PerfProfdTest, MultipleRunWithLivePerf)
runner.addToConfig("sample_duration=2");
// Avoid the symbolizer for spurious messages.
runner.addToConfig("use_elf_symbolizer=0");
+
+ // Disable compression.
+ runner.addToConfig("compress=0");
+
runner.write_processed_file(1, 2);
// Create semaphore file
@@ -930,12 +1149,12 @@ TEST_F(PerfProfdTest, MultipleRunWithLivePerf)
ASSERT_EQ(0, daemon_main_return_code);
// Read and decode the resulting perf.data.encoded file
- wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
- readEncodedProfile(dest_dir, "BasicRunWithLivePerf", encodedProfile);
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, false, encodedProfile);
// Examine what we get back. Since it's a live profile, we can't
// really do much in terms of verifying the contents.
- EXPECT_LT(0, encodedProfile.programs_size());
+ EXPECT_LT(0, encodedProfile.perf_data().events_size());
// Examine that encoded.1 file is removed while encoded.{0|2} exists.
EXPECT_EQ(0, access(encoded_file_path(dest_dir, 0).c_str(), F_OK));
@@ -989,6 +1208,9 @@ TEST_F(PerfProfdTest, CallChainRunWithLivePerf)
// Avoid the symbolizer for spurious messages.
runner.addToConfig("use_elf_symbolizer=0");
+ // Disable compression.
+ runner.addToConfig("compress=0");
+
// Create semaphore file
runner.create_semaphore_file();
@@ -999,12 +1221,12 @@ TEST_F(PerfProfdTest, CallChainRunWithLivePerf)
ASSERT_EQ(0, daemon_main_return_code);
// Read and decode the resulting perf.data.encoded file
- wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
- readEncodedProfile(dest_dir, "CallChainRunWithLivePerf", encodedProfile);
+ android::perfprofd::PerfprofdRecord encodedProfile;
+ readEncodedProfile(dest_dir, false, encodedProfile);
// Examine what we get back. Since it's a live profile, we can't
// really do much in terms of verifying the contents.
- EXPECT_LT(0, encodedProfile.programs_size());
+ EXPECT_LT(0, encodedProfile.perf_data().events_size());
// Verify log contents
const std::string expected = std::string(
@@ -1021,6 +1243,58 @@ TEST_F(PerfProfdTest, CallChainRunWithLivePerf)
);
// check to make sure log excerpt matches
CompareLogMessages(expandVars(expected), "CallChainRunWithLivePerf", true);
+
+ // Check that we have at least one SampleEvent with a callchain.
+ SampleEventIterator samples(encodedProfile.perf_data());
+ bool found_callchain = false;
+ while (!found_callchain && samples != samples.end()) {
+ found_callchain = samples->sample_event().callchain_size() > 0;
+ }
+ EXPECT_TRUE(found_callchain) << CreateStats(encodedProfile.perf_data());
+}
+
+#endif
+
+class RangeMapTest : public testing::Test {
+};
+
+TEST_F(RangeMapTest, TestRangeMap) {
+ using namespace android::perfprofd;
+
+ RangeMap<std::string, uint64_t> map;
+ auto print = [&]() {
+ std::ostringstream oss;
+ for (auto& aggr_sym : map) {
+ oss << aggr_sym.first << "#" << aggr_sym.second.symbol;
+ oss << "[";
+ for (auto& x : aggr_sym.second.offsets) {
+ oss << x << ",";
+ }
+ oss << "]";
+ }
+ return oss.str();
+ };
+
+ EXPECT_STREQ("", print().c_str());
+
+ map.Insert("a", 10);
+ EXPECT_STREQ("10#a[10,]", print().c_str());
+ map.Insert("a", 100);
+ EXPECT_STREQ("10#a[10,100,]", print().c_str());
+ map.Insert("a", 1);
+ EXPECT_STREQ("1#a[1,10,100,]", print().c_str());
+ map.Insert("a", 1);
+ EXPECT_STREQ("1#a[1,10,100,]", print().c_str());
+ map.Insert("a", 2);
+ EXPECT_STREQ("1#a[1,2,10,100,]", print().c_str());
+
+ map.Insert("b", 200);
+ EXPECT_STREQ("1#a[1,2,10,100,]200#b[200,]", print().c_str());
+ map.Insert("b", 199);
+ EXPECT_STREQ("1#a[1,2,10,100,]199#b[199,200,]", print().c_str());
+
+ map.Insert("c", 50);
+ EXPECT_STREQ("1#a[1,2,10,]50#c[50,]100#a[100,]199#b[199,200,]", print().c_str());
}
int main(int argc, char **argv) {
diff --git a/simpleperf/Android.mk b/simpleperf/Android.mk
index 01263516..05a94717 100644
--- a/simpleperf/Android.mk
+++ b/simpleperf/Android.mk
@@ -178,10 +178,12 @@ LOCAL_CFLAGS := $(simpleperf_cflags_target)
LOCAL_SRC_FILES := main.cpp
LOCAL_STATIC_LIBRARIES := libsimpleperf $(simpleperf_static_libraries_with_libc_target)
ifdef TARGET_2ND_ARCH
+ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := simpleperf32
LOCAL_MODULE_STEM_64 := simpleperf
endif
+endif
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(LLVM_DEVICE_BUILD_MK)
include $(BUILD_EXECUTABLE)