* 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
*
* 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.
*/
#ifndef HIPERF_SYMBOLS_H
#define HIPERF_SYMBOLS_H
#include <cinttypes>
#include <iomanip>
#include <sstream>
#include <string>
#include "dfx_elf.h"
#include "dfx_symbol.h"
#include "perf_file_format.h"
#include "utilities.h"
#define HIPERF_ELF_READ_USE_MMAP
namespace OHOS {
namespace Developtools {
namespace HiPerf {
using namespace OHOS::HiviewDFX;
constexpr const char KERNEL_MMAP_NAME[] = "[kernel.kallsyms]";
constexpr const char KERNEL_MODULES_EXT_NAME[] = ".ko";
constexpr const char KERNEL_ELF_NAME[] = "vmlinux";
constexpr const char MMAP_VDSO_NAME[] = "[vdso]";
constexpr const char MMAP_ANONYMOUS_NAME[] = "[anon]";
constexpr const char MMAP_ANONYMOUS_OHOS_NAME[] = "//anon";
inline const std::string NOTE_GNU_BUILD_ID = ".note.gnu.build-id";
inline const std::string EH_FRAME_HR = ".eh_frame_hdr";
inline const std::string EH_FRAME = ".eh_frame";
inline const std::string ARM_EXIDX = ".ARM.exidx";
inline const std::string SYMTAB = ".symtab";
inline const std::string DYNSYM = ".dynsym";
inline const std::string GNU_DEBUGDATA = ".gnu_debugdata";
inline const std::string PLT = ".plt";
inline const std::string LINKER_PREFIX = "__dl_";
inline const std::string LINKER_PREFIX_NAME = "[linker]";
const int MAX_SYMBOLS_TYPE_NAME_LEN = 10;
const pid_t SYSMGR_PID = 2;
inline const std::string SYSMGR_NAME = "sysmgr";
inline const std::string SYSMGR_FILE_NAME = "sysmgr.elf";
inline const std::string DEVHOST_FILE_NAME = "devhost.elf";
inline const std::string DEVHOST_LINUX_FILE_NAME = "/lib/libdh-linux.so";
inline const std::string DEVHOST_LINUX_PREFIX = "/liblinux/";
class FileSymbol {
[[maybe_unused]] uint64_t vaddr_ = 0;
[[maybe_unused]] uint64_t len_ = 0;
std::string name_ = "";
std::string demangle_ = "";
FileSymbol(uint64_t vaddr, uint64_t len, const char *name, const char *demangle)
: vaddr_(vaddr), len_(len), name_(name), demangle_(demangle)
{
}
};
enum SymbolsFileType {
SYMBOL_KERNEL_FILE,
SYMBOL_KERNEL_MODULE_FILE,
SYMBOL_KERNEL_THREAD_FILE,
SYMBOL_ELF_FILE,
SYMBOL_JAVA_FILE,
SYMBOL_JS_FILE,
SYMBOL_HAP_FILE,
SYMBOL_CJ_FILE,
SYMBOL_JSVM_V8_FILE,
SYMBOL_ARKWEB_V8_FILE,
SYMBOL_UNKNOW_FILE,
};
class SymbolsFile {
public:
SymbolsFileType symbolFileType_;
std::string filePath_ = "";
int32_t id_ = -1;
static const uint64_t maxVaddr = std::numeric_limits<uint64_t>::max();
uint64_t textExecVaddr_ = maxVaddr;
uint64_t textExecVaddrFileOffset_ = 0;
uint64_t textExecVaddrRange_ = maxVaddr;
std::shared_ptr<DfxMap> map_ = nullptr;
SymbolsFile(SymbolsFileType symbolType, const std::string path)
: symbolFileType_(symbolType), filePath_(path) {};
virtual ~SymbolsFile();
virtual std::shared_ptr<DfxElf> GetElfFile()
{
return nullptr;
}
static std::unique_ptr<SymbolsFile> CreateSymbolsFile(
SymbolsFileType = SYMBOL_UNKNOW_FILE, const std::string symbolFilePath = EMPTY_STRING, pid_t pid = 0);
static std::unique_ptr<SymbolsFile> CreateSymbolsFile(const std::string &symbolFilePath, pid_t pid = 0);
bool setSymbolsFilePath(const std::string &symbolsSearchPath)
{
std::vector<std::string> symbolsSearchPaths = {symbolsSearchPath};
return setSymbolsFilePath(symbolsSearchPaths);
};
bool setSymbolsFilePath(const std::vector<std::string> &);
virtual bool IsAbc()
{
return false;
}
virtual bool IsJsvm()
{
return false;
}
virtual bool IsArkweb()
{
return false;
}
virtual void SetBoolValue(bool value);
virtual bool LoadSymbols([[maybe_unused]] std::shared_ptr<DfxMap> map = nullptr,
[[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
{
HLOGV("virtual dummy function called");
symbolsLoaded_ = true;
return false;
};
virtual bool LoadDebugInfo(std::shared_ptr<DfxMap> map = nullptr,
[[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
{
HLOGV("virtual dummy function called");
debugInfoLoaded_ = true;
return false;
};
virtual const std::unordered_map<uint64_t, ElfLoadInfo> GetPtLoads()
{
std::unordered_map<uint64_t, ElfLoadInfo> loadInfoMap;
return loadInfoMap;
}
const std::string GetBuildId() const;
virtual void EnableMiniDebugInfo() {}
const std::vector<DfxSymbol> &GetSymbols();
const std::vector<DfxSymbol *> &GetMatchedSymbols();
virtual uint64_t GetVaddrInSymbols(const uint64_t ip, const uint64_t mapStart, const uint64_t mapOffset) const;
uint64_t GetVaddrByLoadBase(uint64_t ip, uint64_t loadBase) const;
const DfxSymbol GetSymbolWithVaddr(uint64_t vaddrInFile);
virtual bool GetSectionInfo([[maybe_unused]] const std::string &name,
[[maybe_unused]] uint64_t §ionVaddr,
[[maybe_unused]] uint64_t §ionSize,
[[maybe_unused]] uint64_t §ionFileOffset) const
{
HLOGV("virtual dummy function called");
return false;
}
#ifndef __arm__
virtual bool GetHDRSectionInfo([[maybe_unused]] uint64_t &ehFrameHdrElfOffset,
[[maybe_unused]] uint64_t &fdeTableElfOffset,
[[maybe_unused]] uint64_t &fdeTableSize)
{
HLOGV("virtual dummy function called");
return false;
}
#endif
static std::unique_ptr<SymbolsFile> LoadSymbolsFromSaved(const SymbolFileStruct &);
void ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct);
bool SymbolsLoaded()
{
return symbolsLoaded_;
}
void AddSymbol(DfxSymbol symbol);
static bool onRecording_;
static bool needJsvm_;
std::vector<DfxSymbol> symbols_ {};
std::vector<DfxSymbol *> matchedSymbols_ {};
std::map<uint64_t, DfxSymbol> symbolsMap_;
static uint32_t offsetNum_;
virtual DfxSymbol GetSymbolWithPcAndMap(const uint64_t pc, std::shared_ptr<DfxMap> map)
{
return DfxSymbol();
}
void SetMapsInfo(std::shared_ptr<DfxMap> map)
{
map_ = map;
}
protected:
bool symbolsLoaded_ = false;
bool symbolsLoadResult_ = false;
bool debugInfoLoaded_ = false;
bool debugInfoLoadResult_ = false;
const std::string FindSymbolFile(const std::vector<std::string> &,
std::string symboleFilePath = EMPTY_STRING) const;
std::string SearchReadableFile(const std::vector<std::string> &searchPaths,
const std::string &filePath) const;
bool UpdateBuildIdIfMatch(const std::string &buildId);
std::string buildId_ = "";
std::vector<std::string> symbolsFileSearchPaths_;
std::vector<FileSymbol> fileSymbols_ {};
std::mutex mutex_;
void AdjustSymbols();
void SortMatchedSymbols();
bool CheckPathReadable(const std::string &path) const;
};
}
}
}
#endif