diff options
author | Andreas Gampe <agampe@google.com> | 2018-03-13 16:04:01 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2018-03-23 19:51:09 -0700 |
commit | b73bc962b85c9fdcf9bc4e7a8479885a18974b07 (patch) | |
tree | 89d751b30c7063f82e551f61754b026b1f32ae13 | |
parent | 0bdadad9e5572ef6483f70b51a52b70b9a908fba (diff) | |
download | extras-b73bc962b85c9fdcf9bc4e7a8479885a18974b07.tar.gz |
Perfprofd: Use external quipper
Switch to using external/perf_data_converter. This removes
on-device symbolization for the moment.
(cherry picked from commit 0c09e0ec9942acc56454720ccc6d26a61e4b2085)
Bug: 73175642
Test: mmma system/extras/perfprofd
Test: perfprofd_test
Merged-In: I01dc7c54299c295b29475632d5b6cf7ce68c236c
Change-Id: I01dc7c54299c295b29475632d5b6cf7ce68c236c
45 files changed, 527 insertions, 7517 deletions
diff --git a/perfprofd/Android.bp b/perfprofd/Android.bp index 2787dc69..498b6452 100644 --- a/perfprofd/Android.bp +++ b/perfprofd/Android.bp @@ -51,19 +51,16 @@ cc_library_static { "perfprofd_defaults", ], - local_include_dirs: ["quipper/kernel-headers"], - export_include_dirs: ["."], static_libs: [ "libbase", + "libquipper", "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", @@ -73,7 +70,15 @@ cc_library_static { proto: { export_proto_headers: true, + include_dirs: ["external/perf_data_converter/src/quipper"], + type: "lite", }, + cflags: [ + "-Wno-gnu-anonymous-struct", + ], + + export_include_dirs: ["."], + export_static_lib_headers: ["libquipper"], } // diff --git a/perfprofd/binder_interface/perfprofd_binder.cc b/perfprofd/binder_interface/perfprofd_binder.cc index 388dea61..50f6aee2 100644 --- a/perfprofd/binder_interface/perfprofd_binder.cc +++ b/perfprofd/binder_interface/perfprofd_binder.cc @@ -30,8 +30,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,7 +45,7 @@ #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" @@ -129,7 +131,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(); @@ -148,7 +150,7 @@ class PerfProfdNativeService : public BinderService<PerfProfdNativeService>, }; 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) { diff --git a/perfprofd/perf_data_converter.cc b/perfprofd/perf_data_converter.cc index 9d35d337..ffd1444d 100644 --- a/perfprofd/perf_data_converter.cc +++ b/perfprofd/perf_data_converter.cc @@ -4,330 +4,44 @@ #include <algorithm> #include <limits> #include <map> +#include <memory> #include <unordered_map> +#include <android-base/macros.h> #include <android-base/strings.h> +#include <perf_parser.h> +#include <perf_protobuf_io.h> -#include "perf_profile.pb.h" +#include "perfprofd_record.pb.h" -#include "quipper/perf_parser.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; - -// 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; - -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(); - } - int rc = do1->dso_name().compare(do2->dso_name()); - if (rc) { - return rc < 0; - } - } - 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* +PerfprofdRecord* RawPerfDataToAndroidPerfProfile(const string &perf_file, - ::perfprofd::Symbolizer* symbolizer) { - quipper::PerfParser parser; - if (!parser.ReadFile(perf_file) || !parser.ParseRawEvents()) { - return nullptr; - } - 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>; + ::perfprofd::Symbolizer* symbolizer ATTRIBUTE_UNUSED) { + std::unique_ptr<PerfprofdRecord> ret(new PerfprofdRecord()); + ret->set_id(0); // TODO. - 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; + quipper::PerfParserOptions options = {}; + options.do_remap = true; + options.discard_unused_events = true; + options.read_missing_buildids = true; - // 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; - } - } - return false; - }; - - for (const auto &event : parser.parsed_events()) { - if (!event.raw_event || - event.raw_event->header.type != PERF_RECORD_SAMPLE) { - 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)]++; - } - } - } + quipper::PerfDataProto* perf_data = ret->mutable_perf_data(); - struct ModuleData { - int index = 0; - - std::vector<std::string> symbols; - std::unordered_map<uint64_t, size_t> addr_to_symbol_index; - - 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(); - } - } - 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); - } - } - 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); - } else { - index = it - module_data->symbols.begin(); - } - 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); - } - 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())); - } - } - } - } - - 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 (!quipper::SerializeFromFileWithOptions(perf_file, options, perf_data)) { + return nullptr; } - 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); - } - } + // TODO: Symbolization. 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_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..95a9d316 --- /dev/null +++ b/perfprofd/perfprofd_record.proto @@ -0,0 +1,37 @@ + +syntax = "proto2"; + +import "perf_data.proto"; + +option java_package = "com.google.android.perfprofd"; + +package android.perfprofd; + +message PerfprofdRecord { + optional int64 id = 1; + optional quipper.PerfDataProto perf_data = 2; + + // 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..d1a9d3c7 100644 --- a/perfprofd/perfprofdcore.cc +++ b/perfprofd/perfprofdcore.cc @@ -43,12 +43,12 @@ #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> -#include "perf_profile.pb.h" +#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 "symbolizer.h" // @@ -61,6 +61,8 @@ //...................................................................... +using ProtoUniquePtr = std::unique_ptr<android::perfprofd::PerfprofdRecord>; + // // Output file from 'perf record'. // @@ -416,7 +418,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,28 +470,7 @@ 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, - perfprofd::Symbolizer* symbolizer) { - // - // Open and read perf.data file - // - ProtoUniquePtr encodedProfile( - wireless_android_logging_awp::RawPerfDataToAndroidPerfProfile(data_file_path, symbolizer)); - if (encodedProfile == nullptr) { - return nullptr; - } - - // All of the info in 'encodedProfile' is derived from the perf.data file; - // here we tack display status, cpu utilization, system load, etc. - annotate_encoded_perf_profile(encodedProfile.get(), config, cpu_utilization); - - return encodedProfile; -} - -PROFILE_RESULT SerializeProtobuf(wireless_android_play_playlog::AndroidPerfProfile* encodedProfile, +PROFILE_RESULT SerializeProtobuf(android::perfprofd::PerfprofdRecord* encodedProfile, const char* encoded_file_path) { // // Serialize protobuf to array @@ -516,6 +497,26 @@ PROFILE_RESULT SerializeProtobuf(wireless_android_play_playlog::AndroidPerfProfi return OK_PROFILE_COLLECTION; } +static ProtoUniquePtr encode_to_proto(const std::string &data_file_path, + const Config& config, + unsigned cpu_utilization, + perfprofd::Symbolizer* symbolizer) { + // + // Open and read perf.data file + // + ProtoUniquePtr encodedProfile( + android::perfprofd::RawPerfDataToAndroidPerfProfile(data_file_path, symbolizer)); + if (encodedProfile == nullptr) { + return nullptr; + } + + // All of the info in 'encodedProfile' is derived from the perf.data file; + // here we tack display status, cpu utilization, system load, etc. + annotate_encoded_perf_profile(encodedProfile.get(), config, cpu_utilization); + + return encodedProfile; +} + PROFILE_RESULT encode_to_proto(const std::string &data_file_path, const char *encoded_file_path, const Config& config, @@ -530,7 +531,7 @@ 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; } @@ -1008,8 +1009,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; } diff --git a/perfprofd/perfprofdcore.h b/perfprofd/perfprofdcore.h index 6ea24ab1..1fcbd4ce 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,10 @@ 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, +PROFILE_RESULT SerializeProtobuf(android::perfprofd::PerfprofdRecord* 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/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc index d6a8f219..8b0f640a 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> @@ -43,8 +44,7 @@ #include "perfprofdcore.h" #include "symbolizer.h" -#include "perf_profile.pb.h" -#include "google/protobuf/text_format.h" +#include "perfprofd_record.pb.h" // // Set to argv[0] on startup @@ -68,6 +68,16 @@ 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, @@ -182,7 +192,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 { @@ -341,7 +359,7 @@ 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) + android::perfprofd::PerfprofdRecord& encodedProfile) { struct stat statb; int perf_data_stat_result = stat(encoded_file_path(dest_dir, 0).c_str(), &statb); @@ -360,6 +378,7 @@ static void readEncodedProfile(const std::string& dest_dir, encodedProfile.ParseFromString(encoded); } +/* static std::string encodedLoadModuleToString(const wireless_android_play_playlog::LoadModule &lm) { std::stringstream ss; @@ -372,7 +391,9 @@ static std::string encodedLoadModuleToString(const wireless_android_play_playlog } return ss.str(); } +*/ +/* static std::string encodedModuleSamplesToString(const wireless_android_play_playlog::LoadModuleSamples &mod) { std::stringstream ss; @@ -391,6 +412,7 @@ static std::string encodedModuleSamplesToString(const wireless_android_play_play } return ss.str(); } +*/ #define RAW_RESULT(x) #x @@ -600,6 +622,187 @@ TEST_F(PerfProfdTest, ProfileCollectionAnnotations) EXPECT_FALSE(get_camera_active()); } +namespace { + +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()) { + } +}; + +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(); +} + +} + TEST_F(PerfProfdTest, BasicRunWithCannedPerf) { // @@ -625,60 +828,127 @@ 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; + android::perfprofd::PerfprofdRecord 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()); + ASSERT_TRUE(encodedProfile.has_perf_data()); + 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(); } - { 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()); + + { + 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; + } } - // 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()); + { + 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; + } } - { 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()); + + { + 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(PerfProfdTest, BasicRunWithCannedPerfWithSymbolizer) +TEST_F(PerfProfdTest, DISABLED_BasicRunWithCannedPerfWithSymbolizer) { // // Verify the portion of the daemon that reads and encodes @@ -713,59 +983,18 @@ 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; + android::perfprofd::PerfprofdRecord 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()); - } + ASSERT_TRUE(encodedProfile.has_perf_data()); + const quipper::PerfDataProto& perf_data = encodedProfile.perf_data(); - // 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()); - } + // Expect 21108 events. + EXPECT_EQ(21108, perf_data.events_size()) << CreateStats(perf_data); + + // TODO: Re-add symbolization. } TEST_F(PerfProfdTest, CallchainRunWithCannedPerf) @@ -790,59 +1019,57 @@ 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; + android::perfprofd::PerfprofdRecord 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()); - } + ASSERT_TRUE(encodedProfile.has_perf_data()); + const quipper::PerfDataProto& perf_data = encodedProfile.perf_data(); - // 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()); + // 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; + } + } + } } } @@ -876,12 +1103,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; + android::perfprofd::PerfprofdRecord encodedProfile; readEncodedProfile(dest_dir, "BasicRunWithLivePerf", 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( @@ -930,12 +1157,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; + android::perfprofd::PerfprofdRecord encodedProfile; readEncodedProfile(dest_dir, "BasicRunWithLivePerf", 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)); @@ -999,12 +1226,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; + android::perfprofd::PerfprofdRecord encodedProfile; readEncodedProfile(dest_dir, "CallChainRunWithLivePerf", 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 +1248,14 @@ 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()); } int main(int argc, char **argv) { |