• 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 "dfx_stack_info_json_formatter.h"
17 
18 #include <cinttypes>
19 #include <string>
20 
21 #include "dfx_define.h"
22 #include "dfx_logger.h"
23 #include "dfx_maps.h"
24 #include "dfx_process.h"
25 #include "dfx_signal.h"
26 #include "dfx_thread.h"
27 #include "process_dumper.h"
28 #if defined(__aarch64__)
29 #include "printer.h"
30 #endif
31 
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace {
35 static const char NATIVE_CRASH_TYPE[] = "NativeCrash";
36 
37 #ifndef is_ohos_lite
FillJsFrame(const DfxFrame & frame,Json::Value & jsonInfo)38 void FillJsFrame(const DfxFrame& frame, Json::Value& jsonInfo)
39 {
40     Json::Value frameJson;
41     frameJson["file"] = frame.mapName;
42     frameJson["packageName"] = frame.packageName;
43     frameJson["symbol"] = frame.funcName;
44     frameJson["line"] = frame.line;
45     frameJson["column"] = frame.column;
46     jsonInfo.append(frameJson);
47 }
48 #endif
49 }
50 
GetJsonFormatInfo(bool isDump,std::string & jsonStringInfo) const51 bool DfxStackInfoJsonFormatter::GetJsonFormatInfo(bool isDump, std::string& jsonStringInfo) const
52 {
53 #ifndef is_ohos_lite
54     Json::Value jsonInfo;
55     if ((process_ == nullptr) || (request_ == nullptr)) {
56         DFXLOGE("GetStackInfo var is null");
57         return false;
58     }
59     if (isDump) {
60         GetDumpJsonFormatInfo(jsonInfo);
61     } else {
62         GetCrashJsonFormatInfo(jsonInfo);
63     }
64     jsonStringInfo.append(Json::FastWriter().write(jsonInfo));
65     return true;
66 #endif
67     return false;
68 }
69 
70 #ifndef is_ohos_lite
GetCrashJsonFormatInfo(Json::Value & jsonInfo) const71 void DfxStackInfoJsonFormatter::GetCrashJsonFormatInfo(Json::Value& jsonInfo) const
72 {
73     jsonInfo["time"] = request_->timeStamp;
74     jsonInfo["uuid"] = "";
75     jsonInfo["crash_type"] = NATIVE_CRASH_TYPE;
76     jsonInfo["pid"] = process_->processInfo_.pid;
77     jsonInfo["uid"] = process_->processInfo_.uid;
78     jsonInfo["app_running_unique_id"] = request_->appRunningId;
79 
80     DfxSignal dfxSignal(request_->siginfo.si_signo);
81     Json::Value signal;
82     signal["signo"] = request_->siginfo.si_signo;
83     signal["code"] = request_->siginfo.si_code;
84     if (dfxSignal.IsAddrAvailable()) {
85         signal["address"] = StringPrintf("%" PRIX64_ADDR, reinterpret_cast<uint64_t>(request_->siginfo.si_addr));
86     } else {
87         signal["address"] = "";
88     }
89     Json::Value exception;
90     exception["signal"] = signal;
91     exception["message"] = process_->GetFatalMessage();
92     if (process_->keyThread_ == nullptr) {
93         exception["thread_name"] = "";
94         exception["tid"] = 0;
95     } else {
96         exception["thread_name"] = process_->keyThread_->threadInfo_.threadName;
97         exception["tid"] = process_->keyThread_->threadInfo_.tid;
98     }
99 
100     Json::Value frames(Json::arrayValue);
101     if (process_->keyThread_ != nullptr) {
102         FillFrames(process_->keyThread_, frames);
103     }
104     exception["frames"] = frames;
105     jsonInfo["exception"] = exception;
106 
107     // fill other thread info
108     auto otherThreads = process_->GetOtherThreads();
109     if (otherThreads.size() > 0) {
110         Json::Value threadsJsonArray(Json::arrayValue);
111         AppendThreads(otherThreads, threadsJsonArray);
112         jsonInfo["threads"] = threadsJsonArray;
113     }
114 }
115 
GetDumpJsonFormatInfo(Json::Value & jsonInfo) const116 void DfxStackInfoJsonFormatter::GetDumpJsonFormatInfo(Json::Value& jsonInfo) const
117 {
118     Json::Value thread;
119     Json::Value frames(Json::arrayValue);
120     if (process_->keyThread_ == nullptr) {
121         thread["thread_name"] = "";
122         thread["tid"] = 0;
123     } else {
124         thread["thread_name"] = process_->keyThread_->threadInfo_.threadName;
125         thread["tid"] = process_->keyThread_->threadInfo_.tid;
126         FillFrames(process_->keyThread_, frames);
127     }
128     thread["frames"] = frames;
129     jsonInfo.append(thread);
130 
131     // fill other thread info
132     auto otherThreads = process_->GetOtherThreads();
133     if (otherThreads.size() > 0) {
134         AppendThreads(otherThreads, jsonInfo);
135     }
136 }
137 
FillFrames(const std::shared_ptr<DfxThread> & thread,Json::Value & jsonInfo) const138 bool DfxStackInfoJsonFormatter::FillFrames(const std::shared_ptr<DfxThread>& thread,
139                                            Json::Value& jsonInfo) const
140 {
141     if (thread == nullptr) {
142         DFXLOGE("FillFrames thread is null");
143         return false;
144     }
145     const auto& threadFrames = thread->GetFrames();
146     for (const auto& frame : threadFrames) {
147         if (frame.isJsFrame) {
148             FillJsFrame(frame, jsonInfo);
149             continue;
150         }
151         FillNativeFrame(frame, jsonInfo);
152 #if defined(__aarch64__)
153         if (Printer::IsLastValidFrame(frame)) {
154             break;
155         }
156 #endif
157     }
158     return true;
159 }
160 
FillNativeFrame(const DfxFrame & frame,Json::Value & jsonInfo) const161 void DfxStackInfoJsonFormatter::FillNativeFrame(const DfxFrame& frame, Json::Value& jsonInfo) const
162 {
163     Json::Value frameJson;
164 #ifdef __LP64__
165     frameJson["pc"] = StringPrintf("%016lx", frame.relPc);
166 #else
167     frameJson["pc"] = StringPrintf("%08llx", frame.relPc);
168 #endif
169     if (frame.funcName.length() > MAX_FUNC_NAME_LEN) {
170         DFXLOGD("length of funcName greater than 256 byte, do not report it");
171         frameJson["symbol"] = "";
172     } else {
173         frameJson["symbol"] = frame.funcName;
174     }
175     frameJson["offset"] = frame.funcOffset;
176     std::string strippedMapName = frame.mapName;
177     DfxMap::UnFormatMapName(strippedMapName);
178     frameJson["file"] = strippedMapName;
179     frameJson["buildId"] = frame.buildId;
180     jsonInfo.append(frameJson);
181 }
182 
AppendThreads(const std::vector<std::shared_ptr<DfxThread>> & threads,Json::Value & jsonInfo) const183 void DfxStackInfoJsonFormatter::AppendThreads(const std::vector<std::shared_ptr<DfxThread>>& threads,
184                                               Json::Value& jsonInfo) const
185 {
186     for (auto const& oneThread : threads) {
187         Json::Value threadJson;
188         threadJson["thread_name"] = oneThread->threadInfo_.threadName;
189         threadJson["tid"] = oneThread->threadInfo_.tid;
190         Json::Value frames(Json::arrayValue);
191         FillFrames(oneThread, frames);
192         threadJson["frames"] = frames;
193         jsonInfo.append(threadJson);
194     }
195 }
196 #endif
197 } // namespace HiviewDFX
198 } // namespace OHOS
199