148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci#include "hiperf_libreport.h"
1648f512ceSopenharmony_ci
1748f512ceSopenharmony_ci#include "debug_logger.h"
1848f512ceSopenharmony_ci#include "dfx_elf.h"
1948f512ceSopenharmony_ci#include "perf_file_reader.h"
2048f512ceSopenharmony_ci#include "subcommand_dump.h"
2148f512ceSopenharmony_ci#include "subcommand_report.h"
2248f512ceSopenharmony_ci#include "utilities.h"
2348f512ceSopenharmony_ci
2448f512ceSopenharmony_ciusing namespace OHOS::Developtools::HiPerf;
2548f512ceSopenharmony_ciextern "C" {
2648f512ceSopenharmony_ci// this is a demo function
2748f512ceSopenharmony_ciconst char *EchoLoopBack(const char *echo)
2848f512ceSopenharmony_ci{
2948f512ceSopenharmony_ci    HLOGD("EchoLoopBack:%s\n", echo);
3048f512ceSopenharmony_ci    return echo;
3148f512ceSopenharmony_ci}
3248f512ceSopenharmony_ci
3348f512ceSopenharmony_ciint SetDebug(bool enable)
3448f512ceSopenharmony_ci{
3548f512ceSopenharmony_ci#ifdef HIPERF_DEBUG
3648f512ceSopenharmony_ci    if (enable) {
3748f512ceSopenharmony_ci        DebugLogger::GetInstance()->SetLogLevel(LEVEL_VERBOSE);
3848f512ceSopenharmony_ci        DebugLogger::GetInstance()->Disable(false);
3948f512ceSopenharmony_ci    } else {
4048f512ceSopenharmony_ci        DebugLogger::GetInstance()->Disable(true);
4148f512ceSopenharmony_ci    }
4248f512ceSopenharmony_ci#endif
4348f512ceSopenharmony_ci    return 0;
4448f512ceSopenharmony_ci}
4548f512ceSopenharmony_ci
4648f512ceSopenharmony_ciint Report(const char *perfFile, const char *reportFile, const char *reportOptions)
4748f512ceSopenharmony_ci{
4848f512ceSopenharmony_ci    std::unique_ptr<SubCommandReport> report = std::make_unique<SubCommandReport>();
4948f512ceSopenharmony_ci    HLOGD("report the file %s to %s\n", perfFile, reportFile);
5048f512ceSopenharmony_ci    if (perfFile != nullptr and reportFile != nullptr) {
5148f512ceSopenharmony_ci        std::vector<std::string> args;
5248f512ceSopenharmony_ci        args.emplace_back("-i");
5348f512ceSopenharmony_ci        args.emplace_back(perfFile);
5448f512ceSopenharmony_ci        args.emplace_back("-o");
5548f512ceSopenharmony_ci        args.emplace_back(reportFile);
5648f512ceSopenharmony_ci        if (reportOptions != nullptr) {
5748f512ceSopenharmony_ci            std::vector<std::string> options = StringSplit(reportOptions);
5848f512ceSopenharmony_ci            for (std::string &option : options) {
5948f512ceSopenharmony_ci                args.emplace_back(option);
6048f512ceSopenharmony_ci            }
6148f512ceSopenharmony_ci        }
6248f512ceSopenharmony_ci        if (report->ParseOption(args)) {
6348f512ceSopenharmony_ci            return report->OnSubCommand(args) ? 0 : -1;
6448f512ceSopenharmony_ci        }
6548f512ceSopenharmony_ci    } else {
6648f512ceSopenharmony_ci        printf("path is nullptr\n");
6748f512ceSopenharmony_ci    }
6848f512ceSopenharmony_ci    return -1;
6948f512ceSopenharmony_ci}
7048f512ceSopenharmony_ci
7148f512ceSopenharmony_ciint ReportJson(const char *perfFile, const char *reportFile)
7248f512ceSopenharmony_ci{
7348f512ceSopenharmony_ci    return ReportUnwindJson(perfFile, reportFile, nullptr);
7448f512ceSopenharmony_ci}
7548f512ceSopenharmony_ci
7648f512ceSopenharmony_ciint ReportUnwindJson(const char *perfFile, const char *reportFile, const char *symbolsDir)
7748f512ceSopenharmony_ci{
7848f512ceSopenharmony_ci    std::unique_ptr<SubCommandReport> report = std::make_unique<SubCommandReport>();
7948f512ceSopenharmony_ci    HLOGD("report the file %s to json file %s symbols from %s\n", perfFile, reportFile, symbolsDir);
8048f512ceSopenharmony_ci    if (perfFile != nullptr and reportFile != nullptr) {
8148f512ceSopenharmony_ci        std::vector<std::string> args;
8248f512ceSopenharmony_ci        args.emplace_back("-i");
8348f512ceSopenharmony_ci        args.emplace_back(perfFile);
8448f512ceSopenharmony_ci        args.emplace_back("-o");
8548f512ceSopenharmony_ci        args.emplace_back(reportFile);
8648f512ceSopenharmony_ci        args.emplace_back("--json");
8748f512ceSopenharmony_ci        if (symbolsDir != nullptr) {
8848f512ceSopenharmony_ci            args.emplace_back("--symbol-dir");
8948f512ceSopenharmony_ci            args.emplace_back(symbolsDir);
9048f512ceSopenharmony_ci        }
9148f512ceSopenharmony_ci        if (report->ParseOption(args)) {
9248f512ceSopenharmony_ci            return report->OnSubCommand(args) ? 0 : -1;
9348f512ceSopenharmony_ci        }
9448f512ceSopenharmony_ci    }
9548f512ceSopenharmony_ci    return -1;
9648f512ceSopenharmony_ci}
9748f512ceSopenharmony_ci
9848f512ceSopenharmony_cistatic std::unique_ptr<PerfFileReader> GetReader(const std::string &fileName)
9948f512ceSopenharmony_ci{
10048f512ceSopenharmony_ci    // check if file exist
10148f512ceSopenharmony_ci    if (access(fileName.c_str(), F_OK) != 0) {
10248f512ceSopenharmony_ci        // file not exists
10348f512ceSopenharmony_ci        printf("Can not access data file %s\n", fileName.c_str());
10448f512ceSopenharmony_ci        return nullptr;
10548f512ceSopenharmony_ci    }
10648f512ceSopenharmony_ci
10748f512ceSopenharmony_ci    auto reader = PerfFileReader::Instance(fileName);
10848f512ceSopenharmony_ci    if (reader == nullptr) {
10948f512ceSopenharmony_ci        printf("%s format not correct\n", fileName.c_str());
11048f512ceSopenharmony_ci        return nullptr;
11148f512ceSopenharmony_ci    } else {
11248f512ceSopenharmony_ci        return reader;
11348f512ceSopenharmony_ci    }
11448f512ceSopenharmony_ci}
11548f512ceSopenharmony_ci
11648f512ceSopenharmony_ciconst char *ReportGetSymbolFiles(const char *perfFile)
11748f512ceSopenharmony_ci{
11848f512ceSopenharmony_ci    HLOGD("report the file %s for symbols \n", perfFile);
11948f512ceSopenharmony_ci    static std::string result; // static for hold the c_str buffer
12048f512ceSopenharmony_ci    result.clear();
12148f512ceSopenharmony_ci    if (perfFile == nullptr) {
12248f512ceSopenharmony_ci        return result.c_str();
12348f512ceSopenharmony_ci    }
12448f512ceSopenharmony_ci
12548f512ceSopenharmony_ci    auto reader = GetReader(perfFile);
12648f512ceSopenharmony_ci    if (reader == nullptr) {
12748f512ceSopenharmony_ci        return result.c_str();
12848f512ceSopenharmony_ci    }
12948f512ceSopenharmony_ci    // found symbols in file
13048f512ceSopenharmony_ci    reader->ReadFeatureSection();
13148f512ceSopenharmony_ci    for (auto &featureSection : reader->GetFeatureSections()) {
13248f512ceSopenharmony_ci        if (featureSection->featureId_ == FEATURE::HIPERF_FILES_SYMBOL) {
13348f512ceSopenharmony_ci            const PerfFileSectionSymbolsFiles *sectionSymbolsFiles =
13448f512ceSopenharmony_ci                static_cast<const PerfFileSectionSymbolsFiles *>(featureSection.get());
13548f512ceSopenharmony_ci            auto it = sectionSymbolsFiles->symbolFileStructs_.begin();
13648f512ceSopenharmony_ci            while (it != sectionSymbolsFiles->symbolFileStructs_.end()) {
13748f512ceSopenharmony_ci                HLOGD("%s buildId:%s\n", it->filePath_.c_str(), it->buildId_.c_str());
13848f512ceSopenharmony_ci                result.append("[");
13948f512ceSopenharmony_ci                result.append(it->filePath_.c_str());
14048f512ceSopenharmony_ci                result.append(",");
14148f512ceSopenharmony_ci                result.append(it->buildId_.c_str());
14248f512ceSopenharmony_ci                result.append("]");
14348f512ceSopenharmony_ci                result.append(",");
14448f512ceSopenharmony_ci                it++;
14548f512ceSopenharmony_ci            }
14648f512ceSopenharmony_ci            result[result.size() >= 1 ? result.size() - 1 : 0] = '\0';
14748f512ceSopenharmony_ci        }
14848f512ceSopenharmony_ci    }
14948f512ceSopenharmony_ci    return result.c_str();
15048f512ceSopenharmony_ci}
15148f512ceSopenharmony_ci
15248f512ceSopenharmony_ciconst char *ReportGetBuildId(const char *elfPath)
15348f512ceSopenharmony_ci{
15448f512ceSopenharmony_ci    static std::string buildId; // static for hold the c_str buffer
15548f512ceSopenharmony_ci    buildId.clear();
15648f512ceSopenharmony_ci    std::string path(elfPath);
15748f512ceSopenharmony_ci    std::shared_ptr<DfxElf> elfFile = std::make_shared<DfxElf>(path);
15848f512ceSopenharmony_ci    buildId = elfFile->GetBuildId();
15948f512ceSopenharmony_ci    return buildId.c_str();
16048f512ceSopenharmony_ci}
16148f512ceSopenharmony_ci
16248f512ceSopenharmony_ciconst char *ReportGetElfArch(const char *elfPath)
16348f512ceSopenharmony_ci{
16448f512ceSopenharmony_ci    std::string path(elfPath);
16548f512ceSopenharmony_ci    std::shared_ptr<DfxElf> elfFile = std::make_shared<DfxElf>(path);
16648f512ceSopenharmony_ci    const char *machineName = "unknown";
16748f512ceSopenharmony_ci    switch (elfFile->GetArchType()) {
16848f512ceSopenharmony_ci        case ArchType::ARCH_ARM:
16948f512ceSopenharmony_ci            machineName = "arm";
17048f512ceSopenharmony_ci            break;
17148f512ceSopenharmony_ci        case ArchType::ARCH_ARM64:
17248f512ceSopenharmony_ci            machineName = "arm64";
17348f512ceSopenharmony_ci            break;
17448f512ceSopenharmony_ci        case ArchType::ARCH_X86:
17548f512ceSopenharmony_ci            machineName = "x86";
17648f512ceSopenharmony_ci            break;
17748f512ceSopenharmony_ci        case ArchType::ARCH_X86_64:
17848f512ceSopenharmony_ci            machineName = "x86_64";
17948f512ceSopenharmony_ci            break;
18048f512ceSopenharmony_ci        default:
18148f512ceSopenharmony_ci            break;
18248f512ceSopenharmony_ci    }
18348f512ceSopenharmony_ci    HLOGD("elf '%s' mache type is %s \n", elfPath, machineName);
18448f512ceSopenharmony_ci    return machineName;
18548f512ceSopenharmony_ci}
18648f512ceSopenharmony_ci
18748f512ceSopenharmony_ciint Dump(const char *fileName)
18848f512ceSopenharmony_ci{
18948f512ceSopenharmony_ci    std::unique_ptr<SubCommandDump> dump = std::make_unique<SubCommandDump>();
19048f512ceSopenharmony_ci    HLOGD("dump the file %s\n", fileName);
19148f512ceSopenharmony_ci    if (fileName != nullptr) {
19248f512ceSopenharmony_ci        std::vector<std::string> args;
19348f512ceSopenharmony_ci        args.emplace_back(fileName);
19448f512ceSopenharmony_ci        if (dump->ParseOption(args)) {
19548f512ceSopenharmony_ci            return dump->OnSubCommand(args) ? 0 : -1;
19648f512ceSopenharmony_ci        }
19748f512ceSopenharmony_ci    }
19848f512ceSopenharmony_ci    return -1;
19948f512ceSopenharmony_ci}
20048f512ceSopenharmony_ci
20148f512ceSopenharmony_ci} // extern "C"
202