1/* 2 * Copyright (c) 2023 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#ifndef STACK_UTIL_H 16#define STACK_UTIL_H 17 18#include <cstdio> 19#include <csignal> 20#include <cstring> 21#include <string> 22#include <pthread.h> 23#include "dfx_define.h" 24 25namespace OHOS { 26namespace HiviewDFX { 27namespace { 28static uintptr_t g_stackMapStart = 0; 29static uintptr_t g_stackMapEnd = 0; 30static uintptr_t g_arkMapStart = 0; 31static uintptr_t g_arkMapEnd = 0; 32 33static bool ParseSelfMaps() 34{ 35 FILE *fp = fopen(PROC_SELF_MAPS_PATH, "r"); 36 if (fp == NULL) { 37 return false; 38 } 39 bool ret = false; 40 char mapInfo[256] = {0}; // 256: map info size 41 int pos = 0; 42 uint64_t begin = 0; 43 uint64_t end = 0; 44 uint64_t offset = 0; 45 char perms[5] = {0}; // 5:rwxp 46 while (fgets(mapInfo, sizeof(mapInfo), fp) != NULL) { 47 if (strstr(mapInfo, "[stack]") != NULL) { 48 if (sscanf_s(mapInfo, "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %*x:%*x %*d%n", &begin, &end, 49 &perms, sizeof(perms), &offset, &pos) != 4) { // 4:scan size 50 continue; 51 } 52 g_stackMapStart = static_cast<uintptr_t>(begin); 53 g_stackMapEnd = static_cast<uintptr_t>(end); 54 ret = true; 55 } 56 57 if (strstr(mapInfo, "stub.an") != NULL) { 58 if (sscanf_s(mapInfo, "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %*x:%*x %*d%n", &begin, &end, 59 &perms, sizeof(perms), &offset, &pos) != 4) { // 4:scan size 60 continue; 61 } 62 g_arkMapStart = static_cast<uintptr_t>(begin); 63 g_arkMapEnd = static_cast<uintptr_t>(end); 64 ret = true; 65 } 66 } 67 (void)fclose(fp); 68 return ret; 69}; 70} 71 72AT_UNUSED inline bool GetArkStackRange(uintptr_t& start, uintptr_t& end) 73{ 74 if (g_arkMapStart == 0 || g_arkMapEnd == 0) { 75 ParseSelfMaps(); 76 } 77 start = g_arkMapStart; 78 end = g_arkMapEnd; 79 return (g_arkMapStart != 0 && g_arkMapEnd != 0); 80} 81 82AT_UNUSED inline bool GetMainStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) 83{ 84 if (g_stackMapStart == 0 || g_stackMapEnd == 0) { 85 ParseSelfMaps(); 86 } 87 stackBottom = g_stackMapStart; 88 stackTop = g_stackMapEnd; 89 return (g_stackMapStart != 0 && g_stackMapEnd != 0); 90} 91 92AT_UNUSED static bool GetSelfStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) 93{ 94 bool ret = false; 95 pthread_attr_t tattr; 96 void *base = nullptr; 97 size_t size = 0; 98 if (pthread_getattr_np(pthread_self(), &tattr) != 0) { 99 return ret; 100 } 101 if (pthread_attr_getstack(&tattr, &base, &size) == 0) { 102 stackBottom = reinterpret_cast<uintptr_t>(base); 103 stackTop = reinterpret_cast<uintptr_t>(base) + size; 104 ret = true; 105 } 106 pthread_attr_destroy(&tattr); 107 return ret; 108} 109 110AT_UNUSED static bool GetSigAltStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) 111{ 112 bool ret = false; 113 stack_t altStack; 114 if (sigaltstack(nullptr, &altStack) != -1) { 115 if ((static_cast<uint32_t>(altStack.ss_flags) & SS_ONSTACK) != 0) { 116 stackBottom = reinterpret_cast<uintptr_t>(altStack.ss_sp); 117 stackTop = reinterpret_cast<uintptr_t>(altStack.ss_sp) + altStack.ss_size; 118 ret = true; 119 } 120 } 121 return ret; 122} 123} // namespace HiviewDFX 124} // namespace OHOS 125#endif 126