1 /*
2 * Copyright (c) 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 "process_dump_config.h"
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <map>
21 #include <mutex>
22 #include <securec.h>
23 #include <string>
24 #ifndef is_ohos_lite
25 #include "cJSON.h"
26 #endif
27 #include "dfx_define.h"
28 #include "dfx_log.h"
29 #include "file_ex.h"
30 #include "string_util.h"
31
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace {
35 #undef LOG_DOMAIN
36 #undef LOG_TAG
37 #define LOG_DOMAIN 0xD002D11
38 #define LOG_TAG "ProcessDumpConfig"
39
40 const char* const KEY_THREAD_DUMP_INFO = "KeyThreadDumpInfo";
41 const char* const DUMP_INFO_HEADER = "DumpInfoHeader";
42 const char* const SUBMITTER_STACK = "SubmitterStack";
43 const char* const REGISTERS = "Registers";
44 const char* const EXTRA_CRASH_INFO = "ExtraCrashInfo";
45 const char* const OTHER_THREAD_DUMP_INFO = "OtherThreadDumpInfo";
46 const char* const MEMORY_NEAR_REGISTER = "MemoryNearRegister";
47 const char* const FAULT_STACK = "FaultStack";
48 const char* const MAPS = "Maps";
49 const char* const OPEN_FILES = "OpenFiles";
50 #ifndef is_ohos_lite
51 constexpr int32_t MAX_NUM_INT32 = std::numeric_limits<int32_t>::max();
52 const char* const DUMP_INFO_COMPONENT_NAME[] = {
53 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, SUBMITTER_STACK, REGISTERS, EXTRA_CRASH_INFO,
54 OTHER_THREAD_DUMP_INFO, MEMORY_NEAR_REGISTER, FAULT_STACK, MAPS, OPEN_FILES,
55 };
56 const char* const PROCESS_DUMP_CONF_PATH = "/system/etc/faultlogger.conf";
GetStringValueFromJson(const cJSON * json,std::string defaultValue="")57 std::string GetStringValueFromJson(const cJSON* json, std::string defaultValue = "")
58 {
59 if (!cJSON_IsString(json)) {
60 return defaultValue;
61 }
62 return json->valuestring;
63 }
64
GetInt32ValueFromJson(const cJSON * json,int32_t defaultValue=0)65 int32_t GetInt32ValueFromJson(const cJSON* json, int32_t defaultValue = 0)
66 {
67 if (!cJSON_IsNumber(json)) {
68 return defaultValue;
69 }
70 return json->valueint;
71 }
72
GetBoolValueFromJson(const cJSON * json,bool defaultValue=false)73 bool GetBoolValueFromJson(const cJSON* json, bool defaultValue = false)
74 {
75 if (!cJSON_IsBool(json)) {
76 return defaultValue;
77 }
78 return cJSON_IsTrue(json) == 1;
79 }
80
ParseDumpInfoConfig(const cJSON * json,DumpConfig & dumpConfig)81 void ParseDumpInfoConfig(const cJSON* json, DumpConfig& dumpConfig)
82 {
83 auto* dumpInfos = cJSON_GetObjectItem(json, "DumpInfos");
84 if (dumpInfos == nullptr) {
85 DFXLOGE("Failed to Parse Dump Info Config!");
86 return;
87 }
88 if (!cJSON_IsArray(dumpInfos)) {
89 DFXLOGE("dumpInfos is not array!");
90 return;
91 }
92 int size = cJSON_GetArraySize(dumpInfos);
93 for (int i = 0; i < size; i++) {
94 auto* dumpInfo = cJSON_GetArrayItem(dumpInfos, i);
95 int32_t code = GetInt32ValueFromJson(cJSON_GetObjectItem(dumpInfo, "Code"));
96 std::string typeName = GetStringValueFromJson(cJSON_GetObjectItem(dumpInfo, "TypeName"));
97 std::vector<std::string> dumpInfoComponent;
98 for (const auto& componentName : DUMP_INFO_COMPONENT_NAME) {
99 if (GetBoolValueFromJson(cJSON_GetObjectItem(dumpInfo, componentName))) {
100 dumpInfoComponent.emplace_back(componentName);
101 }
102 }
103 dumpConfig.dumpInfo[static_cast<ProcessDumpType>(code)] = dumpInfoComponent;
104 }
105 }
106
ParseConfig(const cJSON * json,DumpConfig & dumpConfig)107 void ParseConfig(const cJSON* json, DumpConfig& dumpConfig)
108 {
109 if (json == nullptr) {
110 DFXLOGE("failed to Parse directoryConfig");
111 return;
112 }
113 dumpConfig.maxFrameNums = std::clamp(
114 GetInt32ValueFromJson(cJSON_GetObjectItem(json, "maxFrameNums")), 0, MAX_NUM_INT32);
115 dumpConfig.faultStackLowAddrStep = std::clamp(
116 GetInt32ValueFromJson(cJSON_GetObjectItem(json, "faultStackLowAddrStep")), 0, MAX_NUM_INT32);
117 dumpConfig.faultStackHighAddrStep = std::clamp(
118 GetInt32ValueFromJson(cJSON_GetObjectItem(json, "faultStackHighAddrStep")), 0, MAX_NUM_INT32);
119 dumpConfig.extendPcLrPrinting = GetBoolValueFromJson(cJSON_GetObjectItem(json, "extendPcLrPrinting"));
120 dumpConfig.simplifyVmaPrinting = GetBoolValueFromJson(cJSON_GetObjectItem(json, "simplifyVmaPrinting"));
121 dumpConfig.reservedParseSymbolTime = std::clamp(
122 GetInt32ValueFromJson(cJSON_GetObjectItem(json, "reservedParseSymbolTime")), 0, MAX_NUM_INT32);
123 ParseDumpInfoConfig(json, dumpConfig);
124 }
125 #endif
126 }
127
GetInstance()128 ProcessDumpConfig& ProcessDumpConfig::GetInstance()
129 {
130 static ProcessDumpConfig processDumpConfig;
131 return processDumpConfig;
132 }
133
134 #ifndef is_ohos_lite
ProcessDumpConfig()135 ProcessDumpConfig::ProcessDumpConfig()
136 {
137 std::string content;
138 OHOS::LoadStringFromFile(PROCESS_DUMP_CONF_PATH, content);
139 cJSON* json = cJSON_Parse(content.c_str());
140 if (json == nullptr) {
141 DFXLOGE("failed to parse json from the content of file(%{public}s).", PROCESS_DUMP_CONF_PATH);
142 LoadDefaultConfig();
143 return;
144 }
145 ParseConfig(json, dumpConfig_);
146 cJSON_Delete(json);
147 }
148 #else
ProcessDumpConfig()149 ProcessDumpConfig::ProcessDumpConfig()
150 {
151 LoadDefaultConfig();
152 }
153 #endif
154
LoadDefaultConfig()155 void ProcessDumpConfig::LoadDefaultConfig()
156 {
157 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_CPP_CRASH] = {
158 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, SUBMITTER_STACK,
159 REGISTERS, EXTRA_CRASH_INFO, OTHER_THREAD_DUMP_INFO,
160 MEMORY_NEAR_REGISTER, FAULT_STACK, MAPS, OPEN_FILES,
161 };
162 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_DUMP_CATCH] = {
163 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, OTHER_THREAD_DUMP_INFO,
164 };
165 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_MEM_LEAK] = {
166 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, REGISTERS,
167 MEMORY_NEAR_REGISTER, FAULT_STACK, MAPS,
168 };
169 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_FDSAN] = {
170 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, REGISTERS,
171 MEMORY_NEAR_REGISTER, FAULT_STACK, MAPS, OPEN_FILES,
172 };
173 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_JEMALLOC] = {
174 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, REGISTERS,
175 MEMORY_NEAR_REGISTER, FAULT_STACK, MAPS,
176 };
177 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_BADFD] = {
178 KEY_THREAD_DUMP_INFO, DUMP_INFO_HEADER, REGISTERS,
179 MEMORY_NEAR_REGISTER, FAULT_STACK, MAPS, OPEN_FILES,
180 };
181 dumpConfig_.dumpInfo[ProcessDumpType::DUMP_TYPE_COREDUMP] = {
182 KEY_THREAD_DUMP_INFO, REGISTERS, OTHER_THREAD_DUMP_INFO,
183 };
184 }
185
GetConfig() const186 const DumpConfig& ProcessDumpConfig::GetConfig() const
187 {
188 return dumpConfig_;
189 }
190 } // namespace HiviewDFX
191 } // namespace OHOS
192