1 /*
2 * Copyright (c) 2022 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.h"
17 #include "hidebug/hidebug.h"
18 #include "hilog/log.h"
19 #include <condition_variable>
20 #include <csignal>
21 #include <sys/syscall.h>
22 #include <unistd.h>
23
24
25 #define MAX_FRAME_SIZE 256 // 最大栈回溯深度,应根据业务场景调整该值。
26 namespace {
27 constexpr auto LOG_PRINT_DOMAIN = 0xFF00;
28 } // namespace
29
30 class BackTraceObject {
31 public:
32 static BackTraceObject &GetInstance();
33 BackTraceObject(const BackTraceObject &) = delete;
34 BackTraceObject &operator=(const BackTraceObject &) = delete;
35 BackTraceObject(BackTraceObject &&) = delete;
36 BackTraceObject &operator=(BackTraceObject &&) = delete;
37 bool Init(uint32_t size);
38 void Release();
39 int BackTraceFromFp(void *startFp, int size);
40 void SymbolicAddress(int index);
41 void SymbolicInvalidAddress(int index);
42 void PrintStackFrame(void *pc, const HiDebug_StackFrame &frame);
43
44 private:
45 BackTraceObject() = default;
46 ~BackTraceObject() = default;
47 HiDebug_Backtrace_Object backtraceObject_ = nullptr;
48 void **pcs_ = nullptr;
49 };
50
GetInstance()51 BackTraceObject &BackTraceObject::GetInstance()
52 {
53 static BackTraceObject instance;
54 return instance;
55 }
56
Init(uint32_t size)57 bool BackTraceObject::Init(uint32_t size) // 初始化,申请资源。
58 {
59 backtraceObject_ = OH_HiDebug_CreateBacktraceObject();
60 if (backtraceObject_ == nullptr) {
61 return false;
62 }
63 pcs_ = new (std::nothrow) void *[MAX_FRAME_SIZE] { nullptr };
64 if (pcs_ == nullptr) {
65 return false;
66 }
67 return true;
68 }
69
Release()70 void BackTraceObject::Release() // 释放栈回溯及栈解析的资源。
71 {
72 OH_HiDebug_DestroyBacktraceObject(backtraceObject_);
73 backtraceObject_ = nullptr;
74 delete[] pcs_;
75 pcs_ = nullptr;
76 }
77
BackTraceFromFp(void * startFp,int size)78 int BackTraceObject::BackTraceFromFp(void *startFp, int size)
79 {
80 if (size <= MAX_FRAME_SIZE) {
81 return OH_HiDebug_BacktraceFromFp(backtraceObject_, startFp, pcs_, size);
82 }
83 return 0;
84 }
85
PrintStackFrame(void * pc,const HiDebug_StackFrame & frame)86 void BackTraceObject::PrintStackFrame(void *pc, const HiDebug_StackFrame &frame)
87 {
88 if (frame.type == HIDEBUG_STACK_FRAME_TYPE_JS) {
89 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "TestTag",
90 "js stack frame info for pc: %{public}p is "
91 "relativePc: %{public}p "
92 "line: %{public}d "
93 "column: %{public}d "
94 "mapName: %{public}s "
95 "functionName: %{public}s "
96 "url: %{public}s "
97 "packageName: %{public}s.",
98 pc, reinterpret_cast<void *>(frame.frame.js.relativePc), frame.frame.js.line,
99 frame.frame.js.column, frame.frame.js.mapName, frame.frame.js.functionName, frame.frame.js.url,
100 frame.frame.js.packageName);
101 } else {
102 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "TestTag",
103 "native stack frame info for pc: %{public}p is "
104 "relativePc: %{public}p "
105 "funcOffset: %{public}p "
106 "mapName: %{public}s "
107 "functionName: %{public}s "
108 "buildId: %{public}s "
109 "reserved: %{public}s.",
110 pc, reinterpret_cast<void *>(frame.frame.native.relativePc),
111 reinterpret_cast<void *>(frame.frame.native.funcOffset), frame.frame.native.mapName,
112 frame.frame.native.functionName, frame.frame.native.buildId, frame.frame.native.reserved);
113 }
114 }
115
SymbolicAddress(int index)116 void BackTraceObject::SymbolicAddress(int index)
117 {
118 if (index < 0 || index >= MAX_FRAME_SIZE) {
119 return;
120 }
121 OH_HiDebug_SymbolicAddress(backtraceObject_, pcs_[index], this,
122 [](void *pc, void *arg, const HiDebug_StackFrame *frame) {
123 reinterpret_cast<BackTraceObject *>(arg)->PrintStackFrame(pc, *frame);
124 });
125 }
126
SymbolicInvalidAddress(int index)127 void BackTraceObject::SymbolicInvalidAddress(int index) {
128 if (index < 0 || index >= MAX_FRAME_SIZE) {
129 return;
130 }
131 int i = OH_HiDebug_SymbolicAddress(backtraceObject_, reinterpret_cast<BackTraceObject *>(0x0001), this,
132 [](void *pc, void *arg, const HiDebug_StackFrame *frame) {
133 reinterpret_cast<BackTraceObject *>(arg)->PrintStackFrame(pc, *frame);
134 });
135 OH_LOG_Print(LOG_APP, LOG_WARN, LOG_PRINT_DOMAIN, "TestTag", "return error code %{public}d", i);
136 }
137
138
BackTraceCurrentThread()139 void BackTraceCurrentThread()
140 {
141 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "TestTag", "start BackTraceCurrentThread");
142 BackTraceObject::GetInstance().Init(MAX_FRAME_SIZE);
143 auto pcSize2 = BackTraceObject::GetInstance().BackTraceFromFp(__builtin_frame_address(0), MAX_FRAME_SIZE);
144 for (int i = 0; i < pcSize2; i++) {
145 BackTraceObject::GetInstance().SymbolicAddress(i); // 栈解析。
146 }
147 BackTraceObject::GetInstance().Release();
148 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "TestTag", "end BackTraceCurrentThread");
149 }
150
InvaildBackTraceCurrentThread()151 void InvaildBackTraceCurrentThread()
152 {
153 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "TestTag", "start BackTraceCurrentThread");
154 BackTraceObject::GetInstance().Init(MAX_FRAME_SIZE);
155 auto pcSize2 = BackTraceObject::GetInstance().BackTraceFromFp(__builtin_frame_address(0), MAX_FRAME_SIZE);
156 for (int i = 0; i < pcSize2; i++) {
157 BackTraceObject::GetInstance().SymbolicInvalidAddress(i); // 栈解析。
158 }
159 BackTraceObject::GetInstance().Release();
160 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "TestTag", "end BackTraceCurrentThread");
161 }