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_json_formatter.h"
17
18 #include <cstdlib>
19 #include <iostream>
20 #include <ostream>
21 #include <regex>
22 #include <securec.h>
23 #include <sstream>
24 #ifndef is_ohos_lite
25 #include "json/json.h"
26 #endif
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 #ifndef is_ohos_lite
31 namespace {
32 const int FRAME_BUF_LEN = 1024;
FormatJsFrame(const Json::Value & frames,const uint32_t & frameIdx,std::string & outStr)33 static bool FormatJsFrame(const Json::Value& frames, const uint32_t& frameIdx, std::string& outStr)
34 {
35 const int jsIdxLen = 10;
36 char buf[jsIdxLen] = { 0 };
37 char idxFmt[] = "#%02u at ";
38 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, idxFmt, frameIdx) <= 0) {
39 return false;
40 }
41 outStr = std::string(buf, strlen(buf));
42 std::string symbol = frames[frameIdx]["symbol"].asString();
43 std::string file = frames[frameIdx]["file"].asString();
44 std::string line = frames[frameIdx]["line"].asString();
45 std::string column = frames[frameIdx]["column"].asString();
46 outStr.append(symbol + " (" + file + ":" + line + ":" + column + ")");
47 return true;
48 }
49
FormatNativeFrame(const Json::Value & frames,const uint32_t & frameIdx,std::string & outStr)50 static bool FormatNativeFrame(const Json::Value& frames, const uint32_t& frameIdx, std::string& outStr)
51 {
52 char buf[FRAME_BUF_LEN] = {0};
53 char format[] = "#%02u pc %s %s";
54 std::string buildId = frames[frameIdx]["buildId"].asString();
55 std::string file = frames[frameIdx]["file"].asString();
56 std::string offset = frames[frameIdx]["offset"].asString();
57 std::string pc = frames[frameIdx]["pc"].asString();
58 std::string symbol = frames[frameIdx]["symbol"].asString();
59 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, frameIdx, pc.c_str(),
60 file.empty() ? "Unknown" : file.c_str()) <= 0) {
61 return false;
62 }
63 outStr = std::string(buf, strlen(buf));
64 if (!symbol.empty()) {
65 outStr.append("(" + symbol + "+" + offset + ")");
66 }
67 if (!buildId.empty()) {
68 outStr.append("(" + buildId + ")");
69 }
70 return true;
71 }
72 }
73
FormatJsonStack(std::string jsonStack,std::string & outStackStr)74 bool DfxJsonFormatter::FormatJsonStack(std::string jsonStack, std::string& outStackStr)
75 {
76 Json::Reader reader;
77 Json::Value threads;
78 if (!(reader.parse(jsonStack, threads))) {
79 outStackStr.append("Failed to parse json stack info.");
80 return false;
81 }
82
83 for (uint32_t i = 0; i < threads.size(); ++i) {
84 std::ostringstream ss;
85 Json::Value thread = threads[i];
86 if (thread["tid"].isConvertibleTo(Json::stringValue) &&
87 thread["thread_name"].isConvertibleTo(Json::stringValue)) {
88 ss << "Tid:" << thread["tid"].asString() << ", Name:" << thread["thread_name"].asString() << std::endl;
89 }
90 const Json::Value frames = thread["frames"];
91 for (uint32_t j = 0; j < frames.size(); ++j) {
92 std::string frameStr = "";
93 bool formatStatus = false;
94 if (frames[j]["line"].asString().empty()) {
95 formatStatus = FormatNativeFrame(frames, j, frameStr);
96 } else {
97 formatStatus = FormatJsFrame(frames, j, frameStr);
98 }
99 if (formatStatus) {
100 ss << frameStr << std::endl;
101 } else {
102 // Shall we try to print more information?
103 outStackStr.append("Frame info is illegal.");
104 return false;
105 }
106 }
107 outStackStr.append(ss.str());
108 }
109 return true;
110 }
111 #endif
112 } // namespace HiviewDFX
113 } // namespace OHOS
114