• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "backtrace_local_thread.h"
17 
18 #include <sstream>
19 
20 #include <link.h>
21 #include <unistd.h>
22 #include <mutex>
23 #include <pthread.h>
24 #include <libunwind.h>
25 #include <libunwind_i-ohos.h>
26 #include <securec.h>
27 
28 #include "backtrace_local_context.h"
29 #include "dfx_define.h"
30 #include "dfx_util.h"
31 #include "procinfo.h"
32 #include "fp_unwinder.h"
33 #include "dwarf_unwinder.h"
34 #include "dfx_frame_format.h"
35 
36 namespace OHOS {
37 namespace HiviewDFX {
38 namespace {
39 #undef LOG_DOMAIN
40 #undef LOG_TAG
41 #define LOG_DOMAIN 0xD002D11
42 #define LOG_TAG "DfxBacktraceLocal"
43 }
44 
BacktraceLocalThread(int32_t tid)45 BacktraceLocalThread::BacktraceLocalThread(int32_t tid) : tid_(tid)
46 {
47     frames_.clear();
48 }
49 
~BacktraceLocalThread()50 BacktraceLocalThread::~BacktraceLocalThread()
51 {
52     if (tid_ != BACKTRACE_CURRENT_THREAD) {
53         BacktraceLocalContext::GetInstance().CleanUp();
54     }
55     frames_.clear();
56 }
57 
UnwindCurrentThread(unw_addr_space_t as,std::shared_ptr<DfxSymbols> symbol,size_t skipFrameNum,bool fast)58 bool BacktraceLocalThread::UnwindCurrentThread(unw_addr_space_t as, std::shared_ptr<DfxSymbols> symbol,
59     size_t skipFrameNum, bool fast)
60 {
61     bool ret = false;
62     unw_context_t context;
63     (void)memset_s(&context, sizeof(unw_context_t), 0, sizeof(unw_context_t));
64     unw_getcontext(&context);
65 
66     if (fast) {
67 #ifdef __aarch64__
68         FpUnwinder unwinder;
69         ret = unwinder.UnwindWithContext(context, skipFrameNum + 1);
70         unwinder.UpdateFrameInfo();
71         frames_ = unwinder.GetFrames();
72 #endif
73     }
74     if (!ret) {
75         DwarfUnwinder unwinder;
76         ret = unwinder.UnwindWithContext(as, context, symbol, skipFrameNum + 1);
77         frames_ = unwinder.GetFrames();
78     }
79     return ret;
80 }
81 
Unwind(unw_addr_space_t as,std::shared_ptr<DfxSymbols> symbol,size_t skipFrameNum,bool fast,bool releaseThread)82 bool BacktraceLocalThread::Unwind(unw_addr_space_t as, std::shared_ptr<DfxSymbols> symbol,
83     size_t skipFrameNum, bool fast, bool releaseThread)
84 {
85     static std::mutex mutex;
86     std::unique_lock<std::mutex> lock(mutex);
87     bool ret = false;
88 
89     if (tid_ == BACKTRACE_CURRENT_THREAD) {
90         return UnwindCurrentThread(as, symbol, skipFrameNum + 1, fast);
91     } else if (tid_ < BACKTRACE_CURRENT_THREAD) {
92         return ret;
93     }
94 
95     auto threadContext = BacktraceLocalContext::GetInstance().GetThreadContext(tid_);
96     if (threadContext == nullptr) {
97         return ret;
98     }
99 
100     if (threadContext->ctx == nullptr) {
101         // should never happen
102         ReleaseThread();
103         return ret;
104     }
105 
106     if (!ret) {
107         DwarfUnwinder unwinder;
108         ret = unwinder.UnwindWithContext(as, *(threadContext->ctx), symbol, skipFrameNum);
109         frames_ = unwinder.GetFrames();
110     }
111 
112     if (releaseThread) {
113         ReleaseThread();
114     }
115     return ret;
116 }
117 
GetFrames() const118 const std::vector<DfxFrame>& BacktraceLocalThread::GetFrames() const
119 {
120     return frames_;
121 }
122 
ReleaseThread()123 void BacktraceLocalThread::ReleaseThread()
124 {
125     if (tid_ > BACKTRACE_CURRENT_THREAD) {
126         BacktraceLocalContext::GetInstance().ReleaseThread(tid_);
127     }
128 }
129 
GetFormatedStr(bool withThreadName)130 std::string BacktraceLocalThread::GetFormatedStr(bool withThreadName)
131 {
132     if (frames_.empty()) {
133         return "";
134     }
135 
136     std::ostringstream ss;
137     if (withThreadName && (tid_ > 0)) {
138         std::string threadName;
139         // Tid:1676, Name:IPC_3_1676
140         ReadThreadName(tid_, threadName);
141         ss << "Tid:" << tid_ << ", Name:" << threadName << std::endl;
142     }
143 
144     ss << DfxFrameFormat::GetFramesStr(frames_);
145     return ss.str();
146 }
147 } // namespace HiviewDFX
148 } // namespace OHOS
149