1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "dfx_kernel_stack.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <dlfcn.h> 19800b99b8Sopenharmony_ci#include <fcntl.h> 20800b99b8Sopenharmony_ci#include <regex> 21800b99b8Sopenharmony_ci#include <string_ex.h> 22800b99b8Sopenharmony_ci#include <sys/ioctl.h> 23800b99b8Sopenharmony_ci#include <unistd.h> 24800b99b8Sopenharmony_ci 25800b99b8Sopenharmony_ci#include "dfx_log.h" 26800b99b8Sopenharmony_ci 27800b99b8Sopenharmony_ci#define LOGGER_GET_STACK _IO(0xAB, 9) 28800b99b8Sopenharmony_cinamespace OHOS { 29800b99b8Sopenharmony_cinamespace HiviewDFX { 30800b99b8Sopenharmony_cinamespace { 31800b99b8Sopenharmony_ci// keep sync with defines in kernel/hicollie 32800b99b8Sopenharmony_ciconst char* const BBOX_PATH = "/dev/bbox"; 33800b99b8Sopenharmony_ciconst int BUFF_STACK_SIZE = 20 * 1024; 34800b99b8Sopenharmony_ciconst uint32_t MAGIC_NUM = 0x9517; 35800b99b8Sopenharmony_citypedef struct HstackVal { 36800b99b8Sopenharmony_ci uint32_t magic {0}; 37800b99b8Sopenharmony_ci pid_t pid {0}; 38800b99b8Sopenharmony_ci char hstackLogBuff[BUFF_STACK_SIZE] {0}; 39800b99b8Sopenharmony_ci} HstackVal; 40800b99b8Sopenharmony_ci} 41800b99b8Sopenharmony_ciint DfxGetKernelStack(int32_t pid, std::string& kernelStack) 42800b99b8Sopenharmony_ci{ 43800b99b8Sopenharmony_ci auto kstackBuf = std::make_shared<HstackVal>(); 44800b99b8Sopenharmony_ci if (kstackBuf == nullptr) { 45800b99b8Sopenharmony_ci DFXLOGW("Failed create HstackVal, errno:%{public}d", errno); 46800b99b8Sopenharmony_ci return -1; 47800b99b8Sopenharmony_ci } 48800b99b8Sopenharmony_ci kstackBuf->pid = pid; 49800b99b8Sopenharmony_ci kstackBuf->magic = MAGIC_NUM; 50800b99b8Sopenharmony_ci int fd = open(BBOX_PATH, O_WRONLY | O_CLOEXEC); 51800b99b8Sopenharmony_ci if (fd < 0) { 52800b99b8Sopenharmony_ci DFXLOGW("Failed to open bbox, errno:%{public}d", errno); 53800b99b8Sopenharmony_ci return -1; 54800b99b8Sopenharmony_ci } 55800b99b8Sopenharmony_ci 56800b99b8Sopenharmony_ci int ret = ioctl(fd, LOGGER_GET_STACK, kstackBuf.get()); 57800b99b8Sopenharmony_ci if (ret != 0) { 58800b99b8Sopenharmony_ci DFXLOGW("Failed to get pid(%{public}d) kernel stack, errno:%{public}d", pid, errno); 59800b99b8Sopenharmony_ci } else { 60800b99b8Sopenharmony_ci kernelStack = std::string(kstackBuf->hstackLogBuff); 61800b99b8Sopenharmony_ci } 62800b99b8Sopenharmony_ci close(fd); 63800b99b8Sopenharmony_ci return ret; 64800b99b8Sopenharmony_ci} 65800b99b8Sopenharmony_ci 66800b99b8Sopenharmony_cibool FormatThreadKernelStack(const std::string& kernelStack, DfxThreadStack& threadStack) 67800b99b8Sopenharmony_ci{ 68800b99b8Sopenharmony_ci#ifdef __aarch64__ 69800b99b8Sopenharmony_ci std::regex headerPattern(R"(name=(.{1,20}), tid=(\d{1,10}), ([\w\=\.]{1,256}, ){3}pid=(\d{1,10}))"); 70800b99b8Sopenharmony_ci std::smatch result; 71800b99b8Sopenharmony_ci if (!regex_search(kernelStack, result, headerPattern)) { 72800b99b8Sopenharmony_ci DFXLOGI("search thread name failed"); 73800b99b8Sopenharmony_ci return false; 74800b99b8Sopenharmony_ci } 75800b99b8Sopenharmony_ci threadStack.threadName = result[1].str(); 76800b99b8Sopenharmony_ci int base {10}; 77800b99b8Sopenharmony_ci threadStack.tid = strtol(result[2].str().c_str(), nullptr, base); // 2 : second of searched element 78800b99b8Sopenharmony_ci auto pos = kernelStack.rfind("pid=" + result[result.size() - 1].str()); 79800b99b8Sopenharmony_ci if (pos == std::string::npos) { 80800b99b8Sopenharmony_ci return false; 81800b99b8Sopenharmony_ci } 82800b99b8Sopenharmony_ci size_t index = 0; 83800b99b8Sopenharmony_ci std::regex framePattern(R"(\[(\w{16})\]\<[\w\?+/]{1,1024}\> \(([\w\-./]{1,1024})\))"); 84800b99b8Sopenharmony_ci for (std::sregex_iterator it = std::sregex_iterator(kernelStack.begin() + pos, kernelStack.end(), framePattern); 85800b99b8Sopenharmony_ci it != std::sregex_iterator(); ++it) { 86800b99b8Sopenharmony_ci if ((*it)[2].str().rfind(".elf") != std::string::npos) { // 2 : second of searched element is map name 87800b99b8Sopenharmony_ci continue; 88800b99b8Sopenharmony_ci } 89800b99b8Sopenharmony_ci DfxFrame frame; 90800b99b8Sopenharmony_ci frame.index = index++; 91800b99b8Sopenharmony_ci base = 16; // 16 : Hexadecimal 92800b99b8Sopenharmony_ci frame.relPc = strtoull((*it)[1].str().c_str(), nullptr, base); 93800b99b8Sopenharmony_ci frame.mapName = (*it)[2].str(); // 2 : second of searched element is map name 94800b99b8Sopenharmony_ci threadStack.frames.emplace_back(frame); 95800b99b8Sopenharmony_ci } 96800b99b8Sopenharmony_ci return true; 97800b99b8Sopenharmony_ci#else 98800b99b8Sopenharmony_ci return false; 99800b99b8Sopenharmony_ci#endif 100800b99b8Sopenharmony_ci} 101800b99b8Sopenharmony_ci 102800b99b8Sopenharmony_cibool FormatProcessKernelStack(const std::string& kernelStack, std::vector<DfxThreadStack>& processStack) 103800b99b8Sopenharmony_ci{ 104800b99b8Sopenharmony_ci#ifdef __aarch64__ 105800b99b8Sopenharmony_ci std::vector<std::string> threadKernelStackVec; 106800b99b8Sopenharmony_ci OHOS::SplitStr(kernelStack, "Thread info:", threadKernelStackVec); 107800b99b8Sopenharmony_ci if (threadKernelStackVec.size() == 1) { 108800b99b8Sopenharmony_ci return false; 109800b99b8Sopenharmony_ci } 110800b99b8Sopenharmony_ci for (const std::string& threadKernelStack : threadKernelStackVec) { 111800b99b8Sopenharmony_ci DfxThreadStack threadStack; 112800b99b8Sopenharmony_ci if (FormatThreadKernelStack(threadKernelStack, threadStack)) { 113800b99b8Sopenharmony_ci processStack.emplace_back(threadStack); 114800b99b8Sopenharmony_ci } 115800b99b8Sopenharmony_ci } 116800b99b8Sopenharmony_ci return true; 117800b99b8Sopenharmony_ci#else 118800b99b8Sopenharmony_ci return false; 119800b99b8Sopenharmony_ci#endif 120800b99b8Sopenharmony_ci} 121800b99b8Sopenharmony_ci} 122800b99b8Sopenharmony_ci}