• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
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 
16 #include "unwinder.h"
17 
18 #include <dlfcn.h>
19 #include <link.h>
20 
21 #include "dfx_ark.h"
22 #include "dfx_define.h"
23 #include "dfx_errors.h"
24 #include "dfx_frame_formatter.h"
25 #include "dfx_instructions.h"
26 #include "dfx_log.h"
27 #include "dfx_regs_get.h"
28 #include "dfx_symbols.h"
29 #include "stack_util.h"
30 #include "string_printf.h"
31 #include "string_util.h"
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace {
36 #undef LOG_DOMAIN
37 #undef LOG_TAG
38 #define LOG_DOMAIN 0xD002D11
39 #define LOG_TAG "DfxUnwinder"
40 }
41 
Init()42 void Unwinder::Init()
43 {
44     Destroy();
45     memory_ = std::make_shared<DfxMemory>(acc_);
46 #if defined(__arm__)
47     armExidx_ = std::make_shared<ArmExidx>(memory_);
48 #endif
49     dwarfSection_ = std::make_shared<DwarfSection>(memory_);
50 
51     if (pid_ == UNWIND_TYPE_LOCAL) {
52         maps_ = DfxMaps::Create(getpid());
53     } else {
54         if (pid_ > 0) {
55             maps_ = DfxMaps::Create(pid_);
56         }
57     }
58 }
59 
Clear()60 void Unwinder::Clear()
61 {
62     isFpStep_ = false;
63     pcs_.clear();
64     frames_.clear();
65     if (memset_s(&lastErrorData_, sizeof(UnwindErrorData), 0, sizeof(UnwindErrorData)) != 0) {
66         LOGE("Failed to memset lastErrorData");
67     }
68 }
69 
Destroy()70 void Unwinder::Destroy()
71 {
72     Clear();
73     rsCache_.clear();
74 }
75 
GetStackRange(uintptr_t & stackBottom,uintptr_t & stackTop)76 bool Unwinder::GetStackRange(uintptr_t& stackBottom, uintptr_t& stackTop)
77 {
78     if (getpid() == gettid()) {
79         if (maps_ == nullptr || !maps_->GetStackRange(stackBottom, stackTop)) {
80             return false;
81         }
82     } else {
83         if (GetSelfStackRange(stackBottom, stackTop) != 0) {
84             return false;
85         }
86     }
87     return true;
88 }
89 
UnwindLocalWithContext(const ucontext_t & context,size_t maxFrameNum,size_t skipFrameNum)90 bool Unwinder::UnwindLocalWithContext(const ucontext_t& context, size_t maxFrameNum, size_t skipFrameNum)
91 {
92     regs_ = DfxRegs::CreateFromUcontext(context);
93     return UnwindLocal(true, maxFrameNum, skipFrameNum);
94 }
95 
UnwindLocal(bool withRegs,size_t maxFrameNum,size_t skipFrameNum)96 bool Unwinder::UnwindLocal(bool withRegs, size_t maxFrameNum, size_t skipFrameNum)
97 {
98     uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1);
99     if (!GetStackRange(stackBottom, stackTop)) {
100         LOGE("Get stack range error");
101         return false;
102     }
103     LOGU("stackBottom: %" PRIx64 ", stackTop: %" PRIx64 "", (uint64_t)stackBottom, (uint64_t)stackTop);
104 
105     if (!withRegs) {
106         regs_ = DfxRegs::Create();
107         auto regsData = regs_->RawData();
108         if (regsData == nullptr) {
109             LOGE("params is nullptr");
110             return false;
111         }
112         GetLocalRegs(regsData);
113     }
114 
115     UnwindContext context;
116     context.pid = UNWIND_TYPE_LOCAL;
117     context.regs = regs_;
118     context.stackCheck = false;
119     context.stackBottom = stackBottom;
120     context.stackTop = stackTop;
121     bool ret = Unwind(&context, maxFrameNum, skipFrameNum);
122     return ret;
123 }
124 
UnwindRemote(pid_t tid,bool withRegs,size_t maxFrameNum,size_t skipFrameNum)125 bool Unwinder::UnwindRemote(pid_t tid, bool withRegs, size_t maxFrameNum, size_t skipFrameNum)
126 {
127     if ((pid_ <= 0) || (tid < 0)) {
128         LOGE("params is nullptr, pid: %d", pid_);
129         return false;
130     }
131     if (tid == 0) {
132         tid = pid_;
133     }
134     LOGI("tid: %d", tid);
135     if (!withRegs) {
136         regs_ = DfxRegs::CreateRemoteRegs(tid);
137     }
138     if ((regs_ == nullptr)) {
139         LOGE("regs is nullptr");
140         return false;
141     }
142 
143     UnwindContext context;
144     context.pid = tid;
145     context.regs = regs_;
146     bool ret = Unwind(&context, maxFrameNum, skipFrameNum);
147     return ret;
148 }
149 
GetMapByPc(uintptr_t pc,void * ctx,std::shared_ptr<DfxMap> & map)150 bool Unwinder::GetMapByPc(uintptr_t pc, void *ctx, std::shared_ptr<DfxMap>& map)
151 {
152     if (ctx == nullptr) {
153         return false;
154     }
155     UnwindContext* uctx = reinterpret_cast<UnwindContext *>(ctx);
156     if (uctx->map != nullptr &&
157         (pc >= (uintptr_t)uctx->map->begin && pc < (uintptr_t)uctx->map->end)) {
158         LOGU("map had matched by ctx");
159         map = uctx->map;
160         return true;
161     }
162 
163     for (size_t i = 0; i < frames_.size(); ++i) {
164         if (frames_[i].map != nullptr &&
165             (pc >= (uintptr_t)frames_[i].map->begin && pc < (uintptr_t)frames_[i].map->end)) {
166             LOGU("map had matched by frames");
167             map = frames_[i].map;
168             uctx->map = map;
169             return true;
170         }
171     }
172 
173     if (!maps_->FindMapByAddr(pc, map) || (map == nullptr)) {
174         return false;
175     }
176     uctx->map = map;
177     return true;
178 }
179 
180 #if defined(ENABLE_MIXSTACK)
StepArkJsFrame(size_t & curIdx)181 bool Unwinder::StepArkJsFrame(size_t& curIdx)
182 {
183     uintptr_t pc = regs_->GetPc();
184     uintptr_t sp = regs_->GetSp();
185     uintptr_t fp = regs_->GetFp();
186     const size_t JSFRAME_MAX = 64;
187     JsFrame jsFrames[JSFRAME_MAX];
188     size_t size = JSFRAME_MAX;
189     if (memset_s(jsFrames, sizeof(JsFrame) * JSFRAME_MAX, 0, sizeof(JsFrame) * JSFRAME_MAX) != 0) {
190         LOGE("Failed to memset_s jsFrames.");
191         return false;
192     }
193     uintptr_t prevPc = pc;
194     uintptr_t prevSp = sp;
195     uintptr_t prevFp = fp;
196     LOGI("Ark input pc: %" PRIx64 ", fp: %" PRIx64 ", sp: %" PRIx64 ".", (uint64_t)pc, (uint64_t)fp, (uint64_t)sp);
197     int ret = DfxArk::GetArkNativeFrameInfo(pid_, pc, fp, sp, jsFrames, size);
198     LOGI("Ark output pc: %" PRIx64 ", fp: %" PRIx64 ", sp: %" PRIx64 ", js frame size: %zu.",
199         (uint64_t)pc, (uint64_t)fp, (uint64_t)sp, size);
200 
201     if (ret < 0 || (pc == prevPc && prevSp == sp && prevFp == fp)) {
202         return false;
203     }
204     for (size_t i = 0; i < size; ++i) {
205         DfxFrame frame;
206         frame.isJsFrame = true;
207         frame.index = (curIdx++);
208         frame.mapName = std::string(jsFrames[i].url);
209         frame.funcName = std::string(jsFrames[i].functionName);
210         frame.line = jsFrames[i].line;
211         frame.column = jsFrames[i].column;
212         frames_.emplace_back(frame);
213     }
214     regs_->SetPc(pc);
215     regs_->SetSp(sp);
216     regs_->SetFp(fp);
217     return true;
218 }
219 #endif
220 
Unwind(void * ctx,size_t maxFrameNum,size_t skipFrameNum)221 bool Unwinder::Unwind(void *ctx, size_t maxFrameNum, size_t skipFrameNum)
222 {
223     if ((ctx == nullptr) || (regs_ == nullptr) || (maps_ == nullptr)) {
224         LOGE("params is nullptr?");
225         return false;
226     }
227     Clear();
228 
229     bool needAdjustPc = false;
230     bool isFirstValidFrame = false;
231     size_t skipIndex = 0;
232     size_t curIndex = 0;
233     uintptr_t pc = 0, sp = 0, stepPc = 0;
234     std::shared_ptr<DfxMap> map = nullptr;
235     do {
236         if (skipIndex < skipFrameNum) {
237             skipIndex++;
238             continue;
239         }
240         if (curIndex >= maxFrameNum) {
241             lastErrorData_.SetCode(UNW_ERROR_MAX_FRAMES_EXCEEDED);
242             break;
243         }
244         SetLocalStackCheck(ctx, false);
245 
246         pc = regs_->GetPc();
247         sp = regs_->GetSp();
248         if (!GetMapByPc(pc, ctx, map)) {
249             if (isFirstValidFrame) {
250                 lastErrorData_.SetAddrAndCode(pc, UNW_ERROR_INVALID_MAP);
251                 break;
252             }
253 
254             if (enableLrFallback_ && regs_->SetPcFromReturnAddress(memory_)) {
255                 LOGW("Failed to get map, lr fallback");
256                 AddFrame(pc, sp, map, curIndex);
257                 continue;
258             }
259 
260             uintptr_t fp = regs_->GetFp();
261             if (!FpStep(fp, pc, ctx)) {
262                 break;
263             }
264             LOGW("Failed to get map, fp fallback");
265             isFirstValidFrame = true;
266             continue;
267         }
268         isFirstValidFrame = true;
269 
270         if (needAdjustPc) {
271             DoPcAdjust(pc);
272         }
273         needAdjustPc = true;
274 
275         AddFrame(pc, sp, map, curIndex);
276 #if defined(ENABLE_MIXSTACK)
277         if (map->IsArkExecutable()) {
278             if (!StepArkJsFrame(curIndex)) {
279                 LOGE("Failed to step ark Js frames, curIndex: %zu", curIndex);
280                 break;
281             }
282             continue;
283         }
284 #endif
285 
286         stepPc = pc;
287         if (!Step(stepPc, sp, ctx)) {
288             break;
289         }
290     } while (true);
291     LOGU("Last error code: %d, addr: %p", (int)GetLastErrorCode(), reinterpret_cast<void *>(GetLastErrorAddr()));
292     return (curIndex > 0);
293 }
294 
UnwindByFp(void * ctx,size_t maxFrameNum,size_t skipFrameNum)295 bool Unwinder::UnwindByFp(void *ctx, size_t maxFrameNum, size_t skipFrameNum)
296 {
297     if (regs_ == nullptr) {
298         LOGE("params is nullptr?");
299         return false;
300     }
301     pcs_.clear();
302 
303     size_t idx = 0;
304     size_t curIdx = 0;
305     uintptr_t pc = 0;
306     uintptr_t fp = 0;
307     do {
308         if (idx < skipFrameNum) {
309             idx++;
310             continue;
311         }
312 
313         if (curIdx >= maxFrameNum) {
314             lastErrorData_.SetCode(UNW_ERROR_MAX_FRAMES_EXCEEDED);
315             break;
316         }
317 
318         pc = regs_->GetPc();
319         fp = regs_->GetFp();
320         pcs_.emplace_back(pc);
321 
322         if (!FpStep(fp, pc, ctx) || (pc == 0)) {
323             break;
324         }
325         curIdx++;
326     } while (true);
327     return (curIdx > 0);
328 }
329 
Step(uintptr_t & pc,uintptr_t & sp,void * ctx)330 bool Unwinder::Step(uintptr_t& pc, uintptr_t& sp, void *ctx)
331 {
332     if (regs_ == nullptr || memory_ == nullptr) {
333         LOGE("params is nullptr");
334         return false;
335     }
336     LOGU("++++++pc: %" PRIx64 ", sp: %" PRIx64 "", (uint64_t)pc, (uint64_t)sp);
337     SetLocalStackCheck(ctx, false);
338     memory_->SetCtx(ctx);
339     bool isSignalFrame = false;
340     uintptr_t prevPc = pc;
341     uintptr_t prevSp = sp;
342 
343     std::shared_ptr<RegLocState> rs = nullptr;
344     bool ret = false;
345     do {
346         if (isFpStep_) {
347             break;
348         }
349 
350         if (enableCache_) {
351             // 1. find cache rs
352             auto iter = rsCache_.find(pc);
353             if (iter != rsCache_.end()) {
354                 if (pid_ != UNWIND_TYPE_CUSTOMIZE) {
355                     LOGI("Find rs cache, pc: %p", reinterpret_cast<void *>(pc));
356                 }
357                 rs = iter->second;
358                 ret = true;
359                 break;
360             }
361         }
362 
363         // Check if this is a signal frame.
364         if (regs_->StepIfSignalFrame(pc, memory_)) {
365             isSignalFrame = true;
366             break;
367         }
368 
369         // 2. find unwind table and entry
370         UnwindTableInfo uti;
371         MAYBE_UNUSED int utiRet = acc_->FindUnwindTable(pc, uti, ctx);
372         if (utiRet != UNW_ERROR_NONE) {
373             lastErrorData_.SetAddrAndCode(pc, UNW_ERROR_NO_UNWIND_INFO);
374             LOGU("Failed to find unwind table ret: %d", utiRet);
375             break;
376         }
377 
378         // 3. parse instructions and get cache rs
379         struct UnwindEntryInfo uei;
380         rs = std::make_shared<RegLocState>();
381 #if defined(__arm__)
382         if (!ret && uti.format == UNW_INFO_FORMAT_ARM_EXIDX) {
383             if (!armExidx_->SearchEntry(pc, uti, uei)) {
384                 lastErrorData_.SetAddrAndCode(armExidx_->GetLastErrorAddr(), armExidx_->GetLastErrorCode());
385                 LOGE("Failed to search unwind entry?");
386                 break;
387             }
388             if (!armExidx_->Step((uintptr_t)uei.unwindInfo, rs)) {
389                 lastErrorData_.SetAddrAndCode(armExidx_->GetLastErrorAddr(), armExidx_->GetLastErrorCode());
390                 LOGU("Step exidx section error?");
391             } else {
392                 ret = true;
393             }
394         }
395 #endif
396         if (!ret && uti.format == UNW_INFO_FORMAT_REMOTE_TABLE) {
397             if ((uti.isLinear == false && !dwarfSection_->SearchEntry(pc, uti, uei)) ||
398                 (uti.isLinear == true && !dwarfSection_->LinearSearchEntry(pc, uti, uei))) {
399                 lastErrorData_.SetAddrAndCode(dwarfSection_->GetLastErrorAddr(), dwarfSection_->GetLastErrorCode());
400                 LOGU("Failed to search unwind entry?");
401                 break;
402             }
403             memory_->SetDataOffset(uti.segbase);
404             if (!dwarfSection_->Step((uintptr_t)uei.unwindInfo, regs_, rs)) {
405                 lastErrorData_.SetAddrAndCode(dwarfSection_->GetLastErrorAddr(), dwarfSection_->GetLastErrorCode());
406                 LOGU("Step dwarf section error?");
407             } else {
408                 ret = true;
409             }
410         }
411 
412         if (ret && enableCache_) {
413             // 4. update rs cache
414             rsCache_.emplace(pc, rs);
415             break;
416         }
417     } while (false);
418 
419     if (!isSignalFrame) {
420         // 5. update regs and regs state
421         if (ret) {
422             SetLocalStackCheck(ctx, true);
423             ret = Apply(regs_, rs);
424         }
425     } else {
426         LOGW("Step signal frame");
427         ret = true;
428     }
429 
430 #if defined(__aarch64__)
431     if (!ret && enableFpFallback_) {
432         uintptr_t fp = regs_->GetFp();
433         ret = FpStep(fp, pc, ctx);
434     }
435 #endif
436 
437     pc = regs_->GetPc();
438     sp = regs_->GetSp();
439     if (ret && (prevPc == pc) && (prevSp == sp)) {
440         if (pid_ >= 0) {
441             MAYBE_UNUSED UnwindContext* uctx = reinterpret_cast<UnwindContext *>(ctx);
442             LOGU("pc and sp is same, tid: %d", uctx->pid);
443         } else {
444             LOGU("pc and sp is same");
445         }
446         lastErrorData_.SetAddrAndCode(pc, UNW_ERROR_REPEATED_FRAME);
447         ret = false;
448     }
449 
450     uintptr_t tmp = 0;
451     if (ret && ((pc == 0) || (!memory_->ReadUptr(sp, &tmp, false)))) {
452         LOGU("------pc: %" PRIx64 ", sp: %" PRIx64 " error?", (uint64_t)pc, (uint64_t)sp);
453         ret = false;
454     } else {
455         LOGU("------pc: %" PRIx64 ", sp: %" PRIx64 "", (uint64_t)pc, (uint64_t)sp);
456     }
457     return ret;
458 }
459 
FpStep(uintptr_t & fp,uintptr_t & pc,void * ctx)460 bool Unwinder::FpStep(uintptr_t& fp, uintptr_t& pc, void *ctx)
461 {
462 #if defined(__aarch64__)
463     LOGU("++++++fp: %lx, pc: %lx", (uint64_t)fp, (uint64_t)pc);
464     if (!isFpStep_) {
465         LOGI("First enter fp step, pc: %p", reinterpret_cast<void *>(pc));
466         isFpStep_ = true;
467     }
468     SetLocalStackCheck(ctx, true);
469     memory_->SetCtx(ctx);
470 
471     uintptr_t prevFp = fp;
472     uintptr_t ptr = fp;
473     if (memory_->ReadUptr(ptr, &fp, true) &&
474         memory_->ReadUptr(ptr, &pc, false)) {
475         if (enableFpCheckMapExec_) {
476             std::shared_ptr<DfxMap> map = nullptr;
477             if (!GetMapByPc(pc, ctx, map) || !map->IsMapExec()) {
478                 return false;
479             }
480         }
481         regs_->SetReg(REG_FP, &fp);
482         regs_->SetReg(REG_PC, &pc);
483         regs_->SetReg(REG_SP, &prevFp);
484         if (pid_ == UNWIND_TYPE_CUSTOMIZE) {
485             regs_->SetPc(StripPac(pc, pacMask_));
486         }
487         LOGU("------fp: %lx, pc: %lx", (uint64_t)fp, (uint64_t)pc);
488         return true;
489     }
490 #endif
491     return false;
492 }
493 
Apply(std::shared_ptr<DfxRegs> regs,std::shared_ptr<RegLocState> rs)494 bool Unwinder::Apply(std::shared_ptr<DfxRegs> regs, std::shared_ptr<RegLocState> rs)
495 {
496     bool ret = false;
497     if (rs == nullptr || regs == nullptr) {
498         return false;
499     }
500     ret = DfxInstructions::Apply(memory_, *(regs.get()), *(rs.get()));
501     if (!ret) {
502         LOGE("Failed to apply rs");
503     }
504 #if defined(__arm__) || defined(__aarch64__)
505     if (!rs->isPcSet) {
506         regs_->SetReg(REG_PC, regs->GetReg(REG_LR));
507     }
508 #endif
509 
510     if (rs->pseudoReg != 0) {
511         regs->SetPc(StripPac(regs_->GetPc(), pacMask_));
512     }
513     return ret;
514 }
515 
StripPac(uintptr_t inAddr,uintptr_t pacMask)516 uintptr_t Unwinder::StripPac(uintptr_t inAddr, uintptr_t pacMask)
517 {
518     uintptr_t outAddr = inAddr;
519 #if defined(__aarch64__)
520     if (outAddr != 0) {
521         if (pacMask != 0) {
522             outAddr &= ~pacMask;
523         } else {
524             register uint64_t x30 __asm("x30") = inAddr;
525             asm("hint 0x7" : "+r"(x30));
526             outAddr = x30;
527         }
528         if (outAddr != inAddr) {
529             LOGW("Strip pac in addr: %lx, out addr: %lx", (uint64_t)inAddr, (uint64_t)outAddr);
530         }
531     }
532 #endif
533     return outAddr;
534 }
535 
DoPcAdjust(uintptr_t & pc)536 void Unwinder::DoPcAdjust(uintptr_t& pc)
537 {
538     if (pc <= 0x4) {
539         return;
540     }
541     uintptr_t sz = 0x4;
542 #if defined(__arm__)
543     if (pc & 0x1) {
544         uintptr_t val;
545         if (pc < 0x5 || !(memory_->ReadMem(pc - 0x5, &val)) ||
546             (val & 0xe000f000) != 0xe000f000) {
547             sz = 0x2;
548         }
549     }
550 #elif defined(__x86_64__)
551     sz = 0x1;
552 #endif
553     pc -= sz;
554 }
555 
GetFrames()556 std::vector<DfxFrame>& Unwinder::GetFrames()
557 {
558     if (enableFillFrames_) {
559         FillFrames(frames_);
560     }
561     return frames_;
562 }
563 
SetFrames(std::vector<DfxFrame> & frames)564 void Unwinder::SetFrames(std::vector<DfxFrame>& frames)
565 {
566     frames_ = frames;
567 }
568 
AddFrame(uintptr_t pc,uintptr_t sp,std::shared_ptr<DfxMap> map,size_t & index)569 void Unwinder::AddFrame(uintptr_t pc, uintptr_t sp, std::shared_ptr<DfxMap> map, size_t& index)
570 {
571     pcs_.emplace_back(pc);
572     DfxFrame frame;
573     frame.index = (index++);
574     frame.sp = static_cast<uint64_t>(sp);
575     frame.pc = static_cast<uint64_t>(pc);
576     frame.map = map;
577     frames_.emplace_back(frame);
578 }
579 
AddFrame(DfxFrame & frame)580 void Unwinder::AddFrame(DfxFrame& frame)
581 {
582     frames_.emplace_back(frame);
583 }
584 
FillFrames(std::vector<DfxFrame> & frames)585 void Unwinder::FillFrames(std::vector<DfxFrame>& frames)
586 {
587     for (size_t i = 0; i < frames.size(); ++i) {
588         FillFrame(frames[i]);
589     }
590 }
591 
FillFrame(DfxFrame & frame)592 void Unwinder::FillFrame(DfxFrame& frame)
593 {
594     if (frame.isJsFrame) {
595         return;
596     }
597     if (frame.map == nullptr) {
598         frame.relPc = frame.pc;
599         frame.mapName = "Not mapped";
600         LOGU("Current frame is not mapped.");
601         return;
602     }
603     frame.relPc = frame.map->GetRelPc(frame.pc);
604     frame.mapName = frame.map->GetElfName();
605     frame.mapOffset = frame.map->offset;
606     auto elf = frame.map->GetElf();
607     if (elf == nullptr) {
608         LOGU("elf is null, mapName: %s", frame.mapName.c_str());
609         return;
610     }
611     LOGU("mapName: %s, mapOffset: %" PRIx64 "", frame.mapName.c_str(), frame.mapOffset);
612     if (!DfxSymbols::GetFuncNameAndOffsetByPc(frame.relPc, elf, frame.funcName, frame.funcOffset)) {
613         LOGU("Failed to get symbol, mapName: %s, relPc: %" PRIx64 "", frame.mapName.c_str(), frame.relPc);
614     }
615     frame.buildId = elf->GetBuildId();
616 }
617 
GetFramesByPcs(std::vector<DfxFrame> & frames,std::vector<uintptr_t> pcs,std::shared_ptr<DfxMaps> maps)618 void Unwinder::GetFramesByPcs(std::vector<DfxFrame>& frames, std::vector<uintptr_t> pcs,
619     std::shared_ptr<DfxMaps> maps)
620 {
621     frames.clear();
622     std::shared_ptr<DfxMap> map = nullptr;
623     for (size_t i = 0; i < pcs.size(); ++i) {
624         DfxFrame frame;
625         frame.index = i;
626         frame.pc = static_cast<uint64_t>(pcs[i]);
627         if ((map != nullptr) && map->Contain(frame.pc)) {
628             LOGU("map had matched");
629         } else {
630             if (!maps->FindMapByAddr(pcs[i], map) || (map == nullptr)) {
631                 LOGE("map is null");
632                 continue;
633             }
634         }
635         frame.map = map;
636         FillFrame(frame);
637         frames.emplace_back(frame);
638     }
639 }
640 
GetSymbolByPc(uintptr_t pc,std::shared_ptr<DfxMaps> maps,std::string & funcName,uint64_t & funcOffset)641 bool Unwinder::GetSymbolByPc(uintptr_t pc, std::shared_ptr<DfxMaps> maps, std::string& funcName, uint64_t& funcOffset)
642 {
643     if (maps == nullptr) {
644         return false;
645     }
646     std::shared_ptr<DfxMap> map = nullptr;
647     if (!maps->FindMapByAddr(pc, map) || (map == nullptr)) {
648         LOGE("Find map is null");
649         return false;
650     }
651     uint64_t relPc = map->GetRelPc(static_cast<uint64_t>(pc));
652     auto elf = map->GetElf();
653     if (elf == nullptr) {
654         LOGE("Get elf is null");
655         return false;
656     }
657     return DfxSymbols::GetFuncNameAndOffsetByPc(relPc, elf, funcName, funcOffset);
658 }
659 
GetFramesStr(const std::vector<DfxFrame> & frames)660 std::string Unwinder::GetFramesStr(const std::vector<DfxFrame>& frames)
661 {
662     return DfxFrameFormatter::GetFramesStr(frames);
663 }
664 } // namespace HiviewDFX
665 } // namespace OHOS
666