• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }