1 /*
2 * Copyright (c) 2023-2025 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 "dump_info_json_formatter.h"
17
18 #include <cinttypes>
19 #include <string>
20
21 #include "dfx_define.h"
22
23 #include "dfx_log.h"
24 #include "dfx_maps.h"
25 #include "dfx_process.h"
26 #include "dfx_signal.h"
27 #include "dfx_thread.h"
28 #include "dump_utils.h"
29 #include "process_dumper.h"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33
GetJsonFormatInfo(const ProcessDumpRequest & request,DfxProcess & process,std::string & jsonStringInfo)34 bool DumpInfoJsonFormatter::GetJsonFormatInfo(const ProcessDumpRequest& request, DfxProcess& process,
35 std::string& jsonStringInfo)
36 {
37 #ifndef is_ohos_lite
38 Json::Value jsonInfo;
39 switch (request.type) {
40 case ProcessDumpType::DUMP_TYPE_CPP_CRASH:
41 GetCrashJsonFormatInfo(request, process, jsonInfo);
42 break;
43 case ProcessDumpType::DUMP_TYPE_DUMP_CATCH:
44 GetDumpJsonFormatInfo(process, jsonInfo);
45 break;
46 default:
47 break;
48 }
49 jsonStringInfo.append(Json::FastWriter().write(jsonInfo));
50 return true;
51 #endif
52 return false;
53 }
54
55 #ifndef is_ohos_lite
GetCrashJsonFormatInfo(const ProcessDumpRequest & request,DfxProcess & process,Json::Value & jsonInfo)56 void DumpInfoJsonFormatter::GetCrashJsonFormatInfo(const ProcessDumpRequest& request, DfxProcess& process,
57 Json::Value& jsonInfo)
58 {
59 jsonInfo["time"] = request.timeStamp;
60 jsonInfo["uuid"] = "";
61 jsonInfo["crash_type"] = "NativeCrash";
62 jsonInfo["pid"] = process.GetProcessInfo().pid;
63 jsonInfo["uid"] = process.GetProcessInfo().uid;
64 jsonInfo["app_running_unique_id"] = request.appRunningId;
65
66 DfxSignal dfxSignal(request.siginfo.si_signo);
67 Json::Value signal;
68 signal["signo"] = request.siginfo.si_signo;
69 signal["code"] = request.siginfo.si_code;
70 signal["address"] = dfxSignal.IsAddrAvailable() ?
71 StringPrintf("%" PRIX64_ADDR, reinterpret_cast<uint64_t>(request.siginfo.si_addr)) : "";
72 Json::Value exception;
73 exception["signal"] = signal;
74 exception["message"] = process.GetFatalMessage();
75
76 Json::Value frames(Json::arrayValue);
77 if (process.GetKeyThread() == nullptr) {
78 exception["thread_name"] = "";
79 exception["tid"] = 0;
80 } else {
81 exception["thread_name"] = process.GetKeyThread()->GetThreadInfo().threadName;
82 exception["tid"] = process.GetKeyThread()->GetThreadInfo().tid;
83 FillFramesJson(process.GetKeyThread()->GetFrames(), frames);
84 }
85 exception["frames"] = frames;
86 jsonInfo["exception"] = exception;
87
88 // fill other thread info
89 const auto& otherThreads = process.GetOtherThreads();
90 if (otherThreads.size() > 0) {
91 Json::Value threadsJsonArray(Json::arrayValue);
92 AppendThreads(otherThreads, threadsJsonArray);
93 jsonInfo["threads"] = threadsJsonArray;
94 }
95 }
96
GetDumpJsonFormatInfo(DfxProcess & process,Json::Value & jsonInfo)97 void DumpInfoJsonFormatter::GetDumpJsonFormatInfo(DfxProcess& process, Json::Value& jsonInfo)
98 {
99 Json::Value thread;
100 Json::Value frames(Json::arrayValue);
101 if (process.GetKeyThread() == nullptr) {
102 thread["thread_name"] = "";
103 thread["tid"] = 0;
104 } else {
105 thread["thread_name"] = process.GetKeyThread()->GetThreadInfo().threadName;
106 thread["tid"] = process.GetKeyThread()->GetThreadInfo().tid;
107 FillFramesJson(process.GetKeyThread()->GetFrames(), frames);
108 }
109 thread["frames"] = frames;
110 jsonInfo.append(thread);
111
112 // fill other thread info
113 const auto& otherThreads = process.GetOtherThreads();
114 if (otherThreads.size() > 0) {
115 AppendThreads(otherThreads, jsonInfo);
116 }
117 }
118
AppendThreads(const std::vector<std::shared_ptr<DfxThread>> & threads,Json::Value & jsonInfo) const119 void DumpInfoJsonFormatter::AppendThreads(const std::vector<std::shared_ptr<DfxThread>>& threads,
120 Json::Value& jsonInfo) const
121 {
122 for (auto const& oneThread : threads) {
123 if (oneThread != nullptr) {
124 Json::Value threadJson;
125 threadJson["thread_name"] = oneThread->GetThreadInfo().threadName;
126 threadJson["tid"] = oneThread->GetThreadInfo().tid;
127 Json::Value framesJson(Json::arrayValue);
128 FillFramesJson(oneThread->GetFrames(), framesJson);
129 threadJson["frames"] = framesJson;
130 jsonInfo.append(threadJson);
131 }
132 }
133 }
134
FillFramesJson(const std::vector<DfxFrame> & frames,Json::Value & jsonInfo) const135 bool DumpInfoJsonFormatter::FillFramesJson(const std::vector<DfxFrame>& frames, Json::Value& jsonInfo) const
136 {
137 for (const auto& frame : frames) {
138 if (frame.isJsFrame) {
139 FillJsFrameJson(frame, jsonInfo);
140 } else {
141 FillNativeFrameJson(frame, jsonInfo);
142 #if defined(__aarch64__)
143 if (DumpUtils::IsLastValidFrame(frame)) {
144 break;
145 }
146 #endif
147 }
148 }
149 return true;
150 }
151
FillJsFrameJson(const DfxFrame & frame,Json::Value & jsonInfo) const152 void DumpInfoJsonFormatter::FillJsFrameJson(const DfxFrame& frame, Json::Value& jsonInfo) const
153 {
154 Json::Value frameJson;
155 frameJson["file"] = frame.mapName;
156 frameJson["packageName"] = frame.packageName;
157 frameJson["symbol"] = frame.funcName;
158 frameJson["line"] = frame.line;
159 frameJson["column"] = frame.column;
160 jsonInfo.append(frameJson);
161 }
162
FillNativeFrameJson(const DfxFrame & frame,Json::Value & jsonInfo) const163 void DumpInfoJsonFormatter::FillNativeFrameJson(const DfxFrame& frame, Json::Value& jsonInfo) const
164 {
165 Json::Value frameJson;
166 #ifdef __LP64__
167 frameJson["pc"] = StringPrintf("%016lx", frame.relPc);
168 #else
169 frameJson["pc"] = StringPrintf("%08llx", frame.relPc);
170 #endif
171 if (frame.parseSymbolState.IsParseSymbolComplete() && frame.funcName.length() <= MAX_FUNC_NAME_LEN) {
172 frameJson["symbol"] = frame.funcName;
173 } else {
174 frameJson["symbol"] = "";
175 }
176 frameJson["offset"] = frame.funcOffset;
177 std::string strippedMapName = DfxMap::UnFormatMapName(frame.mapName);
178 frameJson["file"] = strippedMapName;
179 frameJson["buildId"] = frame.buildId;
180 jsonInfo.append(frameJson);
181 }
182 #endif
183 } // namespace HiviewDFX
184 } // namespace OHOS
185