• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define HILOG_TAG "Runtime"
16 
17 #include "virtual_runtime.h"
18 
19 #include <cinttypes>
20 #include <iostream>
21 #include <sstream>
22 #include <unistd.h>
23 #if !is_mingw
24 #include <sys/mman.h>
25 #endif
26 
27 #include "dfx_maps.h"
28 #include "register.h"
29 #include "symbols_file.h"
30 #include "utilities.h"
31 
32 using namespace std::chrono;
33 namespace OHOS {
34 namespace Developtools {
35 namespace NativeDaemon {
36 namespace {
37 std::atomic<uint64_t> callStackErrCnt = 0;
38 constexpr uint32_t CALL_STACK_ERROR_TIMES = 10;
39 constexpr uint32_t SYMBOL_FILES_SIZE = 512;
40 }
41 // we unable to access 'swapper' from /proc/0/
ClearMaps()42 void VirtualRuntime::ClearMaps()
43 {
44     processMaps_.clear();
45 }
46 
VirtualRuntime(const NativeHookConfig & hookConfig)47 VirtualRuntime::VirtualRuntime(const NativeHookConfig& hookConfig): hookConfig_(hookConfig)
48 {
49     symbolsFiles_.reserve(SYMBOL_FILES_SIZE);
50     if (!hookConfig_.offline_symbolization()) {
51         userSymbolCache_.reserve(USER_SYMBOL_CACHE_LIMIT);
52     }
53 }
54 
~VirtualRuntime()55 VirtualRuntime::~VirtualRuntime()
56 {
57     PROFILER_LOG_INFO(LOG_CORE, "%s:%d UserSymbolCache size = %zu", __func__, __LINE__, userSymbolCache_.size());
58     PROFILER_LOG_INFO(LOG_CORE, "Total number of call stack errors: %" PRIu64 "", callStackErrCnt.load());
59     ClearMaps();
60 }
61 
ReadThreadName(pid_t tid)62 std::string VirtualRuntime::ReadThreadName(pid_t tid)
63 {
64     std::string comm = ReadFileToString(StringPrintf("/proc/%d/comm", tid)).c_str();
65     comm.erase(std::remove(comm.begin(), comm.end(), '\r'), comm.end());
66     comm.erase(std::remove(comm.begin(), comm.end(), '\n'), comm.end());
67     return comm;
68 }
69 
UpdateThread(pid_t pid,pid_t tid,const std::string name)70 VirtualThread &VirtualRuntime::UpdateThread(pid_t pid, pid_t tid, const std::string name)
71 {
72 #ifdef HIPERF_DEBUG_TIME
73     const auto startTime = steady_clock::now();
74 #endif
75     VirtualThread &thread = GetThread(pid, tid);
76     if (!name.empty()) {
77         thread.name_ = name;
78     }
79 #ifdef HIPERF_DEBUG_TIME
80     updateThreadTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
81 #endif
82     return thread;
83 }
84 
CreateThread(pid_t pid,pid_t tid)85 VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid)
86 {
87     // make a new one
88     userSpaceThreadMap_.emplace(std::piecewise_construct, std::forward_as_tuple(tid),
89                                 std::forward_as_tuple(pid, tid, symbolsFiles_, this));
90     VirtualThread& thr = userSpaceThreadMap_.at(tid);
91     return thr;
92 }
93 
GetThread(pid_t pid,pid_t tid)94 VirtualThread &VirtualRuntime::GetThread(pid_t pid, pid_t tid)
95 {
96     HLOGV("find thread %u:%u", pid, tid);
97     auto it = userSpaceThreadMap_.find(tid);
98     if (it == userSpaceThreadMap_.end()) {
99         // we also need thread
100         VirtualThread& thr = CreateThread(pid, tid);
101         return thr;
102     } else {
103         VirtualThread& thr = it->second;
104         return thr;
105     }
106 }
107 
MakeCallFrame(DfxSymbol & symbol,CallFrame & callFrame)108 void VirtualRuntime::MakeCallFrame(DfxSymbol &symbol, CallFrame &callFrame)
109 {
110     callFrame.vaddrInFile_ = symbol.funcVaddr_;
111     callFrame.symbolName_ = symbol.symbolName_;
112     callFrame.symbolIndex_ = symbol.index_;
113     callFrame.filePath_ = symbol.module_.empty() ? symbol.comm_ : symbol.module_;
114     callFrame.symbolOffset_ = symbol.offset_;
115     callFrame.callFrameId_ = symbol.symbolId_;
116     callFrame.symbolNameId_ = symbol.symbolNameId_;
117     callFrame.filePathId_ = symbol.filePathId_;
118     if (symbol.funcVaddr_ != 0) {
119         callFrame.offset_ = symbol.funcVaddr_;
120     } else {
121         callFrame.offset_ = callFrame.ip_;
122     }
123 }
124 
GetSymbolName(pid_t pid,pid_t tid,std::vector<CallFrame> & callFrames,int offset,bool first)125 bool VirtualRuntime::GetSymbolName(pid_t pid, pid_t tid, std::vector<CallFrame>& callFrames, int offset, bool first)
126 {
127 #ifdef HIPERF_DEBUG_TIME
128     const auto startTime = steady_clock::now();
129 #endif
130     // Symbolic the Call Stack
131     HLOGV("total %zu frames", callFrames.size());
132 
133     perf_callchain_context perfCallchainContext = PERF_CONTEXT_MAX;
134     for (auto callFrameIt = callFrames.begin() + offset; callFrameIt != callFrames.end(); ++callFrameIt) {
135         auto &callFrame = callFrameIt.operator*();
136         if (callFrame.ip_ >= PERF_CONTEXT_MAX) {
137             // dont care, this is not issue.
138             HLOGV("%s", UpdatePerfContext(callFrame.ip_, perfCallchainContext).c_str());
139             continue;
140         }
141         auto symbol = GetSymbol(callFrame, pid, tid,
142             perfCallchainContext);
143         if (symbol.IsValid()) {
144             MakeCallFrame(symbol, callFrame);
145         } else {
146 #ifdef TRY_UNWIND_TWICE
147             if (first) {
148                 if (failedIPs_.find(callFrame.ip_) == failedIPs_.end()) {
149                     return false;
150                 } else {
151                     callFrames.erase(callFrameIt, callFrames.end());
152                     return true;
153                 }
154             } else {
155                 failedIPs_.insert(callFrame.ip_);
156                 callFrames.erase(callFrameIt, callFrames.end());
157                 return true;
158             }
159 #else
160             ++callStackErrCnt;
161             if (callStackErrCnt.load() % CALL_STACK_ERROR_TIMES == 0) {
162                 PROFILER_LOG_DEBUG(LOG_CORE, "number of call stack errors: %" PRIu64 "", callStackErrCnt.load());
163             }
164             callFrames.erase(callFrameIt, callFrames.end());
165             return true;
166 #endif
167         }
168         int index = callFrameIt - callFrames.begin();
169         HLOGV(" (%u)unwind symbol: %*s%s", index, index, "", callFrame.ToSymbolString().c_str());
170     }
171 #ifdef HIPERF_DEBUG_TIME
172     auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime);
173     if (usedTime.count() != 0) {
174         HLOGV("cost %0.3f ms to symbolic ", usedTime.count() / MS_DUARTION);
175     }
176     symbolicRecordTimes_ += usedTime;
177 #endif
178     return true;
179 }
180 
UpdateMaps(pid_t pid,pid_t tid)181 void VirtualRuntime::UpdateMaps(pid_t pid, pid_t tid)
182 {
183     auto &thread = UpdateThread(pid, tid);
184     if (thread.ParseMap(processMaps_, true)) {
185         PROFILER_LOG_DEBUG(LOG_CORE, "voluntarily update maps succeed");
186     } else {
187         PROFILER_LOG_DEBUG(LOG_CORE, "voluntarily update maps ignore");
188     }
189 }
190 
UnwindStack(std::vector<u64> & regs,const u8 * stack_addr,int stack_size,pid_t pid,pid_t tid,std::vector<CallFrame> & callFrames,size_t maxStackLevel)191 bool VirtualRuntime::UnwindStack(std::vector<u64>& regs,
192                                  const u8* stack_addr,
193                                  int stack_size,
194                                  pid_t pid,
195                                  pid_t tid,
196                                  std::vector<CallFrame>& callFrames,
197                                  size_t maxStackLevel)
198 {
199 #ifdef HIPERF_DEBUG_TIME
200     const auto startTime = steady_clock::now();
201 #endif
202     // if we have userstack ?
203     int offset = 0;
204     auto &thread = UpdateThread(pid, tid);
205     if (stack_size > 0) {
206         callstack_.UnwindCallStack(thread, &regs[0], regs.size(), stack_addr, stack_size, callFrames, maxStackLevel);
207         if (callFrames.size() <= FILTER_STACK_DEPTH) {
208             callFrames.clear();
209             return false;
210         }
211         // Do not symbolize the first two frame, cause the two frame implement by tool itself
212         offset = FILTER_STACK_DEPTH;
213 #ifdef HIPERF_DEBUG_TIME
214         unwindCallStackTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
215 #endif
216     }
217 #ifdef HIPERF_DEBUG_TIME
218     unwindFromRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
219 #endif
220     if (hookConfig_.offline_symbolization()) {
221         return true;
222     }
223     if (!GetSymbolName(pid, tid, callFrames, offset, true)) {
224 #ifdef TRY_UNWIND_TWICE
225         HLOGD("clear and unwind one more time");
226         if (!thread.ParseMap(processMaps_, true)) {
227             GetSymbolName(pid, tid, callFrames, offset, false);
228             return false;
229         }
230         if (stack_size > 0) {
231             callFrames.clear();
232             callstack_.UnwindCallStack(thread, &regs[0], regs.size(), stack_addr,
233                 stack_size, callFrames, maxStackLevel);
234         }
235         if (callFrames.size() <= FILTER_STACK_DEPTH) {
236             callFrames.clear();
237             return false;
238         }
239         if (!GetSymbolName(pid, tid, callFrames, offset, false)) {
240             return false;
241         }
242 #endif
243     }
244     return true;
245 }
246 
IsSymbolExist(const std::string & fileName)247 bool VirtualRuntime::IsSymbolExist(const std::string& fileName)
248 {
249     if (symbolsFiles_.find(fileName) != symbolsFiles_.end()) {
250         HLOGV("already have '%s'", fileName.c_str());
251         return true;
252     }
253     return false;
254 }
255 
DelSymbolFile(const std::string & fileName)256 void VirtualRuntime::DelSymbolFile(const std::string& fileName)
257 {
258     symbolsFiles_.erase(fileName);
259 }
260 
UpdateSymbols(std::string fileName)261 void VirtualRuntime::UpdateSymbols(std::string fileName)
262 {
263     HLOGD("try to find symbols for file: %s", fileName.c_str());
264 #ifdef HIPERF_DEBUG_TIME
265     const auto startTime = steady_clock::now();
266 #endif
267     if (symbolsFiles_.find(fileName) != symbolsFiles_.end()) {
268         HLOGV("already have '%s'", fileName.c_str());
269         return;
270     }
271 
272     // found it by name
273     auto symbolsFile = SymbolsFile::CreateSymbolsFile(fileName);
274 
275     // set sybol path If it exists
276     if (symbolsPaths_.size() > 0) {
277         symbolsFile->setSymbolsFilePath(symbolsPaths_); // also load from search path
278     }
279     if (loadSymboleWhenNeeded_) {
280         // load it when we need it
281         symbolsFiles_[symbolsFile->filePath_] = std::move(symbolsFile);
282     } else if (symbolsFile->LoadSymbols()) {
283         symbolsFiles_[symbolsFile->filePath_] = std::move(symbolsFile);
284     } else {
285         HLOGW("symbols file for '%s' not found.", fileName.c_str());
286     }
287 #ifdef HIPERF_DEBUG_TIME
288     auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime);
289     if (usedTime.count() != 0) {
290         HLOGV("cost %0.3f ms to load '%s'", usedTime.count() / MS_DUARTION, fileName.c_str());
291     }
292     updateSymbolsTimes_ += usedTime;
293 #endif
294 }
295 
UpdateHapSymbols(std::shared_ptr<DfxMap> map)296 bool VirtualRuntime::UpdateHapSymbols(std::shared_ptr<DfxMap> map)
297 {
298     auto symbolsFile = SymbolsFile::CreateSymbolsFile(map->name);
299     if (symbolsFile == nullptr) {
300         HLOGV("Failed to load CreateSymbolsFile for exec section in hap(%s)", map->name.c_str());
301         return false;
302     }
303     // update maps name if load debuginfo successfully
304     if (!symbolsFile->LoadDebugInfo(map)) {
305         HLOGV("Failed to load debuginfo for exec section in hap(%s)", map->name.c_str());
306         return false;
307     }
308 
309     if (!loadSymboleWhenNeeded_) {
310         symbolsFile->LoadSymbols(map);
311     }
312     symbolsFiles_[symbolsFile->filePath_] = (std::move(symbolsFile));
313     return true;
314 }
315 
GetKernelSymbol(uint64_t ip,const std::vector<std::shared_ptr<DfxMap>> & maps,const VirtualThread & thread)316 const DfxSymbol VirtualRuntime::GetKernelSymbol(uint64_t ip, const std::vector<std::shared_ptr<DfxMap>> &maps,
317                                                 const VirtualThread &thread)
318 {
319     DfxSymbol vaddrSymbol(ip, thread.name_);
320     for (auto &map : maps) {
321         if (ip > map->begin && ip < map->end) {
322             HLOGM("found addr 0x%" PRIx64 " in kernel map 0x%" PRIx64 " - 0x%" PRIx64 " from %s",
323                   ip, map->begin, map->end, map->name.c_str());
324             vaddrSymbol.module_ = map->name;
325             // found symbols by file name
326             auto search = symbolsFiles_.find(map->name);
327             if (search != symbolsFiles_.end()) {
328                 auto& symbolsFile = search->second;
329                 vaddrSymbol.fileVaddr_ =
330                         symbolsFile->GetVaddrInSymbols(ip, map->begin, map->offset);
331                 HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64
332                         " at '%s'",
333                         vaddrSymbol.fileVaddr_, ip, map->name.c_str());
334                 if (!symbolsFile->SymbolsLoaded()) {
335                     symbolsFile->LoadSymbols(map);
336                 }
337                 DfxSymbol foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_);
338                 foundSymbols.taskVaddr_ = ip;
339                 if (!foundSymbols.IsValid()) {
340                     HLOGW("addr 0x%" PRIx64 " vaddr  0x%" PRIx64 " NOT found in symbol file %s",
341                             ip, vaddrSymbol.fileVaddr_, map->name.c_str());
342                     return vaddrSymbol;
343                 } else {
344                     return foundSymbols;
345                 }
346             }
347             HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip,
348                   map->name.c_str());
349         } else {
350             HLOGM("addr 0x%" PRIx64 " not in map 0x%" PRIx64 " - 0x%" PRIx64 " from %s", ip,
351                   map->begin, map->end, map->name.c_str());
352         }
353     }
354     return vaddrSymbol;
355 }
356 
GetUserSymbol(uint64_t ip,const VirtualThread & thread)357 const DfxSymbol VirtualRuntime::GetUserSymbol(uint64_t ip, const VirtualThread &thread)
358 {
359     DfxSymbol vaddrSymbol(ip, thread.name_);
360     auto [curMaps, itemIndex] = FindMap(ip);
361     if (curMaps != nullptr) {
362         auto symbolsFilesIter = symbolsFiles_.find((curMaps->GetMaps())[itemIndex]->name);
363         if (symbolsFilesIter != symbolsFiles_.end()) {
364             auto symbolsFile = symbolsFilesIter->second.get();
365             symbolsFile->LoadDebugInfo((curMaps->GetMaps())[itemIndex]);
366             vaddrSymbol.fileVaddr_ =
367                 symbolsFile->GetVaddrInSymbols(ip, (curMaps->GetMaps())[itemIndex]->begin,
368                                                (curMaps->GetMaps())[itemIndex]->offset);
369             vaddrSymbol.module_ = (curMaps->GetMaps())[itemIndex]->name;
370             vaddrSymbol.symbolName_ = vaddrSymbol.GetName();
371             if (!symbolsFile->SymbolsLoaded()) {
372                 symbolsFile->LoadSymbols((curMaps->GetMaps())[itemIndex]);
373             }
374             DfxSymbol foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_);
375             foundSymbols.taskVaddr_ = ip;
376             foundSymbols.symbolName_ = foundSymbols.GetName();
377             if (!foundSymbols.IsValid()) {
378                 vaddrSymbol.filePathId_ = curMaps->filePathId_;
379                 return vaddrSymbol;
380             } else {
381                 foundSymbols.filePathId_ = curMaps->filePathId_;
382                 return foundSymbols;
383             }
384         } else {
385             HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip,
386                   curMaps->name_.c_str());
387         }
388     } else {
389         HLOGW("ReportVaddrMapMiss");
390 #ifdef HIPERF_DEBUG
391         thread.ReportVaddrMapMiss(ip);
392 #endif
393     }
394     return vaddrSymbol;
395 }
396 
GetSymbolCache(uint64_t ip,DfxSymbol & symbol,const VirtualThread & thread)397 bool VirtualRuntime::GetSymbolCache(uint64_t ip, DfxSymbol &symbol, const VirtualThread &thread)
398 {
399     auto [curMaps, itemIndex] = FindMap(ip);
400     if (curMaps != nullptr) {
401         auto foundSymbolIter = userSymbolCache_.find(std::pair(ip, curMaps->filePathId_));
402         if (foundSymbolIter != userSymbolCache_.end()) {
403             symbol = foundSymbolIter->second;
404             return true;
405         }
406     }
407     return false;
408 }
409 
UpdateSymbolCache(uint64_t ip,DfxSymbol & symbol,HashList<uint64_t,DfxSymbol> & cache)410 void VirtualRuntime::UpdateSymbolCache(uint64_t ip, DfxSymbol &symbol,
411     HashList<uint64_t, DfxSymbol> &cache)
412 {
413     // review change to LRU for memmory
414     HLOG_ASSERT_MESSAGE(cache.count(ip) == 0, "already have cached ip 0x%" PRIx64 "", ip);
415     cache[ip] = symbol;
416 }
417 
GetSymbol(CallFrame & callFrame,pid_t pid,pid_t tid,const perf_callchain_context & context)418 const DfxSymbol VirtualRuntime::GetSymbol(CallFrame& callFrame, pid_t pid, pid_t tid,
419                                           const perf_callchain_context &context)
420 {
421     HLOGM("try find tid %u ip 0x%" PRIx64 " in %zu symbolsFiles ", tid, callFrame.ip_, symbolsFiles_.size());
422     DfxSymbol symbol;
423     if (GetSymbolCache(callFrame.ip_, symbol, GetThread(pid, tid))) {
424         return symbol;
425     }
426     if (context == PERF_CONTEXT_USER or (context == PERF_CONTEXT_MAX and !symbol.IsValid())) {
427         // check userspace memmap
428         symbol = GetUserSymbol(callFrame.ip_, GetThread(pid, tid));
429         if (symbol.IsValid()) {
430             HLOGM("GetUserSymbol valid tid = %d ip = 0x%" PRIx64 "", tid, callFrame.ip_);
431             symbol.symbolId_ = userSymbolCache_.size() + 1;
432             if (hookConfig_.string_compressed()) {
433                 FillSymbolNameId(callFrame, symbol);
434                 FillFileSet(callFrame, symbol);
435             }
436             callFrame.needReport_ |= CALL_FRAME_REPORT;
437             userSymbolCache_[std::pair(callFrame.ip_, symbol.filePathId_)] = symbol;
438         } else {
439             HLOGM("GetUserSymbol invalid!");
440         }
441     }
442 
443     return symbol;
444 }
445 
SetSymbolsPaths(const std::vector<std::string> & symbolsPaths)446 bool VirtualRuntime::SetSymbolsPaths(const std::vector<std::string> &symbolsPaths)
447 {
448     std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE);
449     // we need check if the path is accessable
450     bool accessable = symbolsFile->setSymbolsFilePath(symbolsPaths);
451     if (accessable) {
452         symbolsPaths_ = symbolsPaths;
453     } else {
454         if (!symbolsPaths.empty()) {
455             printf("some symbols path unable access\n");
456         }
457     }
458     return accessable;
459 }
460 
FillMapsCache(std::string & currentFileName,std::shared_ptr<DfxMap> mapItem)461 void VirtualRuntime::FillMapsCache(std::string& currentFileName, std::shared_ptr<DfxMap> mapItem)
462 {
463     if (currentFileName.compare(mapItem->name) != 0) {
464         currentFileName = mapItem->name;
465         soBegin_ = mapItem->begin;
466         auto memMaps = std::make_shared<MemMaps>(++memMapFilePathId_);
467         memMaps->AddMap(mapItem, true);
468         mapsCache_[mapItem->begin] = memMaps;
469     } else {
470         if (auto curMapsIter = mapsCache_.find(soBegin_);
471                 curMapsIter != mapsCache_.end()) {
472             auto& curMaps = curMapsIter->second;
473             curMaps->soEnd_ = mapItem->end;
474             curMaps->AddMap(mapItem, false);
475             if (mapItem->prots & PROT_EXEC) {
476                 offlineMapAddr_.push_back(soBegin_);
477             }
478         }
479     }
480 }
481 
FillSymbolNameId(CallFrame & callFrame,DfxSymbol & symbol)482 inline void VirtualRuntime::FillSymbolNameId(CallFrame& callFrame, DfxSymbol& symbol)
483 {
484     auto itFuntion = functionMap_.find(std::string(symbol.symbolName_));
485     if (itFuntion != functionMap_.end()) {
486         symbol.symbolNameId_ = itFuntion->second;
487     } else {
488         symbol.symbolNameId_ = functionMap_.size() + 1;
489         functionMap_[std::string(symbol.symbolName_)] = symbol.symbolNameId_;
490         callFrame.needReport_ |= SYMBOL_NAME_ID_REPORT;
491     }
492 }
493 
FillFileSet(CallFrame & callFrame,const DfxSymbol & symbol)494 inline void VirtualRuntime::FillFileSet(CallFrame& callFrame, const DfxSymbol& symbol)
495 {
496     auto itFile = fileSet_.find(symbol.filePathId_);
497     if (itFile == fileSet_.end()) {
498         callFrame.needReport_ |= FILE_PATH_ID_REPORT;
499         fileSet_.insert(symbol.filePathId_);
500     }
501 }
502 
HandleMapInfo(uint64_t begin,uint64_t length,uint32_t flags,uint64_t offset,const std::string & filePath)503 void VirtualRuntime::HandleMapInfo(uint64_t begin, uint64_t length, uint32_t flags,
504                                    uint64_t offset, const std::string& filePath)
505 {
506     if (!(flags & MAP_FIXED) || mapsCache_.empty()) {
507         if (mapsCache_.find(begin) != mapsCache_.end()) {
508             return;
509         }
510         soBegin_ = begin;
511         std::shared_ptr<DfxMap> mapItem = std::make_shared<DfxMap>(begin, begin + length, offset, flags, filePath);
512         auto memMaps = std::make_shared<MemMaps>(++memMapFilePathId_);
513         memMaps->AddMap(mapItem, true);
514         mapsCache_[begin] = memMaps;
515         UpdateSymbols(filePath);
516     } else {
517         auto curMapsIter = mapsCache_.find(soBegin_);
518         if (curMapsIter != mapsCache_.end()) {
519             auto& curMaps = curMapsIter->second;
520             curMaps->soEnd_ = begin + length;
521             std::shared_ptr<DfxMap> mapItem = std::make_shared<DfxMap>(begin, begin + length,
522                                                                        offset, flags, curMaps->name_);
523             if (mapItem->name.find(".hap") != std::string::npos && (mapItem->prots & PROT_EXEC)) {
524                 mapItem->prevMap = curMaps->GetMaps().back();
525                 HLOGD("update hap(%s) symbols", mapItem->name.c_str());
526                 UpdateHapSymbols(mapItem);
527             }
528             curMaps->AddMap(mapItem, false);
529         }
530     }
531     if (flags & PROT_EXEC) {
532         offlineMapAddr_.push_back(soBegin_);
533     }
534 }
535 
RemoveMaps(uint64_t addr)536 void VirtualRuntime::RemoveMaps(uint64_t addr)
537 {
538     mapsCache_.erase(addr);
539 }
540 
FindMap(uint64_t addr)541 std::pair<std::shared_ptr<MemMaps>, uint32_t> VirtualRuntime::FindMap(uint64_t addr)
542 {
543     auto iter = mapsCache_.upper_bound(addr);
544     if (iter == mapsCache_.begin()) {
545         // have map 2 3 4 5
546         // find 1 , will return 2 (index 0, begin elem)
547         // this same as not found any thins
548         return {nullptr, 0};
549     }
550 
551     std::shared_ptr<MemMaps> curMaps = (--iter)->second;
552     if (addr >= curMaps->soBegin_ && addr < curMaps->soEnd_) {
553         std::vector<std::shared_ptr<DfxMap>> mapVec = curMaps->GetMaps();
554         for (auto curMapItem = mapVec.begin();
555             curMapItem != mapVec.end(); ++curMapItem) {
556             if (addr >= (*curMapItem)->begin && addr < (*curMapItem)->end) {
557                 return {curMaps, curMapItem - mapVec.begin()};
558             }
559         }
560     }
561     return {nullptr, 0};
562 }
563 } // namespace NativeDaemon
564 } // namespace Developtools
565 } // namespace OHOS