1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <gtest/gtest.h> 18 19 #include <unistd.h> 20 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include <android-base/file.h> 26 27 #include "command.h" 28 #include "get_test_data.h" 29 #include "record_file.h" 30 #include "test_util.h" 31 32 static std::unique_ptr<Command> DebugUnwindCmd() { 33 return CreateCommandInstance("debug-unwind"); 34 } 35 36 TEST(cmd_debug_unwind, smoke) { 37 std::string input_data = GetTestData(PERF_DATA_NO_UNWIND); 38 CaptureStdout capture; 39 TemporaryFile tmp_file; 40 ASSERT_TRUE(capture.Start()); 41 ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "-o", tmp_file.path})); 42 ASSERT_NE(capture.Finish().find("Unwinding sample count: 8"), std::string::npos); 43 44 ASSERT_TRUE(capture.Start()); 45 ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "-o", tmp_file.path, "--time", 46 "1516379654300997"})); 47 ASSERT_NE(capture.Finish().find("Unwinding sample count: 1"), std::string::npos); 48 } 49 50 TEST(cmd_debug_unwind, symfs_option) { 51 std::string input_data = GetTestData(NATIVELIB_IN_APK_PERF_DATA); 52 CaptureStdout capture; 53 TemporaryFile tmp_file; 54 ASSERT_TRUE(capture.Start()); 55 ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "-o", tmp_file.path, "--symfs", 56 GetTestDataDir()})); 57 ASSERT_NE(capture.Finish().find("Unwinding sample count: 55"), std::string::npos); 58 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file.path); 59 ASSERT_TRUE(reader); 60 const std::map<int, PerfFileFormat::SectionDesc>& features = reader->FeatureSectionDescriptors(); 61 ASSERT_NE(features.find(PerfFileFormat::FEAT_FILE), features.end()); 62 ASSERT_NE(features.find(PerfFileFormat::FEAT_META_INFO), features.end()); 63 auto meta_info = reader->GetMetaInfoFeature(); 64 ASSERT_EQ(meta_info["debug_unwind"], "true"); 65 } 66 67 TEST(cmd_debug_unwind, unwind_with_ip_zero_in_callchain) { 68 TemporaryFile tmp_file; 69 CaptureStdout capture; 70 ASSERT_TRUE(capture.Start()); 71 ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", GetTestData(PERF_DATA_WITH_IP_ZERO_IN_CALLCHAIN), 72 "-o", tmp_file.path})); 73 ASSERT_NE(capture.Finish().find("Unwinding sample count: 1"), std::string::npos); 74 } 75 76 TEST(cmd_debug_unwind, unwind_embedded_lib_in_apk) { 77 // Check if we can unwind through a native library embedded in an apk. In the profiling data 78 // file, there is a sample with ip address pointing to 79 // /data/app/simpleperf.demo.cpp_api/base.apk!/lib/arm64-v8a/libnative-lib.so. 80 // If unwound successfully, it can reach a function in libc.so. 81 TemporaryFile tmp_file; 82 ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", GetTestData("perf_unwind_embedded_lib_in_apk.data"), 83 "--symfs", GetTestDataDir(), "-o", tmp_file.path})); 84 CaptureStdout capture; 85 ASSERT_TRUE(capture.Start()); 86 ASSERT_TRUE(CreateCommandInstance("report-sample")->Run( 87 {"--show-callchain", "-i", tmp_file.path})); 88 std::string output = capture.Finish(); 89 ASSERT_NE(output.find("libnative-lib.so"), std::string::npos); 90 ASSERT_NE(output.find("libc.so"), std::string::npos); 91 } 92