summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2018-02-06 17:49:06 -0800
committerYabin Cui <yabinc@google.com>2018-02-08 12:04:23 -0800
commit46848c6da4eff8ea368c3972ee959b994e5dd55d (patch)
treed455ade9e0a3d75ba41b959b784b87e8e6ebc988
parent329daa8b39041fb2041a52aa35dd945b39e870f2 (diff)
downloadextras-46848c6da4eff8ea368c3972ee959b994e5dd55d.tar.gz
simpleperf: improve debug-unwind cmd.
In debug-unwind cmd: 1. Add --symfs option. 2. Add meta_info section when there isn't one. 3. Add file section when there isn't one. Rename unwinding_result_reporter.py to debug_unwind_reporter.py, and fix a small error in it. Bug: http://b/72556486 Test: run simpleperf_unit_test. Test: run debug_unwind_reporter.py manually. Change-Id: Ibc66b7bfdc91a17f6f1c2c0e84f4769d2bcaa1e7
-rw-r--r--simpleperf/cmd_debug_unwind.cpp71
-rw-r--r--simpleperf/cmd_debug_unwind_test.cpp24
-rw-r--r--simpleperf/scripts/debug_unwind_reporter.py (renamed from simpleperf/scripts/unwinding_result_reporter.py)12
3 files changed, 77 insertions, 30 deletions
diff --git a/simpleperf/cmd_debug_unwind.cpp b/simpleperf/cmd_debug_unwind.cpp
index d356355c..cd96a759 100644
--- a/simpleperf/cmd_debug_unwind.cpp
+++ b/simpleperf/cmd_debug_unwind.cpp
@@ -88,6 +88,7 @@ class DebugUnwindCommand : public Command {
"-i <file> The path of record file generated with \"-g --no-unwind\".\n"
" Default is perf.data.\n"
"-o <file> The path ot write new perf.data. Default is perf.data.debug.\n"
+"--symfs <dir> Look for files with symbols relative to this directory.\n"
"--time time Only unwind samples recorded at selected time.\n"
// clang-format on
),
@@ -159,6 +160,13 @@ bool DebugUnwindCommand::ParseOptions(const std::vector<std::string>& args) {
return false;
}
output_filename_ = args[i];
+ } else if (args[i] == "--symfs") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ if (!Dso::SetSymFsDir(args[i])) {
+ return false;
+ }
} else if (args[i] == "--time") {
if (!NextArgumentOrError(args, &i)) {
return false;
@@ -339,34 +347,49 @@ bool DebugUnwindCommand::JoinCallChains() {
}
bool DebugUnwindCommand::WriteFeatureSections() {
+ // Add debug_unwind info in META_INFO section, and add symbol info in FILE section.
const std::map<int, PerfFileFormat::SectionDesc>& features = reader_->FeatureSectionDescriptors();
- if (!writer_->BeginWriteFeatures(features.size())) {
+ size_t new_feature_count = features.size();
+ for (int feature : {PerfFileFormat::FEAT_FILE, PerfFileFormat::FEAT_META_INFO}) {
+ if (features.find(feature) == features.end()) {
+ new_feature_count++;
+ }
+ }
+ if (!writer_->BeginWriteFeatures(new_feature_count)) {
return false;
}
- for (auto& pair : features) {
- int feature = pair.first;
- if (feature == PerfFileFormat::FEAT_META_INFO) {
- std::unordered_map<std::string, std::string> info_map;
- if (!reader_->ReadMetaInfoFeature(&info_map)) {
- return false;
- }
- info_map["debug_unwind"] = "true";
- info_map["debug_unwind_mem_before"] = stat_.mem_before_unwinding.ToString();
- info_map["debug_unwind_mem_after"] = stat_.mem_after_unwinding.ToString();
- if (!writer_->WriteMetaInfoFeature(info_map)) {
- return false;
- }
- } else if (feature == PerfFileFormat::FEAT_FILE) {
- if (!writer_->WriteFileFeatures(thread_tree_.GetAllDsos())) {
- return false;
- }
- } else {
- std::vector<char> data;
- if (!reader_->ReadFeatureSection(feature, &data) || !writer_->WriteFeature(feature, data)) {
- return false;
- }
+
+ auto it = features.begin();
+ // Copy all feature sections except FEAT_FILE and FEAT_META_INFO, which require special handling.
+ while (it != features.end() && it->first < PerfFileFormat::FEAT_FILE) {
+ std::vector<char> data;
+ if (!reader_->ReadFeatureSection(it->first, &data) || !writer_->WriteFeature(it->first, data)) {
+ return false;
}
+ ++it;
+ }
+ // Write a new file section.
+ if (it != features.end() && it->first == PerfFileFormat::FEAT_FILE) {
+ ++it;
+ }
+ if (!writer_->WriteFileFeatures(thread_tree_.GetAllDsos())) {
+ return false;
+ }
+ // Write meta_info section.
+ std::unordered_map<std::string, std::string> info_map;
+ if (it != features.end() && it->first == PerfFileFormat::FEAT_META_INFO) {
+ if (!reader_->ReadMetaInfoFeature(&info_map)) {
+ return false;
+ }
+ ++it;
+ }
+ info_map["debug_unwind"] = "true";
+ info_map["debug_unwind_mem_before"] = stat_.mem_before_unwinding.ToString();
+ info_map["debug_unwind_mem_after"] = stat_.mem_after_unwinding.ToString();
+ if (!writer_->WriteMetaInfoFeature(info_map)) {
+ return false;
}
+ CHECK(it == features.end());
return writer_->EndWriteFeatures() && writer_->Close();
}
@@ -388,7 +411,7 @@ void DebugUnwindCommand::PrintStat() {
PrintIndented(1, "VmRSS: %s -> %s\n", stat_.mem_before_unwinding.vm_rss.c_str(),
stat_.mem_after_unwinding.vm_rss.c_str());
callchain_joiner_.DumpStat();
- printf("Please use unwinding_result_reporter.py to get a report in details.\n");
+ printf("Please use debug_unwind_reporter.py to get a report in details.\n");
}
void RegisterDebugUnwindCommand() {
diff --git a/simpleperf/cmd_debug_unwind_test.cpp b/simpleperf/cmd_debug_unwind_test.cpp
index bae45f6b..e6d44318 100644
--- a/simpleperf/cmd_debug_unwind_test.cpp
+++ b/simpleperf/cmd_debug_unwind_test.cpp
@@ -27,6 +27,7 @@
#include "command.h"
#include "get_test_data.h"
+#include "record_file.h"
#include "test_util.h"
#if defined(__aarch64__)
@@ -93,3 +94,26 @@ TEST(cmd_debug_unwind, smoke) {
GTEST_LOG_(INFO) << "This test does nothing on non-ARM64 devices.";
#endif
}
+
+TEST(cmd_debug_unwind, symfs_option) {
+ // TODO: Remove the arch limitation once using cross-platform unwinding in the new unwinder.
+#if defined(__aarch64__)
+ std::string input_data = GetTestData(NATIVELIB_IN_APK_PERF_DATA);
+ CaptureStdout capture;
+ TemporaryFile tmp_file;
+ ASSERT_TRUE(capture.Start());
+ ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "-o", tmp_file.path, "--symfs",
+ GetTestDataDir()}));
+ ASSERT_NE(capture.Finish().find("Unwinding sample count: 55"), std::string::npos);
+ std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file.path);
+ ASSERT_TRUE(reader);
+ const std::map<int, PerfFileFormat::SectionDesc>& features = reader->FeatureSectionDescriptors();
+ ASSERT_NE(features.find(PerfFileFormat::FEAT_FILE), features.end());
+ ASSERT_NE(features.find(PerfFileFormat::FEAT_META_INFO), features.end());
+ std::unordered_map<std::string, std::string> info_map;
+ ASSERT_TRUE(reader->ReadMetaInfoFeature(&info_map));
+ ASSERT_EQ(info_map["debug_unwind"], "true");
+#else
+ GTEST_LOG_(INFO) << "This test does nothing on non-ARM64 devices.";
+#endif
+}
diff --git a/simpleperf/scripts/unwinding_result_reporter.py b/simpleperf/scripts/debug_unwind_reporter.py
index 3eee00a6..56b51760 100644
--- a/simpleperf/scripts/unwinding_result_reporter.py
+++ b/simpleperf/scripts/debug_unwind_reporter.py
@@ -15,14 +15,14 @@
# limitations under the License.
#
-"""unwinding_result_reporter.py: report dwarf unwinding results generated by debug-unwind cmd.
- Below is an example using unwinding_result_reporter.py:
+"""debug_unwind_reporter.py: report dwarf unwinding results generated by debug-unwind cmd.
+ Below is an example using debug_unwind_reporter.py:
1. Record with "-g --no-unwind" option on device.
simpleperf record -g --no-unwind --app com.google.sample.tunnel --duration 10
2. Use debug-unwind cmd to unwind samples in perf.data on device.
simpleperf debug-unwind
3. Pull perf.data.debug on host, and report it with this script.
- python unwinding_result_reporter.py
+ python debug_unwind_reporter.py
It reports below items:
1. time used for offline dwarf unwinding for each sample.
@@ -380,8 +380,8 @@ def build_unwinding_result_report(args):
stdout=subprocess.PIPE)
(stdoutdata, _) = proc.communicate()
if 'debug_unwind = true' not in stdoutdata:
- log_exit("Can't parse unwinding result. Because %s is not generated by debug-unwind cmd."
- % record_file)
+ log_exit("Can't parse unwinding result. Because " +
+ "%s was not generated by the debug-unwind cmd." % args.record_file[0])
unwinding_report = UnwindingResultErrorReport(args.omit_callchains_fixed_by_joiner)
process_maps = unwinding_report.process_maps
lines = stdoutdata.split('\n')
@@ -454,7 +454,7 @@ def build_unwinding_result_report(args):
def main():
parser = argparse.ArgumentParser(
- description='report dwarf unwinding results generated by debug-unwind cmd')
+ description='Report dwarf unwinding results generated by the debug-unwind cmd.')
parser.add_argument('-i', '--record_file', nargs=1, default=['perf.data.debug'], help="""
Set profiling data to report. Default is perf.data.debug.""")
parser.add_argument('--omit-callchains-fixed-by-joiner', action='store_true', help="""