• 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.h"
17 
18 #include <cstring>
19 #include <mutex>
20 #include <sstream>
21 #include <vector>
22 
23 #include "dfx_frame_format.h"
24 #include "dfx_util.h"
25 #include "directory_ex.h"
26 #include "backtrace_local_thread.h"
27 
28 #include <dirent.h>
29 #include <hilog/log.h>
30 #include <unistd.h>
31 #include <libunwind_i-ohos.h>
32 #include "procinfo.h"
33 
34 namespace OHOS {
35 namespace HiviewDFX {
36 namespace {
37 #undef LOG_DOMAIN
38 #undef LOG_TAG
39 #define LOG_TAG "DfxBacktrace"
40 #define LOG_DOMAIN 0xD002D11
41 
42 constexpr int SKIP_ONE_FRAME = 1; // skip current frame
43 }
44 
GetBacktraceFramesByTid(std::vector<DfxFrame> & frames,int32_t tid,size_t skipFrameNum,bool fast)45 bool GetBacktraceFramesByTid(std::vector<DfxFrame>& frames, int32_t tid, size_t skipFrameNum, bool fast)
46 {
47     bool ret = false;
48     BacktraceLocalThread thread(tid);
49     if (fast) {
50 #ifdef __aarch64__
51         ret = thread.Unwind(nullptr, nullptr, skipFrameNum, fast);
52 #endif
53     }
54     if (!ret) {
55         unw_addr_space_t as;
56         unw_init_local_address_space(&as);
57         if (as == nullptr) {
58             return ret;
59         }
60         auto symbol = std::make_shared<DfxSymbols>();
61 
62         ret = thread.Unwind(as, symbol, skipFrameNum, fast);
63 
64         unw_destroy_local_address_space(as);
65     }
66     frames.clear();
67     frames = thread.GetFrames();
68     return ret;
69 }
70 
GetBacktraceStringByTid(std::string & out,int32_t tid,size_t skipFrameNum,bool fast)71 bool GetBacktraceStringByTid(std::string& out, int32_t tid, size_t skipFrameNum, bool fast)
72 {
73     std::vector<DfxFrame> frames;
74     bool ret = GetBacktraceFramesByTid(frames, tid, skipFrameNum + 1, fast);
75 
76     out.clear();
77     out = DfxFrameFormat::GetFramesStr(frames);
78     return ret;
79 }
80 
PrintBacktrace(int32_t fd,bool fast)81 bool PrintBacktrace(int32_t fd, bool fast)
82 {
83     std::vector<DfxFrame> frames;
84     bool ret = GetBacktraceFramesByTid(frames, BACKTRACE_CURRENT_THREAD, SKIP_ONE_FRAME, fast);
85     if (!ret) {
86         return false;
87     }
88 
89     for (auto const& frame : frames) {
90         auto line = DfxFrameFormat::GetFrameStr(frame);
91         if (fd < 0) {
92             // print to hilog
93             HILOG_INFO(LOG_CORE, " %{public}s", line.c_str());
94         } else {
95             dprintf(fd, "    %s", line.c_str());
96         }
97     }
98     return ret;
99 }
100 
GetBacktrace(std::string & out,bool fast)101 bool GetBacktrace(std::string& out, bool fast)
102 {
103     return GetBacktraceStringByTid(out, BACKTRACE_CURRENT_THREAD, SKIP_ONE_FRAME, fast);
104 }
105 
GetBacktrace(std::string & out,size_t skipFrameNum,bool fast)106 bool GetBacktrace(std::string& out, size_t skipFrameNum, bool fast)
107 {
108     return GetBacktraceStringByTid(out, BACKTRACE_CURRENT_THREAD, skipFrameNum + 1, fast);
109 }
110 
PrintTrace(int32_t fd)111 bool PrintTrace(int32_t fd)
112 {
113     return PrintBacktrace(fd, false);
114 }
115 
GetTrace(size_t skipFrameNum)116 const char* GetTrace(size_t skipFrameNum)
117 {
118     static std::string trace;
119     trace.clear();
120     if (!GetBacktrace(trace, skipFrameNum)) {
121         HILOG_ERROR(LOG_CORE, "Failed to get trace string");
122     }
123     return trace.c_str();
124 }
125 
GetStacktraceHeader()126 static std::string GetStacktraceHeader()
127 {
128     pid_t pid = getpid();
129     std::ostringstream ss;
130     ss << "" << std::endl << "Timestamp:" << GetCurrentTimeStr();
131     ss << "Pid:" << pid << std::endl;
132     ss << "Uid:" << getuid() << std::endl;
133     std::string processName;
134     ReadProcessName(pid, processName);
135     ss << "Process name::" << processName << std::endl;
136     return ss.str();
137 }
138 
GetProcessStacktrace()139 std::string GetProcessStacktrace()
140 {
141     unw_addr_space_t as;
142     unw_init_local_address_space(&as);
143     if (as == nullptr) {
144         return "";
145     }
146     auto symbol = std::make_shared<DfxSymbols>();
147     std::ostringstream ss;
148     ss << std::endl << GetStacktraceHeader();
149 
150     std::function<bool(int)> func = [&](int tid) {
151         if (tid <= 0 || tid == gettid()) {
152             return false;
153         }
154         BacktraceLocalThread thread(tid);
155         if (thread.Unwind(as, symbol, 0)) {
156             ss << thread.GetFormatedStr(true) << std::endl;
157         }
158         return true;
159     };
160 
161     std::vector<int> tids;
162     GetTidsByPidWithFunc(getpid(), tids, func);
163 
164     unw_destroy_local_address_space(as);
165     return ss.str();
166 }
167 } // namespace HiviewDFX
168 } // namespace OHOS
169