* Copyright (c) 2021-2023 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hiperf_libreport.h"
#include "debug_logger.h"
#include "elf_factory.h"
#include "perf_file_reader.h"
#include "subcommand_dump.h"
#include "subcommand_report.h"
#include "utilities.h"
using namespace OHOS::Developtools::HiPerf;
extern "C" {
const char *EchoLoopBack(const char *echo)
{
HLOGD("EchoLoopBack:%s\n", echo);
return echo;
}
int SetDebug(bool enable)
{
#ifdef HIPERF_DEBUG
if (enable) {
DebugLogger::GetInstance()->SetLogLevel(LEVEL_VERBOSE);
DebugLogger::GetInstance()->Disable(false);
} else {
DebugLogger::GetInstance()->Disable(true);
}
#endif
return 0;
}
int Report(const char *perfFile, const char *reportFile, const char *reportOptions)
{
std::unique_ptr<SubCommandReport> report = std::make_unique<SubCommandReport>();
HLOGD("report the file %s to %s\n", perfFile, reportFile);
if (perfFile != nullptr && reportFile != nullptr) {
std::vector<std::string> args;
args.emplace_back("-i");
args.emplace_back(perfFile);
args.emplace_back("-o");
args.emplace_back(reportFile);
if (reportOptions != nullptr) {
std::vector<std::string> options = StringSplit(reportOptions);
for (std::string &option : options) {
args.emplace_back(option);
}
}
if (report->ParseOption(args)) {
return report->OnSubCommand(args) == HiperfError::NO_ERR ? 0 : -1;
}
} else {
printf("path is nullptr\n");
}
return -1;
}
int ReportJson(const char *perfFile, const char *reportFile)
{
return ReportUnwindJson(perfFile, reportFile, nullptr);
}
int ReportUnwindJson(const char *perfFile, const char *reportFile, const char *symbolsDir)
{
std::unique_ptr<SubCommandReport> report = std::make_unique<SubCommandReport>();
HLOGD("report the file %s to json file %s symbols from %s\n", perfFile, reportFile, symbolsDir);
if (perfFile != nullptr && reportFile != nullptr) {
std::vector<std::string> args;
args.emplace_back("-i");
args.emplace_back(perfFile);
args.emplace_back("-o");
args.emplace_back(reportFile);
args.emplace_back("--json");
if (symbolsDir != nullptr) {
args.emplace_back("--symbol-dir");
args.emplace_back(symbolsDir);
}
if (report->ParseOption(args)) {
return report->OnSubCommand(args) == HiperfError::NO_ERR ? 0 : -1;
}
}
return -1;
}
static std::unique_ptr<PerfFileReader> GetReader(const std::string &fileName)
{
if (access(fileName.c_str(), F_OK) != 0) {
printf("Can not access data file %s\n", fileName.c_str());
return nullptr;
}
auto reader = PerfFileReader::Instance(fileName);
if (reader == nullptr) {
printf("%s format not correct\n", fileName.c_str());
return nullptr;
} else {
return reader;
}
}
const char *ReportGetSymbolFiles(const char *perfFile)
{
HLOGD("report the file %s for symbols \n", perfFile);
static std::string result;
result.clear();
if (perfFile == nullptr) {
HLOGW("perfFile is nullptr.");
return result.c_str();
}
auto reader = GetReader(perfFile);
if (reader == nullptr) {
HLOGW("reader is nullptr.");
return result.c_str();
}
reader->ReadFeatureSection();
for (auto &featureSection : reader->GetFeatureSections()) {
if (featureSection->featureId_ == FEATURE::HIPERF_FILES_SYMBOL) {
const PerfFileSectionSymbolsFiles *sectionSymbolsFiles =
static_cast<const PerfFileSectionSymbolsFiles *>(featureSection.get());
auto it = sectionSymbolsFiles->symbolFileStructs_.begin();
while (it != sectionSymbolsFiles->symbolFileStructs_.end()) {
HLOGD("%s buildId:%s\n", it->filePath_.c_str(), it->buildId_.c_str());
result.append("[");
result.append(it->filePath_.c_str());
result.append(",");
result.append(it->buildId_.c_str());
result.append("]");
result.append(",");
it++;
}
result[result.size() >= 1 ? result.size() - 1 : 0] = '\0';
}
}
return result.c_str();
}
const char *ReportGetBuildId(const char *elfPath)
{
static std::string buildId;
buildId.clear();
std::string path(elfPath);
RegularElfFactory elfFactory(path);
std::shared_ptr<DfxElf> elfFile = elfFactory.Create();
buildId = elfFile->GetBuildId();
return buildId.c_str();
}
const char *ReportGetElfArch(const char *elfPath)
{
RegularElfFactory elfFactory(elfPath);
std::shared_ptr<DfxElf> elfFile = elfFactory.Create();
const char *machineName = "unknown";
switch (elfFile->GetArchType()) {
case ArchType::ARCH_ARM:
machineName = "arm";
break;
case ArchType::ARCH_ARM64:
machineName = "arm64";
break;
case ArchType::ARCH_X86:
machineName = "x86";
break;
case ArchType::ARCH_X86_64:
machineName = "x86_64";
break;
default:
break;
}
HLOGD("elf '%s' mache type is %s \n", elfPath, machineName);
return machineName;
}
int Dump(const char *stringArgs)
{
std::unique_ptr<SubCommandDump> dump = std::make_unique<SubCommandDump>();
printf("dump the file, args: '%s'\n", stringArgs);
if (stringArgs != nullptr) {
auto args = StringSplit(stringArgs, " ");
if (dump->ParseOption(args)) {
return dump->OnSubCommand(args) == HiperfError::NO_ERR ? 0 : -1;
}
}
return -1;
}
}