diff --git a/BUILD.gn b/BUILD.gn index 6ccb95b0165d27f106e63165ca864528bd2b8943..0ebb347defaf4d7abe4838ca0f042ea6918aecfc 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -368,6 +368,13 @@ ohos_executable("hiperf_host") { part_name = "hiperf" } +ohos_prebuilt_etc("hiperf.cfg") { + source = "./config/hiperf.cfg" + relative_install_dir = "init" + subsystem_name = "developtools" + part_name = "hiperf" +} + ohos_source_set("hiperf_platform_host") { part_name = "hiperf" sources = [ "./src/hiperf_libreport.cpp" ] diff --git a/bundle.json b/bundle.json index 375e5ebe7653718b058a3f5b4e278a79da2f8380..e99309f843f7edd5114e7d8acd590bc93782e401 100644 --- a/bundle.json +++ b/bundle.json @@ -30,7 +30,8 @@ "build": { "sub_component": [ "//developtools/hiperf:hiperf_target", - "//developtools/hiperf:hiperf_target_all" + "//developtools/hiperf:hiperf_target_all", + "//developtools/hiperf:hiperf.cfg" ], "inner_kits": [ { diff --git a/config/hiperf.cfg b/config/hiperf.cfg new file mode 100644 index 0000000000000000000000000000000000000000..bfde068b33b903f3bf13882cf926d0b658257d23 --- /dev/null +++ b/config/hiperf.cfg @@ -0,0 +1,9 @@ +{ + "jobs" : [{ + "name" : "post-fs-data", + "cmds" : [ + "mkdir /data/log/hiperf/ 0775 shell root" + ] + } + ] +} diff --git a/demo/cpp/hiperf_demo.cpp b/demo/cpp/hiperf_demo.cpp index 8a2cf962551b94ed96cccba60ba94154eb8e239e..f9338cde0675d7e67dce4bf2be01e0a5ab5579df 100644 --- a/demo/cpp/hiperf_demo.cpp +++ b/demo/cpp/hiperf_demo.cpp @@ -64,7 +64,7 @@ int main() printf("demo start\n"); HiperfClient::RecordOption opt; const int timeout = 30; - opt.SetAppPackage("com.ohos.callui"); + opt.SetAppPackage("com.ohos.mms"); opt.SetTimeStopSec(timeout); if (myHiperf.Start(opt)) { printf("demo start successfully\n"); diff --git a/include/subcommand_record.h b/include/subcommand_record.h index 82d5eb8f611ef6bd2253103d6b4737cbdfa8fa42..2bb2d670ce75ab6acfbc4b57b06b4716d7538798 100644 --- a/include/subcommand_record.h +++ b/include/subcommand_record.h @@ -48,6 +48,9 @@ public: static constexpr int DEFAULT_MMAP_PAGES = 256; static constexpr int MIN_PERF_MMAP_PAGE = 2; static constexpr int MAX_PERF_MMAP_PAGE = 1024; + static constexpr int DEFAULT_CHECK_APP_MS = 10; + static constexpr int MIN_CHECK_APP_MS = 1; + static constexpr int MAX_CHECK_APP_MS = 200; static constexpr float MIN_STOP_SECONDS = 0.100; static constexpr float MAX_STOP_SECONDS = 10000.0; @@ -137,6 +140,9 @@ public: " --app \n" " Collect profile info for an OHOS app, the app must be debuggable.\n" " Record will exit if the process is not started within 10 seconds.\n" + " --chkms \n" + " Set the interval of querying the .\n" + " is in range [1-200], default is 10.\n" " --data-limit \n" " Stop recording after SIZE bytes of records. Default is unlimited.\n" " -o \n" @@ -184,6 +190,7 @@ private: std::vector symbolDir_ = {}; std::string outputFilename_ = "/data/local/tmp/perf.data"; std::string appPackage_ = {}; + int checkAppMs_ = DEFAULT_CHECK_APP_MS; std::string clockId_ = {}; std::string strLimit_ = {}; std::vector selectCpus_ = {}; diff --git a/include/utilities.h b/include/utilities.h index c608e3d6796b47cbda4b6f211eebda60804a47fa..bacdfb8d966f5112a4e5ca45a8dbe064b0a8fa88 100644 --- a/include/utilities.h +++ b/include/utilities.h @@ -71,6 +71,7 @@ constexpr const int THOUSANDS = 1000; constexpr const int HUNDREDS = 100; constexpr const int DEFAULT_STRING_BUF_SIZE = 4096; constexpr const int FIVE_THOUSANDS = 5000; +constexpr const int DATA_MAX_SIZE = 1001; #if !is_mingw #ifndef O_BINARY #define O_BINARY 0 diff --git a/proto/report_sample.proto b/proto/report_sample.proto index d5d7f6c9ca2a4358c9b27c0e28fffcca12d93882..fffd50a74a491d1fc04879ce15d5bc4d4c586bb1 100644 --- a/proto/report_sample.proto +++ b/proto/report_sample.proto @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Huawei Device Co., Ltd. +// Copyright (c) 2021-2022 Huawei Device Co., Ltd. // 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 @@ -41,6 +41,9 @@ message CallStackSample { // index of SymbolTableFile::symbol_name, base from 0 // -1 means not found optional int32 function_name_id = 3; + + // loaded function base vaddr + optional uint64 loaded_vaddr = 4; } repeated CallStackFrame callStackFrame = 3; diff --git a/script/hiperf_utils.py b/script/hiperf_utils.py index ed624f1aec231d03f2d7649965ffca32f70a8833..8864a3582eea12f2282e117f7a72bc50c9b7a96a 100644 --- a/script/hiperf_utils.py +++ b/script/hiperf_utils.py @@ -346,6 +346,7 @@ class LocalLibDownload: else: elf_struct.path = path + @classmethod def __get_need_architectures(self, device_arch): if device_arch == 'x86_64': return ['x86', 'x86_64'] diff --git a/script/recv_binary_cache.py b/script/recv_binary_cache.py index b1876631ffbfc40b1dd6414f7b210682296d4759..9f91800aef419532fb3da22c8b07184638f583a3 100644 --- a/script/recv_binary_cache.py +++ b/script/recv_binary_cache.py @@ -169,10 +169,10 @@ class GetLibFiles(object): if (self.hdc.run_hdc_cmd(['shell', 'cp', device_path, '/data/local/tmp']) and self.hdc.run_hdc_cmd(['file recv', - '/data/local/tmp/' + filename, + os.path.join('/data/local/tmp/', filename), host_path])): self.hdc.run_hdc_cmd(['shell', 'rm', - '/data/local/tmp/' + filename]) + os.path.join('/data/local/tmp/', filename)]) return True print('failed to pull %s from device' % device_path) return False diff --git a/script/test/test_utils.py b/script/test/test_utils.py index 1625f8e3ae423b4fe8fc12e992becbf4822656ed..6c12c1a141a5ef8fff70108735f00e02352cbf53 100644 --- a/script/test/test_utils.py +++ b/script/test/test_utils.py @@ -25,9 +25,6 @@ from hiperf_utils import executable_file_available from hiperf_utils import find_tool_path -SO = 'libhiperf_report.z.so' - - class TestUtils(unittest.TestCase): def setUp(self): @@ -42,7 +39,7 @@ class TestUtils(unittest.TestCase): self.assertEqual(result, True) def test_is_elf_file(self): - result = is_elf_file(SO) + result = is_elf_file('libhiperf_report.z.so') self.assertEqual(result, True) def test_remove(self): diff --git a/src/report_protobuf_file.cpp b/src/report_protobuf_file.cpp index 994a4d571325beea3e6cee82eeb2a044e69ee6b8..42aa0da21abef4d775604e60c7d365b764691a89 100644 --- a/src/report_protobuf_file.cpp +++ b/src/report_protobuf_file.cpp @@ -126,7 +126,7 @@ bool ReportProtobufFileWriter::ProcessSampleRecord( for (const CallFrame &frame : recordSample.callFrames_) { auto callframe = sample->add_callstackframe(); callframe->set_symbols_vaddr(frame.vaddrInFile_); - + callframe->set_loaded_vaddr(frame.ip_ - frame.offsetToVaddr_); for (auto fileIt = symbolsFiles.begin(); fileIt != symbolsFiles.end(); fileIt++) { if (fileIt->get()->filePath_ == frame.filePath_) { callframe->set_symbols_file_id(fileIt - symbolsFiles.begin()); diff --git a/src/subcommand_record.cpp b/src/subcommand_record.cpp index 14ccf7ad7706cc05c665394509e75152dd35d790..71792ee862eda4af7ae1a0a4cf2e51bae1ffc0ae 100644 --- a/src/subcommand_record.cpp +++ b/src/subcommand_record.cpp @@ -123,6 +123,7 @@ void SubCommandRecord::DumpOptions() const printf(" symbolDir_:\t%s\n", VectorToString(symbolDir_).c_str()); printf(" outputFilename_:\t%s\n", outputFilename_.c_str()); printf(" appPackage_:\t%s\n", appPackage_.c_str()); + printf(" checkAppMs_:\t%d\n", checkAppMs_); printf(" clockId_:\t%s\n", clockId_.c_str()); printf(" mmapPages_:\t%d\n", mmapPages_); printf(" dataLimit:\t%s\n", strLimit_.c_str()); @@ -183,6 +184,9 @@ bool SubCommandRecord::GetOptions(std::vector &args) if (!Option::GetOptionValue(args, "--app", appPackage_)) { return false; } + if (!Option::GetOptionValue(args, "--chkms", checkAppMs_)) { + return false; + } if (!Option::GetOptionValue(args, "--clockid", clockId_)) { return false; } @@ -326,6 +330,11 @@ bool SubCommandRecord::CheckOptions() MIN_CPU_PERCENT, MAX_CPU_PERCENT); return false; } + if (checkAppMs_ < MIN_CHECK_APP_MS || checkAppMs_ > MAX_CHECK_APP_MS) { + printf("Invalid --chkms value '%d', the milliseconds should be in %d~%d \n", checkAppMs_, + MIN_CHECK_APP_MS, MAX_CHECK_APP_MS); + return false; + } if (mmapPages_ < MIN_PERF_MMAP_PAGE || mmapPages_ > MAX_PERF_MMAP_PAGE || !PowerOfTwo(mmapPages_)) { printf("Invalid -m value '%d', value should be in %d~%d and must be a power of two \n", @@ -392,8 +401,7 @@ pid_t SubCommandRecord::GetAppPackagePid(const std::string &appPackage) } } } - static constexpr uint64_t waitAppSleepMs = 100; - std::this_thread::sleep_for(milliseconds(waitAppSleepMs)); + std::this_thread::sleep_for(milliseconds(checkAppMs_)); } while (steady_clock::now() < endTime); return res; @@ -450,7 +458,7 @@ bool SubCommandRecord::CheckTargetPids() return false; } } - if (appPackage_ != "") { + if (!appPackage_.empty()) { pid_t appPid = GetAppPackagePid(appPackage_); if (appPid <= 0) { printf("app %s not running\n", appPackage_.c_str()); diff --git a/src/symbols_file.cpp b/src/symbols_file.cpp index 5324f914ba8f876ab84cbe043a9da2343d871c33..dc2108f05b098d7624e24043859bb330c39e2b53 100644 --- a/src/symbols_file.cpp +++ b/src/symbols_file.cpp @@ -846,7 +846,7 @@ public: const auto eachFileStartTime = steady_clock::now(); #endif std::string kallsym; - if (!ReadFileToString("/proc/kallsyms", kallsym, KSYM_DEFAULT_SIZE)) { + if (!ReadFileToString("/proc/kallsyms", kallsym, KSYM_DEFAULT_SIZE) || kallsym.empty()) { HLOGW("/proc/kallsyms load failed."); return false; } diff --git a/src/utilities.cpp b/src/utilities.cpp index d30c77f38d0a51c1ef8d5b8962f36b5e32421eb3..5c48290947b75e8f4a7f85bca619ba291c339bf7 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -56,7 +56,9 @@ std::string CanonicalizeSpecPath(const char* src) } #else if (access(src, F_OK) == 0) { - if (realpath(src, resolvedPath) == nullptr) { + if (strstr(src, "/proc/") == src && strstr(src, "/data/storage") != nullptr) { // for sandbox + (void)strncpy_s(resolvedPath, sizeof(resolvedPath), src, strlen(src)); + } else if (realpath(src, resolvedPath) == nullptr) { fprintf(stderr, "Error: realpath %s failed", src); return ""; } diff --git a/src/virtual_thread.cpp b/src/virtual_thread.cpp index 1f74ee0088862964c6d309c3238f73592b2bb0a1..34847076c350f9350775e088b5418d90c4990958 100644 --- a/src/virtual_thread.cpp +++ b/src/virtual_thread.cpp @@ -320,6 +320,9 @@ void VirtualThread::ParseMap() // system/lib/libdl.so if (mapTokens.size() == MMAP_LINE_MAX_TOKEN) { memMapItem.name_ = mapTokens[MMAP_LINE_TOKEN_INDEX_NAME]; + if (memMapItem.name_.find("/data/storage") == 0 && access(memMapItem.name_.c_str(), F_OK) != 0) { + memMapItem.name_ = "/proc/" + std::to_string(pid_) + "/root" + memMapItem.name_; + } } if (!IsLegalFileName(memMapItem.name_)) { continue; diff --git a/test/fuzztest/commandline_fuzzer/CommandLine_fuzzer.cpp b/test/fuzztest/commandline_fuzzer/CommandLine_fuzzer.cpp index 178db7b61e289242806f5266fde5cea28e3f3c2d..315ee8e66739b96b40ba967e0f72d8f0252df97d 100644 --- a/test/fuzztest/commandline_fuzzer/CommandLine_fuzzer.cpp +++ b/test/fuzztest/commandline_fuzzer/CommandLine_fuzzer.cpp @@ -22,7 +22,11 @@ const static size_t MAX_TEST_ARGS_LEN = 4096; bool FuzzCommandLine(const char *subcommand, const uint8_t *data, size_t size) { - const char *argptr = reinterpret_cast(data); + char buf[DATA_MAX_SIZE] = { 0 }; + if (memcpy_s(buf, sizeof(buf), data, size) != 0) { + return false; + } + const char *argptr = reinterpret_cast(buf); const char *argsdata = argptr; std::vector argv; diff --git a/test/fuzztest/libreport_fuzzer/LibReport_fuzzer.cpp b/test/fuzztest/libreport_fuzzer/LibReport_fuzzer.cpp index 26079d9850b40b14c9cfc4d21dd6fd2964957823..008a2bdc266d1af5396e3e46a67203073d5bfe4d 100644 --- a/test/fuzztest/libreport_fuzzer/LibReport_fuzzer.cpp +++ b/test/fuzztest/libreport_fuzzer/LibReport_fuzzer.cpp @@ -18,7 +18,11 @@ namespace OHOS { bool FuzzLibReport(const uint8_t *data, size_t size) { - const char *dataPtr = reinterpret_cast(data); + char buf[DATA_MAX_SIZE] = { 0 }; + if (memcpy_s(buf, sizeof(buf), data, size) != 0) { + return false; + } + const char *dataPtr = reinterpret_cast(buf); EchoLoopBack(dataPtr); Report(dataPtr, dataPtr, dataPtr); diff --git a/test/unittest/common/native/hiperf_client_test.cpp b/test/unittest/common/native/hiperf_client_test.cpp index 22c390e4c4034699ef03f5ac76de0d363ae560d8..d95f7c6a723a7f30b1aaa7c2cb3d96ee773817dd 100644 --- a/test/unittest/common/native/hiperf_client_test.cpp +++ b/test/unittest/common/native/hiperf_client_test.cpp @@ -61,7 +61,7 @@ HWTEST_F(HiperfClientTest, NoPara, TestSize.Level1) StdoutRecord stdoutRecord; stdoutRecord.Start(); - HiperfClient::Client myHiperf; + HiperfClient::Client myHiperf("/data/log/hiperf/"); myHiperf.SetDebugMode(); ASSERT_TRUE(myHiperf.Start()); @@ -81,7 +81,7 @@ HWTEST_F(HiperfClientTest, OutDir, TestSize.Level1) StdoutRecord stdoutRecord; stdoutRecord.Start(); - HiperfClient::Client myHiperf("/data/local/tmp/"); + HiperfClient::Client myHiperf("/data/log/hiperf/"); myHiperf.SetDebugMode(); ASSERT_TRUE(myHiperf.Start()); @@ -100,7 +100,7 @@ void HiperfClientTest::TestCaseOption(const HiperfClient::RecordOption &opt) { StdoutRecord stdoutRecord; stdoutRecord.Start(); - HiperfClient::Client myHiperf; + HiperfClient::Client myHiperf("/data/log/hiperf/"); myHiperf.SetDebugMode(); ASSERT_TRUE(myHiperf.IsReady()); @@ -339,7 +339,7 @@ HWTEST_F(HiperfClientTest, SetDataLimit, TestSize.Level1) HWTEST_F(HiperfClientTest, SetAppPackage, TestSize.Level1) { HiperfClient::RecordOption opt; - opt.SetAppPackage("com.ohos.callui"); + opt.SetAppPackage("com.ohos.mms"); TestCaseOption(opt); } diff --git a/test/unittest/common/native/ring_buffer_test.cpp b/test/unittest/common/native/ring_buffer_test.cpp index 12867916a5e911c4d717c3760053d69e2098e79c..fbb813ecc2bc0b42e14861a9450bd7085ab4e301 100644 --- a/test/unittest/common/native/ring_buffer_test.cpp +++ b/test/unittest/common/native/ring_buffer_test.cpp @@ -60,7 +60,7 @@ void RingBufferTest::ReadBufferAndCheck(RingBuffer &buf) uint8_t *p = nullptr; while ((p = buf.GetReadData()) != nullptr) { ASSERT_EQ(memcpy_s(&readData, sizeof(perf_event_header), p, sizeof(perf_event_header)), 0); - ASSERT_EQ(checkSize, readData.size) + ASSERT_EQ(checkSize, readData.size) \ << " read data size " << readData.size << " expect data size " << checkSize; p += sizeof(perf_event_header); uint8_t data = static_cast(checkSize & U8MASK); diff --git a/test/unittest/common/native/subcommand_record_test.cpp b/test/unittest/common/native/subcommand_record_test.cpp index 0930cbacf01c1c208786845fa146f32176753433..8dc1b20cc8bbab9fb0e1c1ba9f06ebb9a241cb56 100644 --- a/test/unittest/common/native/subcommand_record_test.cpp +++ b/test/unittest/common/native/subcommand_record_test.cpp @@ -75,7 +75,7 @@ void SubCommandRecordTest::TestRecordCommand(const std::string &option, bool exp std::string cmdString = "record "; if (fixPid) { - cmdString += "--app com.ohos.callui "; + cmdString += "--app com.ohos.mms "; } cmdString += " " + option; printf("command : %s\n", cmdString.c_str()); @@ -96,7 +96,7 @@ void SubCommandRecordTest::TestRecordCommand(const std::string &option, bool exp // app package name HWTEST_F(SubCommandRecordTest, PackageName, TestSize.Level1) { - TestRecordCommand("-d 2 --app com.ohos.callui ", true, false); + TestRecordCommand("-d 2 --app com.ohos.mms ", true, false); } HWTEST_F(SubCommandRecordTest, PackageNameErr, TestSize.Level1) @@ -104,6 +104,61 @@ HWTEST_F(SubCommandRecordTest, PackageNameErr, TestSize.Level1) TestRecordCommand("-d 2 --app package_name ", false, false); } +// check app milliseconds +/** + * @tc.name: CheckAppMsMin + * @tc.desc: Test chkms minimum value + * @tc.type: FUNC + * @tc.require: issueI5R305 + */ +HWTEST_F(SubCommandRecordTest, CheckAppMsMin, TestSize.Level1) +{ + TestRecordCommand("-d 0.5 --chkms 1 "); +} + +/** + * @tc.name: CheckAppMsMinErr + * @tc.desc: Test chkms less than minimum value + * @tc.type: FUNC + * @tc.require: issueI5R305 + */ +HWTEST_F(SubCommandRecordTest, CheckAppMsMinErr, TestSize.Level1) +{ + TestRecordCommand("-d 0.5 --chkms 0 ", false); +} + +/** + * @tc.name: CheckAppMsMax + * @tc.desc: Test chkms maximum value + * @tc.type: FUNC + * @tc.require: issueI5R305 + */ +HWTEST_F(SubCommandRecordTest, CheckAppMsMax, TestSize.Level1) +{ + TestRecordCommand("-d 0.5 --chkms 200 "); +} + +/** + * @tc.name: CheckAppMsMaxErr + * @tc.desc: Test chkms more than maximum value + * @tc.type: FUNC + * @tc.require: issueI5R305 + */ +HWTEST_F(SubCommandRecordTest, CheckAppMsMaxErr, TestSize.Level1) +{ + TestRecordCommand("-d 0.5 --chkms 201 ", false); +} + +/** + * @tc.name: CheckAppMsInputErr + * @tc.desc: Test erro type of chkms + * @tc.type: FUNC + * @tc.require: issueI5R305 + */ +HWTEST_F(SubCommandRecordTest, CheckAppMsInputErr, TestSize.Level1) +{ + TestRecordCommand("-d 0.5 --chkms abc ", false); +} // stop seconds HWTEST_F(SubCommandRecordTest, StopSecondsMin, TestSize.Level1) { diff --git a/test/unittest/common/native/subcommand_stat_test.cpp b/test/unittest/common/native/subcommand_stat_test.cpp index 34e8b49d0d8a280eae28bdc64656566074802cdf..023e44f065c568e859791a05b9fab3dfd7ea37a9 100644 --- a/test/unittest/common/native/subcommand_stat_test.cpp +++ b/test/unittest/common/native/subcommand_stat_test.cpp @@ -1498,47 +1498,6 @@ HWTEST_F(SubCommandStatTest, TestOnSubCommand_verbose, TestSize.Level1) t1.join(); } -/** - * @tc.name: TestOnSubCommand_verbose1 - * @tc.desc: -p -t - * @tc.type: FUNC - */ -HWTEST_F(SubCommandStatTest, TestOnSubCommand_verbose1, TestSize.Level1) -{ - int tid1 = 0; - std::thread t1(SubCommandStatTest::TestCodeThread, std::ref(tid1)); - - printf("wait child thread run.\n"); - while (tid1 == 0) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - StdoutRecord stdoutRecord; - stdoutRecord.Start(); - const auto startTime = chrono::steady_clock::now(); - - std::string tidString = " -t "; - tidString += std::to_string(tid1); - - std::string cmdString = "stat"; - cmdString += tidString; - cmdString += " -c 0 -d 3"; - - EXPECT_EQ(Command::DispatchCommand(cmdString), true); - const auto costMs = std::chrono::duration_cast( - chrono::steady_clock::now() - startTime); - EXPECT_LE(costMs.count(), defaultRunTimeoutMs); - - std::string stringOut = stdoutRecord.Stop(); - if (HasFailure()) { - printf("output:\n%s", stringOut.c_str()); - } - - std::string expectStr = "time_enabled:"; - EXPECT_EQ(FindExpectStr(stringOut, expectStr), false); - t1.join(); -} - /** * @tc.name: TestOnSubCommand_cmd * @tc.desc: hiperf stat