1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "log_parse.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include "string_util.h" 18020a203aSopenharmony_ci#include "tbox.h" 19020a203aSopenharmony_ci 20020a203aSopenharmony_ciusing namespace std; 21020a203aSopenharmony_cinamespace OHOS { 22020a203aSopenharmony_cinamespace HiviewDFX { 23020a203aSopenharmony_ciconst std::string LogParse::UNMATCHED_EXCEPTION = "UnMatchedException"; 24020a203aSopenharmony_ci 25020a203aSopenharmony_ci// some stack function is invalid, so it should be ignored 26020a203aSopenharmony_ciconst std::map<std::string, std::set<std::string>> LogParse::ignoreList_ = { 27020a203aSopenharmony_ci {"Level1", { 28020a203aSopenharmony_ci "libc.so", 29020a203aSopenharmony_ci "libc++.so", 30020a203aSopenharmony_ci "ld-musl-aarch64.so", 31020a203aSopenharmony_ci "libc_fdleak_debug.so", 32020a203aSopenharmony_ci "unknown", 33020a203aSopenharmony_ci "watchdog", 34020a203aSopenharmony_ci "kthread", 35020a203aSopenharmony_ci "rdr_system_error"} 36020a203aSopenharmony_ci }, 37020a203aSopenharmony_ci {"Level2", { 38020a203aSopenharmony_ci "libart.so", 39020a203aSopenharmony_ci "__switch_to", 40020a203aSopenharmony_ci "dump_backtrace", 41020a203aSopenharmony_ci "show_stack", 42020a203aSopenharmony_ci "dump_stack"} 43020a203aSopenharmony_ci }, 44020a203aSopenharmony_ci {"Level3", { 45020a203aSopenharmony_ci "panic"} 46020a203aSopenharmony_ci } 47020a203aSopenharmony_ci}; 48020a203aSopenharmony_ci 49020a203aSopenharmony_ci// it is key word in app crash log, it can replace complexed info which may have safe and privacy info 50020a203aSopenharmony_ciconst std::set<std::string> LogParse::exceptionList_ = { 51020a203aSopenharmony_ci "ArithmeticException", 52020a203aSopenharmony_ci "ArrayIndexOutOfBoundsException", 53020a203aSopenharmony_ci "ArrayStoreException", 54020a203aSopenharmony_ci "ClassCastException", 55020a203aSopenharmony_ci "ClassNotFoundException", 56020a203aSopenharmony_ci "CloneNotSupportedException", 57020a203aSopenharmony_ci "EnumConstantNotPresentException", 58020a203aSopenharmony_ci "IllegalAccessException", 59020a203aSopenharmony_ci "IllegalArgumentException", 60020a203aSopenharmony_ci "IllegalMonitorStateException", 61020a203aSopenharmony_ci "IllegalStateException", 62020a203aSopenharmony_ci "IllegalThreadStateException", 63020a203aSopenharmony_ci "IndexOutOfBoundsException", 64020a203aSopenharmony_ci "InstantiationException", 65020a203aSopenharmony_ci "InterruptedException", 66020a203aSopenharmony_ci "NegativeArraySizeException", 67020a203aSopenharmony_ci "NoSuchFieldException", 68020a203aSopenharmony_ci "NoSuchMethodException", 69020a203aSopenharmony_ci "NullPointerException", 70020a203aSopenharmony_ci "NumberFormatException", 71020a203aSopenharmony_ci "ReflectiveOperationException", 72020a203aSopenharmony_ci "RuntimeException", 73020a203aSopenharmony_ci "SecurityException", 74020a203aSopenharmony_ci "StringIndexOutOfBoundsException" 75020a203aSopenharmony_ci}; 76020a203aSopenharmony_ci 77020a203aSopenharmony_cibool LogParse::IsIgnoreLibrary(const string& val) const 78020a203aSopenharmony_ci{ 79020a203aSopenharmony_ci for (auto list : ignoreList_) { 80020a203aSopenharmony_ci for (auto str : list.second) { 81020a203aSopenharmony_ci if (val.find(str, 0) != string::npos) { 82020a203aSopenharmony_ci return true; 83020a203aSopenharmony_ci } 84020a203aSopenharmony_ci } 85020a203aSopenharmony_ci } 86020a203aSopenharmony_ci return false; 87020a203aSopenharmony_ci} 88020a203aSopenharmony_ci 89020a203aSopenharmony_ci/* 90020a203aSopenharmony_ci * Remove ignored backtrace 91020a203aSopenharmony_ci * inStack : inverted sequence with fault log 92020a203aSopenharmony_ci * outStack : filter stack 93020a203aSopenharmony_ci */ 94020a203aSopenharmony_cibool LogParse::GetValidStack(int num, stack<string>& inStack, stack<string>& outStack) const 95020a203aSopenharmony_ci{ 96020a203aSopenharmony_ci vector<string> validStack; 97020a203aSopenharmony_ci size_t count = static_cast<size_t>(num); 98020a203aSopenharmony_ci // count < 1: indicate stack is empty 99020a203aSopenharmony_ci if (count < 1 || inStack.empty()) { 100020a203aSopenharmony_ci return false; 101020a203aSopenharmony_ci } 102020a203aSopenharmony_ci 103020a203aSopenharmony_ci // Automatically checks if it is a stack 104020a203aSopenharmony_ci bool iStack = Tbox::IsCallStack(inStack.top()); 105020a203aSopenharmony_ci if (iStack) { 106020a203aSopenharmony_ci validStack = GetValidStack(count, inStack); 107020a203aSopenharmony_ci } 108020a203aSopenharmony_ci outStack = GetStackTop(validStack, count); 109020a203aSopenharmony_ci return true; 110020a203aSopenharmony_ci} 111020a203aSopenharmony_ci 112020a203aSopenharmony_cistack<string> LogParse::GetStackTop(const vector<string>& validStack, const size_t num) const 113020a203aSopenharmony_ci{ 114020a203aSopenharmony_ci size_t len = validStack.size(); 115020a203aSopenharmony_ci stack<string> stackTop; 116020a203aSopenharmony_ci for (size_t i = 0; i < len; i++) { 117020a203aSopenharmony_ci if (i == 0 || len - i < num) { 118020a203aSopenharmony_ci stackTop.push(validStack.at(i)); 119020a203aSopenharmony_ci } 120020a203aSopenharmony_ci } 121020a203aSopenharmony_ci return stackTop; 122020a203aSopenharmony_ci} 123020a203aSopenharmony_ci 124020a203aSopenharmony_cilist<vector<string>> LogParse::StackToMultipart(stack<string>& inStack, size_t num) const 125020a203aSopenharmony_ci{ 126020a203aSopenharmony_ci stack<string> partStack; 127020a203aSopenharmony_ci vector<string> validPart; 128020a203aSopenharmony_ci list<vector<string>> multiPart; 129020a203aSopenharmony_ci while (!inStack.empty()) { 130020a203aSopenharmony_ci string topStr = inStack.top(); 131020a203aSopenharmony_ci StringUtil::EraseString(topStr, "\t"); 132020a203aSopenharmony_ci if (Tbox::HasCausedBy(topStr)) { 133020a203aSopenharmony_ci topStr = MatchExceptionLibrary(topStr); 134020a203aSopenharmony_ci if (!partStack.empty()) { 135020a203aSopenharmony_ci validPart = GetValidStack(num, partStack); 136020a203aSopenharmony_ci } 137020a203aSopenharmony_ci validPart.insert(validPart.begin(), topStr); 138020a203aSopenharmony_ci multiPart.push_back(validPart); 139020a203aSopenharmony_ci partStack = stack<string>(); 140020a203aSopenharmony_ci validPart.clear(); 141020a203aSopenharmony_ci inStack.pop(); 142020a203aSopenharmony_ci continue; 143020a203aSopenharmony_ci } 144020a203aSopenharmony_ci partStack.push(topStr); 145020a203aSopenharmony_ci inStack.pop(); 146020a203aSopenharmony_ci } 147020a203aSopenharmony_ci if (!partStack.empty()) { 148020a203aSopenharmony_ci validPart = GetValidStack(num, partStack); 149020a203aSopenharmony_ci multiPart.push_back(validPart); 150020a203aSopenharmony_ci } 151020a203aSopenharmony_ci return multiPart; 152020a203aSopenharmony_ci} 153020a203aSopenharmony_ci 154020a203aSopenharmony_cistring LogParse::GetValidBlock(stack<string> inStack, vector<string>& lastPart) const 155020a203aSopenharmony_ci{ 156020a203aSopenharmony_ci vector<string> validStack; 157020a203aSopenharmony_ci 158020a203aSopenharmony_ci list<vector<string>> multiPart = StackToMultipart(inStack, 3); // 3 : first/second/last frame 159020a203aSopenharmony_ci size_t size = multiPart.size(); 160020a203aSopenharmony_ci if (size == 0) { 161020a203aSopenharmony_ci return ""; 162020a203aSopenharmony_ci } 163020a203aSopenharmony_ci if (size == 1) { 164020a203aSopenharmony_ci // only one part 165020a203aSopenharmony_ci validStack = multiPart.front(); 166020a203aSopenharmony_ci if (validStack.size() > STACK_LEN_MAX) { 167020a203aSopenharmony_ci // keep the begin 28 lines and the end 2 lines 168020a203aSopenharmony_ci validStack.erase(validStack.begin() + (STACK_LEN_MAX - 2), validStack.end() - 2); // 2 : end 2 lines 169020a203aSopenharmony_ci } 170020a203aSopenharmony_ci } else if (size >= 2) { // at least 2 parts 171020a203aSopenharmony_ci for (auto part : multiPart) { 172020a203aSopenharmony_ci if (validStack.size() >= STACK_LEN_MAX) { 173020a203aSopenharmony_ci break; 174020a203aSopenharmony_ci } 175020a203aSopenharmony_ci validStack.insert(validStack.begin(), part.begin(), part.end()); 176020a203aSopenharmony_ci } 177020a203aSopenharmony_ci if (multiPart.front().size() > STACK_LEN_MAX) { 178020a203aSopenharmony_ci // keep the begin 28 lines and the end 2 lines 179020a203aSopenharmony_ci validStack.erase(validStack.begin() + (STACK_LEN_MAX - 2), validStack.end() - 2); // 2 : end 2 lines 180020a203aSopenharmony_ci } else if (validStack.size() > STACK_LEN_MAX) { 181020a203aSopenharmony_ci // keep the begin 2 lines and the end 28 lines 182020a203aSopenharmony_ci validStack.erase(validStack.begin() + 2, validStack.end() - (STACK_LEN_MAX - 2)); // 2 : begin 2 lines 183020a203aSopenharmony_ci } 184020a203aSopenharmony_ci } 185020a203aSopenharmony_ci 186020a203aSopenharmony_ci for (auto part : multiPart) { 187020a203aSopenharmony_ci // multiPart has at least 2 parts 188020a203aSopenharmony_ci if (size > 1 && !part.empty() && HasExceptionList(part.front())) { 189020a203aSopenharmony_ci part.erase(part.begin()); 190020a203aSopenharmony_ci } 191020a203aSopenharmony_ci // lastPart should has at least 3 lines 192020a203aSopenharmony_ci if (!part.empty()) { 193020a203aSopenharmony_ci reverse(part.begin(), part.end()); 194020a203aSopenharmony_ci lastPart = part; 195020a203aSopenharmony_ci break; 196020a203aSopenharmony_ci } 197020a203aSopenharmony_ci } 198020a203aSopenharmony_ci return Tbox::ARRAY_STR + StringUtil::VectorToString(validStack, false); 199020a203aSopenharmony_ci} 200020a203aSopenharmony_ci 201020a203aSopenharmony_civector<string> LogParse::GetValidStack(size_t num, stack<string>& inStack) const 202020a203aSopenharmony_ci{ 203020a203aSopenharmony_ci stack<string> src = inStack; 204020a203aSopenharmony_ci vector<string> validStack; 205020a203aSopenharmony_ci stack<string> outStatck; 206020a203aSopenharmony_ci string stackName; 207020a203aSopenharmony_ci size_t len = src.size(); 208020a203aSopenharmony_ci for (size_t i = 0; i < len; i++) { 209020a203aSopenharmony_ci stackName = Tbox::GetStackName(src.top()); // extract function name from the stack 210020a203aSopenharmony_ci if (!IsIgnoreLibrary(stackName)) { 211020a203aSopenharmony_ci validStack.push_back(stackName); 212020a203aSopenharmony_ci } 213020a203aSopenharmony_ci src.pop(); 214020a203aSopenharmony_ci } 215020a203aSopenharmony_ci if (validStack.empty()) { 216020a203aSopenharmony_ci MatchIgnoreLibrary(inStack, outStatck, num); 217020a203aSopenharmony_ci len = outStatck.size(); 218020a203aSopenharmony_ci for (size_t i = 0; i < len; i++) { 219020a203aSopenharmony_ci stackName = Tbox::GetStackName(outStatck.top()); 220020a203aSopenharmony_ci validStack.push_back(stackName); 221020a203aSopenharmony_ci outStatck.pop(); 222020a203aSopenharmony_ci } 223020a203aSopenharmony_ci } 224020a203aSopenharmony_ci return validStack; 225020a203aSopenharmony_ci} 226020a203aSopenharmony_ci 227020a203aSopenharmony_cistring LogParse::MatchExceptionLibrary(const string& val) 228020a203aSopenharmony_ci{ 229020a203aSopenharmony_ci for (auto& str : LogParse::exceptionList_) { 230020a203aSopenharmony_ci if (val.find(str, 0) != string::npos) { 231020a203aSopenharmony_ci return str; 232020a203aSopenharmony_ci } 233020a203aSopenharmony_ci } 234020a203aSopenharmony_ci return UNMATCHED_EXCEPTION; 235020a203aSopenharmony_ci} 236020a203aSopenharmony_ci 237020a203aSopenharmony_civoid LogParse::MatchIgnoreLibrary(stack<string> inStack, stack<string>& outStack, size_t num) const 238020a203aSopenharmony_ci{ 239020a203aSopenharmony_ci if (inStack.size() <= num) { 240020a203aSopenharmony_ci outStack = inStack; 241020a203aSopenharmony_ci return; 242020a203aSopenharmony_ci } 243020a203aSopenharmony_ci size_t count = 0; 244020a203aSopenharmony_ci for (auto it = ignoreList_.rbegin(); it != ignoreList_.rend(); ++it) { 245020a203aSopenharmony_ci if (count == ignoreList_.size() - 1) { 246020a203aSopenharmony_ci outStack = inStack; 247020a203aSopenharmony_ci return; 248020a203aSopenharmony_ci } 249020a203aSopenharmony_ci 250020a203aSopenharmony_ci stack<string> src = inStack; 251020a203aSopenharmony_ci while (src.size() > num) { 252020a203aSopenharmony_ci string name = src.top(); 253020a203aSopenharmony_ci for (auto str : it->second) { 254020a203aSopenharmony_ci if (name.find(str, 0) != string::npos) { 255020a203aSopenharmony_ci outStack = src; 256020a203aSopenharmony_ci return; 257020a203aSopenharmony_ci } 258020a203aSopenharmony_ci } 259020a203aSopenharmony_ci src.pop(); 260020a203aSopenharmony_ci } 261020a203aSopenharmony_ci count++; 262020a203aSopenharmony_ci } 263020a203aSopenharmony_ci} 264020a203aSopenharmony_ci 265020a203aSopenharmony_ci/* 266020a203aSopenharmony_ci * INPUT : 267020a203aSopenharmony_ci * info : trace spliting by "\n" 268020a203aSopenharmony_ci * OUTPUT : 269020a203aSopenharmony_ci * trace : last part trace to get Frame 270020a203aSopenharmony_ci * return string : valid trace spliting by "\n" 271020a203aSopenharmony_ci */ 272020a203aSopenharmony_cistd::string LogParse::GetFilterTrace(const std::string& info, std::vector<std::string>& trace, 273020a203aSopenharmony_ci std::string eventType) const 274020a203aSopenharmony_ci{ 275020a203aSopenharmony_ci std::string newInfo = info; 276020a203aSopenharmony_ci if (eventType == "JS_ERROR" && newInfo.find("libace_napi.z.so") != std::string::npos) { 277020a203aSopenharmony_ci newInfo = StringUtil::GetRightSubstr(info, "libace_napi.z.so"); 278020a203aSopenharmony_ci } 279020a203aSopenharmony_ci StringUtil::SplitStr(newInfo, "\n", trace, false, false); 280020a203aSopenharmony_ci std::stack<std::string> traceStack; 281020a203aSopenharmony_ci for (const auto& str : trace) { 282020a203aSopenharmony_ci traceStack.push(str); 283020a203aSopenharmony_ci } 284020a203aSopenharmony_ci trace.clear(); 285020a203aSopenharmony_ci return GetValidBlock(traceStack, trace); 286020a203aSopenharmony_ci} 287020a203aSopenharmony_ci 288020a203aSopenharmony_civoid LogParse::SetFrame(std::stack<std::string>& stack, std::map<std::string, std::string>& eventInfo) const 289020a203aSopenharmony_ci{ 290020a203aSopenharmony_ci std::vector<std::string> name = {"FIRST_FRAME", "SECOND_FRAME", "LAST_FRAME"}; 291020a203aSopenharmony_ci size_t len = stack.size(); 292020a203aSopenharmony_ci for (size_t i = 0; i < len; i++) { 293020a203aSopenharmony_ci if (eventInfo.find(name[i]) == eventInfo.end()) { 294020a203aSopenharmony_ci eventInfo[name[i]] = stack.top(); 295020a203aSopenharmony_ci } 296020a203aSopenharmony_ci stack.pop(); 297020a203aSopenharmony_ci } 298020a203aSopenharmony_ci} 299020a203aSopenharmony_ci 300020a203aSopenharmony_cibool LogParse::HasExceptionList(const string& line) const 301020a203aSopenharmony_ci{ 302020a203aSopenharmony_ci auto iter = exceptionList_.find(line); 303020a203aSopenharmony_ci if (line == UNMATCHED_EXCEPTION || iter != exceptionList_.end()) { 304020a203aSopenharmony_ci return true; 305020a203aSopenharmony_ci } 306020a203aSopenharmony_ci return false; 307020a203aSopenharmony_ci} 308020a203aSopenharmony_ci} 309020a203aSopenharmony_ci}