!386 feat: hiperf support hap so features

Merge pull request !386 from hw_mzyan/master
This commit is contained in:
openharmony_ci 2023-11-26 10:23:29 +00:00 committed by Gitee
commit 56cdba760e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 116 additions and 37 deletions

View File

@ -119,14 +119,16 @@ public:
bool setSymbolsFilePath(const std::vector<std::string> &);
// load symbol from file
virtual bool LoadSymbols([[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
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;
};
// load debug info for unwind
virtual bool LoadDebugInfo([[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
virtual bool LoadDebugInfo(std::shared_ptr<DfxMap> map = nullptr,
[[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
{
HLOGV("virtual dummy function called");
debugInfoLoaded_ = true;
@ -196,6 +198,7 @@ protected:
std::vector<DfxSymbol> symbols_ {};
std::vector<DfxSymbol *> matchedSymbols_ {};
std::vector<FileSymbol> fileSymbols_ {};
std::mutex mutex_;
void AdjustSymbols();
void SortMatchedSymbols();

View File

@ -165,6 +165,9 @@ private:
void MakeCallFrame(DfxSymbol &symbol, CallFrame &callFrame);
// records
void UpdateSymbols(std::string filename);
// we don't know whether hap vma mapping is stand for a so
// thus we need try to parse it first
bool UpdateHapSymbols(std::shared_ptr<DfxMap> map);
void UpdateFromRecord(PerfRecordSample &recordSample);
void UpdateFromRecord(PerfRecordMmap &recordMmap);
void UpdateFromRecord(PerfRecordMmap2 &recordMmap2);

View File

@ -680,7 +680,7 @@ bool CallStack::DoUnwind2(const VirtualThread &thread, std::vector<CallFrame> &c
regs->SetRegsData(tempRegs);
#else
static std::shared_ptr<DfxRegs> regs = std::make_shared<DfxRegsArm64>();
regs->SetRegsData(static_cast<uintptr_t*>(regs_), regsNum_);
regs->SetRegsData((uintptr_t*)(regs_), regsNum_);
#endif
unwinder->SetRegs(regs);

View File

@ -196,7 +196,7 @@ bool SubCommandDump::DumpElfFile()
{
printf("dump elf: '%s'\n", elfFileName_.c_str());
auto elf = SymbolsFile::CreateSymbolsFile(elfFileName_);
if (!elf->LoadSymbols("")) {
if (!elf->LoadSymbols(nullptr, "")) {
printf("load elf failed.\n");
return false;
} else {

View File

@ -166,15 +166,15 @@ public:
{
}
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
std::string findPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath);
if (findPath.empty()) {
if (findPath.empty() && elfFile_ == nullptr) { // elf not compressed in hap has been initialized before
HLOGW("elf found failed (belong to %s)", filePath_.c_str());
return false;
}
if (LoadElfSymbols(findPath)) {
if (LoadElfSymbols(map, findPath)) {
return true;
} else {
HLOGW("elf open failed with '%s'", findPath.c_str());
@ -194,8 +194,9 @@ public:
}
protected:
bool LoadDebugInfo(const std::string &symbolFilePath) override
bool LoadDebugInfo(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
std::lock_guard<std::mutex> lock(mutex_);
if (debugInfoLoadResult_) {
return true; // it must have been loaded
} else if (debugInfoLoaded_) {
@ -208,14 +209,37 @@ protected:
HLOGW("elf found failed (belong to %s)", filePath_.c_str());
return false;
}
elfFile_ = std::make_shared<DfxElf>(elfPath);
HLOGD("loaded elf %s", elfPath.c_str());
if (elfFile_ == nullptr) {
if (StringEndsWith(elfPath, ".hap")) {
elfFile_ = DfxElf::CreateFromHap(elfPath, map->prevMap, map->offset);
HLOGD("try create elf from hap");
} else {
elfFile_ = std::make_shared<DfxElf>(elfPath);
}
}
if (elfFile_ == nullptr) {
HLOGD("Failed to create elf file for %s.", elfPath.c_str());
return false;
}
if (!elfFile_->IsValid()) {
HLOGD("parser elf file failed.");
return false;
}
HLOGD("loaded elf %s", elfPath.c_str());
// update path for so in hap
if (StringEndsWith(elfPath, ".hap")) {
filePath_ = elfPath + "!" + elfFile_->GetElfName();
HLOGD("update path for so in hap %s.", filePath_.c_str());
map->name = filePath_;
map->elf = elfFile_;
map->prevMap->name = filePath_;
map->prevMap->elf = elfFile_;
}
auto ptloads = elfFile_->GetPtLoads();
for (const auto &ptload : ptloads) {
if (textExecVaddr_ != std::min(textExecVaddr_, ptload.second.tableVaddr)) {
@ -366,12 +390,19 @@ private:
}
}
bool LoadElfSymbols(std::string elfPath)
bool LoadElfSymbols(std::shared_ptr<DfxMap> map, std::string elfPath)
{
#ifdef HIPERF_DEBUG_TIME
const auto startTime = steady_clock::now();
#endif
elfFile_ = std::make_shared<DfxElf>(elfPath);
if (elfFile_ == nullptr) {
if (StringEndsWith(elfPath, ".hap") && map != nullptr) {
elfFile_ = DfxElf::CreateFromHap(elfPath, map->prevMap, map->offset);
map->elf = elfFile_;
} else {
elfFile_ = std::make_shared<DfxElf>(elfPath);
}
}
HLOGD("loaded elf %s", elfPath.c_str());
if (enbleMiniDebugInfo_) {
@ -622,7 +653,7 @@ public:
return true;
}
}
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
HLOGV("KernelSymbols try read '%s' search paths size %zu, inDeviceRecord %d",
@ -657,7 +688,7 @@ public:
} // no search path
// try vmlinux
return ElfFileSymbols::LoadSymbols(KERNEL_ELF_NAME);
return ElfFileSymbols::LoadSymbols(nullptr, KERNEL_ELF_NAME);
}
uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override
{
@ -725,7 +756,8 @@ public:
return true;
}
}
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
HLOGV("KernelThreadSymbols try read '%s', inDeviceRecord %d",
@ -748,7 +780,7 @@ public:
} // no search path
// try elf
return ElfFileSymbols::LoadSymbols(filePath_);
return ElfFileSymbols::LoadSymbols(nullptr, filePath_);
}
~KernelThreadSymbols() override {}
};
@ -763,7 +795,7 @@ public:
}
~KernelModuleSymbols() override {};
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
if (module_ == filePath_ and onRecording_) {
@ -784,7 +816,7 @@ public:
LoadBuildId();
} else {
HLOGV("we have file path, load with %s", filePath_.c_str());
return ElfFileSymbols::LoadSymbols(filePath_);
return ElfFileSymbols::LoadSymbols(nullptr, filePath_);
}
return false;
}
@ -817,7 +849,7 @@ public:
{
symbolFileType_ = SYMBOL_KERNEL_FILE;
}
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
return false;
@ -839,7 +871,7 @@ public:
{
symbolFileType_ = SYMBOL_KERNEL_FILE;
}
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
return false;
@ -853,7 +885,7 @@ public:
: SymbolsFile(SYMBOL_UNKNOW_FILE, symbolFilePath)
{
}
bool LoadSymbols(const std::string &symbolFilePath) override
bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
{
symbolsLoaded_ = true;
return false;

View File

@ -112,14 +112,27 @@ VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid)
if (isHM_) {
thread.FixHMBundleMap();
}
std::shared_ptr<DfxMap> prevMap = nullptr;
for (auto &map : thread.GetMaps()) {
// so in hap is load before start perf record
// dynamic load library should be treat in the same way
bool updateNormalSymbol = true;
if (map->name.find(".hap") != std::string::npos &&
map->prots & PROT_EXEC) {
map->prevMap = prevMap;
updateNormalSymbol = !UpdateHapSymbols(map);
HLOGD("UpdateHapSymbols");
}
auto mmapRecord =
std::make_unique<PerfRecordMmap2>(false, thread.pid_, thread.tid_, map);
HLOGD("make PerfRecordMmap2 %d:%d:%s:%s(0x%" PRIx64 "-0x%" PRIx64 ")@%" PRIx64 " ",
thread.pid_, thread.tid_, thread.name_.c_str(), map->name.c_str(),
map->begin, map->end, map->offset);
recordCallBack_(std::move(mmapRecord));
UpdateSymbols(map->name);
if (updateNormalSymbol) {
UpdateSymbols(map->name);
}
prevMap = map;
}
}
HLOGV("thread created");
@ -131,6 +144,27 @@ VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid)
return thread;
}
bool VirtualRuntime::UpdateHapSymbols(std::shared_ptr<DfxMap> map)
{
// found it by name
auto symbolsFile = SymbolsFile::CreateSymbolsFile(map->name);
if (symbolsFile == nullptr) {
HLOGV("Failed to load CreateSymbolsFile for exec section in hap(%s)", map->name.c_str());
return false;
}
// update maps name if load debuginfo successfully
if (!symbolsFile->LoadDebugInfo(map)) {
HLOGV("Failed to load debuginfo for exec section in hap(%s)", map->name.c_str());
return false;
}
if (!loadSymboleWhenNeeded_) { // todo misspelling
symbolsFile->LoadSymbols(map);
}
symbolsFiles_.emplace_back(std::move(symbolsFile));
return true;
}
VirtualThread &VirtualRuntime::GetThread(pid_t pid, pid_t tid)
{
if (userSpaceThreadMap_.find(pid) == userSpaceThreadMap_.end()) {
@ -605,7 +639,7 @@ const DfxSymbol VirtualRuntime::GetKernelThreadSymbol(uint64_t ip, const Virtual
vaddrSymbol.fileVaddr_, ip, map->name.c_str());
if (!symbolsFile->SymbolsLoaded()) {
symbolsFile->LoadDebugInfo();
symbolsFile->LoadSymbols();
symbolsFile->LoadSymbols(map);
}
auto foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_);
foundSymbols.taskVaddr_ = ip;
@ -642,7 +676,7 @@ const DfxSymbol VirtualRuntime::GetUserSymbol(uint64_t ip, const VirtualThread &
HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64 " at '%s'",
vaddrSymbol.fileVaddr_, ip, map->name.c_str());
if (!symbolsFile->SymbolsLoaded()) {
symbolsFile->LoadSymbols();
symbolsFile->LoadSymbols(map);
}
auto foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_);
foundSymbols.taskVaddr_ = ip;

View File

@ -77,6 +77,9 @@ int64_t VirtualThread::FindMapIndexByAddr(uint64_t addr) const
}
}
if (addr >= memMaps_[memMapsIndexs_[left]]->begin && addr < memMaps_[memMapsIndexs_[left]]->end) {
if (left > 0) {
memMaps_[memMapsIndexs_[left]]->prevMap = memMaps_[memMapsIndexs_[left - 1]];
}
return static_cast<int64_t>(memMapsIndexs_[left]);
}
return illegal;
@ -111,6 +114,9 @@ std::shared_ptr<DfxMap> VirtualThread::FindMapByAddr(uint64_t addr) const
}
}
if (addr >= memMaps_[memMapsIndexs_[left]]->begin && addr < memMaps_[memMapsIndexs_[left]]->end) {
if (left > 0) {
memMaps_[memMapsIndexs_[left]]->prevMap = memMaps_[memMapsIndexs_[left - 1]];
}
return memMaps_[memMapsIndexs_[left]];
}
return nullptr;
@ -139,7 +145,7 @@ SymbolsFile *VirtualThread::FindSymbolsFileByMap(std::shared_ptr<DfxMap> inMap)
for (auto &symbolsFile : symbolsFiles_) {
if (symbolsFile->filePath_ == inMap->name) {
HLOGM("found symbol for map '%s'", inMap->name.c_str());
if (symbolsFile->LoadDebugInfo()) {
if (symbolsFile->LoadDebugInfo(inMap)) {
HLOGM("found symbol for map '%s'", inMap->name.c_str());
return symbolsFile.get();
}
@ -201,7 +207,8 @@ bool VirtualThread::ReadRoMemory(uint64_t vaddr, uint8_t *data, size_t size) con
map->elf = symFile->GetElfFile();
}
if (map->elf != nullptr) {
uint64_t foff = vaddr - map->begin + map->offset;
// default base offset is zero
uint64_t foff = vaddr - map->begin + map->offset - map->elf->GetBaseOffset();
if (map->elf->Read(foff, data, size)) {
return true;
} else {

View File

@ -49,7 +49,7 @@ public:
{
std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(symbolsFileType);
EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
return symbolsFile->LoadSymbols(path);
return symbolsFile->LoadSymbols(nullptr, path);
}
default_random_engine rnd_;
};
@ -222,7 +222,7 @@ bool TestLoadSymbols(SymbolsFileType symbolsFileType, const std::string &path)
{
std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(symbolsFileType);
EXPECT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
return symbolsFile->LoadSymbols(path);
return symbolsFile->LoadSymbols(nullptr, path);
}
/**
@ -302,20 +302,20 @@ HWTEST_F(SymbolsFileTest, LoadElfSymbols, TestSize.Level1)
EXPECT_EQ(symbolsElfLoader->LoadSymbols(), false);
ASSERT_EQ(symbolsElfLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
EXPECT_EQ(symbolsElfLoader->LoadSymbols(TEST_FILE_ELF), true);
EXPECT_EQ(symbolsElfLoader->LoadSymbols(nullptr, TEST_FILE_ELF), true);
if (HasFailure()) {
PrintSymbols(symbolsElfLoader->GetSymbols());
}
ASSERT_EQ(symbolsElfStrippedLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(TEST_FILE_ELF_STRIPPED), true);
EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(nullptr, TEST_FILE_ELF_STRIPPED), true);
if (HasFailure()) {
PrintSymbols(symbolsElfStrippedLoader->GetSymbols());
}
EXPECT_GT(symbolsElfLoader->GetSymbols().size(), symbolsElfStrippedLoader->GetSymbols().size());
ASSERT_EQ(symbolsElfStrippedLoader->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(TEST_FILE_ELF), true);
EXPECT_EQ(symbolsElfStrippedLoader->LoadSymbols(nullptr, TEST_FILE_ELF), true);
if (HasFailure()) {
PrintSymbols(symbolsElfStrippedLoader->GetSymbols());
}
@ -371,7 +371,7 @@ HWTEST_F(SymbolsFileTest, GetSymbolWithVaddr2, TestSize.Level1)
{
auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
ASSERT_EQ(elfSymbols->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
EXPECT_EQ(elfSymbols->LoadSymbols(TEST_FILE_ELF), true);
EXPECT_EQ(elfSymbols->LoadSymbols(nullptr, TEST_FILE_ELF), true);
ASSERT_EQ(elfSymbols->GetSymbols().empty(), false);
/*
@ -433,7 +433,7 @@ HWTEST_F(SymbolsFileTest, GetSymbolWithVaddrFullMatch, TestSize.Level1)
{
auto elfSymbols = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
ASSERT_EQ(elfSymbols->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
if (elfSymbols->LoadSymbols(TEST_SYMBOLS_FILE_ELF)) {
if (elfSymbols->LoadSymbols(nullptr, TEST_SYMBOLS_FILE_ELF)) {
ASSERT_EQ(elfSymbols->GetSymbols().empty(), false);
/*
nm -C --defined-only symbols_file_test_elf64
@ -656,19 +656,19 @@ HWTEST_F(SymbolsFileTest, GetBuildId, TestSize.Level1)
symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
// kernel elf
EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_VMLINUX), true);
EXPECT_EQ(symbolsFile->LoadSymbols(nullptr, TEST_FILE_VMLINUX), true);
EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
// stripped elf
EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_ELF), true);
EXPECT_EQ(symbolsFile->LoadSymbols(nullptr, TEST_FILE_ELF), true);
EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE);
ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DATA), true);
// stripped elf
EXPECT_EQ(symbolsFile->LoadSymbols(TEST_FILE_ELF_STRIPPED), true);
EXPECT_EQ(symbolsFile->LoadSymbols(nullptr, TEST_FILE_ELF_STRIPPED), true);
EXPECT_EQ(symbolsFile->GetBuildId().empty(), false);
}

View File

@ -349,7 +349,7 @@ HWTEST_F(VirtualRuntimeTest, UnwindFromRecord, TestSize.Level1)
auto &symbolsFile = runtime_->symbolsFiles_.emplace_back(
SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, TEST_DWARF_ELF));
ASSERT_EQ(symbolsFile->setSymbolsFilePath(PATH_RESOURCE_TEST_DWARF_DATA), true);
ASSERT_EQ(symbolsFile->LoadSymbols(TEST_DWARF_ELF), true);
ASSERT_EQ(symbolsFile->LoadSymbols(nullptr, TEST_DWARF_ELF), true);
symbolsFile->filePath_ = TEST_DWARF_ELF;
// thread