106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci 1606f6ba60Sopenharmony_ci#include "runtime_stack_range.h" 1706f6ba60Sopenharmony_ci 1806f6ba60Sopenharmony_ci#include <csignal> 1906f6ba60Sopenharmony_ci#include <cstring> 2006f6ba60Sopenharmony_ci#include <map> 2106f6ba60Sopenharmony_ci#include <sys/types.h> 2206f6ba60Sopenharmony_ci#include "get_thread_id.h" 2306f6ba60Sopenharmony_ci#include "utilities.h" 2406f6ba60Sopenharmony_ci 2506f6ba60Sopenharmony_cinamespace { 2606f6ba60Sopenharmony_ciconstexpr int BASE_MIN = 2; 2706f6ba60Sopenharmony_ciconstexpr int BASE_CENTRE = 10; 2806f6ba60Sopenharmony_ciconstexpr int BASE_MAX = 16; 2906f6ba60Sopenharmony_ci 3006f6ba60Sopenharmony_cistruct StackScope { 3106f6ba60Sopenharmony_ci const char* start; 3206f6ba60Sopenharmony_ci const char* end; 3306f6ba60Sopenharmony_ci}; 3406f6ba60Sopenharmony_cistruct StandardLibrary { 3506f6ba60Sopenharmony_ci StandardLibrary(uint64_t begin, uint64_t end, const std::string& name) 3606f6ba60Sopenharmony_ci : soBegin_(begin), soEnd_(end), name_(name) 3706f6ba60Sopenharmony_ci {} 3806f6ba60Sopenharmony_ci uint64_t soBegin_; 3906f6ba60Sopenharmony_ci uint64_t soEnd_; 4006f6ba60Sopenharmony_ci std::string name_; 4106f6ba60Sopenharmony_ci}; 4206f6ba60Sopenharmony_ci 4306f6ba60Sopenharmony_cistatic StackScope g_mainStack; 4406f6ba60Sopenharmony_cistatic std::map<std::string, StandardLibrary> g_stdLib; 4506f6ba60Sopenharmony_ci} // namespace 4606f6ba60Sopenharmony_ci 4706f6ba60Sopenharmony_cistatic void GetThreadRuntimeStackRange(const char** start, const char** end) 4806f6ba60Sopenharmony_ci{ 4906f6ba60Sopenharmony_ci *start = nullptr; 5006f6ba60Sopenharmony_ci *end = nullptr; 5106f6ba60Sopenharmony_ci pthread_t tid = pthread_self(); 5206f6ba60Sopenharmony_ci pthread_attr_t attr; 5306f6ba60Sopenharmony_ci if (pthread_getattr_np(tid, &attr) == 0) { 5406f6ba60Sopenharmony_ci size_t stackSize; 5506f6ba60Sopenharmony_ci if (pthread_attr_getstack(&attr, reinterpret_cast<void**>(const_cast<char**>(start)), &stackSize) == 0) { 5606f6ba60Sopenharmony_ci *end = *start + stackSize; 5706f6ba60Sopenharmony_ci } 5806f6ba60Sopenharmony_ci pthread_attr_destroy(&attr); 5906f6ba60Sopenharmony_ci } 6006f6ba60Sopenharmony_ci} 6106f6ba60Sopenharmony_ci 6206f6ba60Sopenharmony_cistatic long long CvtStrToInt(const char* str, int base) 6306f6ba60Sopenharmony_ci{ 6406f6ba60Sopenharmony_ci long long result = 0; 6506f6ba60Sopenharmony_ci if (base >= BASE_MIN && base <= BASE_CENTRE) { 6606f6ba60Sopenharmony_ci while (*str) { 6706f6ba60Sopenharmony_ci if (*str >= '0' && *str <= '0' + base - 1) { 6806f6ba60Sopenharmony_ci result = result * base + static_cast<long long>((*str) - '0'); 6906f6ba60Sopenharmony_ci } else { 7006f6ba60Sopenharmony_ci break; 7106f6ba60Sopenharmony_ci } 7206f6ba60Sopenharmony_ci ++str; 7306f6ba60Sopenharmony_ci } 7406f6ba60Sopenharmony_ci } else if (base > BASE_CENTRE && base <= BASE_MAX) { 7506f6ba60Sopenharmony_ci while (*str) { 7606f6ba60Sopenharmony_ci if (*str >= '0' && *str <= '0' + base - 1) { 7706f6ba60Sopenharmony_ci result = result * base + static_cast<long long>(*str) - '0'; 7806f6ba60Sopenharmony_ci } else if (*str >= 'a' && *str <= 'a' + base - 0x0a - 1) { 7906f6ba60Sopenharmony_ci result = result * base + static_cast<long long>(*str) - 'a' + 0x0a; 8006f6ba60Sopenharmony_ci } else if (*str >= 'A' && *str <= 'A' + base - 0x0a - 1) { 8106f6ba60Sopenharmony_ci result = result * base + static_cast<long long>(*str) - 'A' + 0x0a; 8206f6ba60Sopenharmony_ci } else { 8306f6ba60Sopenharmony_ci break; 8406f6ba60Sopenharmony_ci } 8506f6ba60Sopenharmony_ci ++str; 8606f6ba60Sopenharmony_ci } 8706f6ba60Sopenharmony_ci } else { 8806f6ba60Sopenharmony_ci result = 0; 8906f6ba60Sopenharmony_ci } 9006f6ba60Sopenharmony_ci return result; 9106f6ba60Sopenharmony_ci} 9206f6ba60Sopenharmony_ci 9306f6ba60Sopenharmony_cistatic int IsEmptyString(const std::string& str) 9406f6ba60Sopenharmony_ci{ 9506f6ba60Sopenharmony_ci size_t idx = 0; 9606f6ba60Sopenharmony_ci size_t size = str.size(); 9706f6ba60Sopenharmony_ci while (idx < size) { 9806f6ba60Sopenharmony_ci if (!isspace(static_cast<unsigned char>(str[idx])) && str[idx] != 0) { 9906f6ba60Sopenharmony_ci return 0; 10006f6ba60Sopenharmony_ci } 10106f6ba60Sopenharmony_ci ++idx; 10206f6ba60Sopenharmony_ci } 10306f6ba60Sopenharmony_ci return 1; 10406f6ba60Sopenharmony_ci} 10506f6ba60Sopenharmony_ci 10606f6ba60Sopenharmony_cistatic void GetAnUnlimitedLine(FILE* fp, std::string& buf) 10706f6ba60Sopenharmony_ci{ 10806f6ba60Sopenharmony_ci if (!fp) { 10906f6ba60Sopenharmony_ci buf.resize(0); 11006f6ba60Sopenharmony_ci return; 11106f6ba60Sopenharmony_ci } 11206f6ba60Sopenharmony_ci char* retLine = nullptr; 11306f6ba60Sopenharmony_ci if (buf.size() == 0) { 11406f6ba60Sopenharmony_ci buf.resize(INIT_LINE_SIZE); 11506f6ba60Sopenharmony_ci } 11606f6ba60Sopenharmony_ci 11706f6ba60Sopenharmony_ci int offset = 0; 11806f6ba60Sopenharmony_ci int length = 0; 11906f6ba60Sopenharmony_ci do { 12006f6ba60Sopenharmony_ci if (offset + length >= static_cast<int>(buf.size())) { 12106f6ba60Sopenharmony_ci buf.resize(buf.size() + INC_LINE_SIZE); 12206f6ba60Sopenharmony_ci } 12306f6ba60Sopenharmony_ci retLine = fgets(&buf[0] + offset, buf.size() - offset, fp); 12406f6ba60Sopenharmony_ci if (retLine == nullptr) { 12506f6ba60Sopenharmony_ci break; 12606f6ba60Sopenharmony_ci } 12706f6ba60Sopenharmony_ci length = static_cast<int>(strlen(&buf[0] + offset)); 12806f6ba60Sopenharmony_ci if (offset + length - 1 >= 0 && buf[offset + length - 1] == '\n') { 12906f6ba60Sopenharmony_ci break; 13006f6ba60Sopenharmony_ci } 13106f6ba60Sopenharmony_ci offset += length; 13206f6ba60Sopenharmony_ci } while (1); 13306f6ba60Sopenharmony_ci} 13406f6ba60Sopenharmony_ci 13506f6ba60Sopenharmony_cistatic bool IsLegalSoName(const std::string &fileName) 13606f6ba60Sopenharmony_ci{ 13706f6ba60Sopenharmony_ci if (fileName.front() == '[' or fileName.back() == ']' or 13806f6ba60Sopenharmony_ci std::strncmp(fileName.c_str(), "/dev/", sizeof("/dev/")) == 0 or 13906f6ba60Sopenharmony_ci std::strncmp(fileName.c_str(), "/memfd:", sizeof("/memfd:")) == 0 or 14006f6ba60Sopenharmony_ci std::strncmp(fileName.c_str(), "//anon", sizeof("//anon")) == 0) { 14106f6ba60Sopenharmony_ci return false; 14206f6ba60Sopenharmony_ci } 14306f6ba60Sopenharmony_ci return true; 14406f6ba60Sopenharmony_ci} 14506f6ba60Sopenharmony_ci 14606f6ba60Sopenharmony_cistatic void GetStandardLibraryRange(std::string& line) 14706f6ba60Sopenharmony_ci{ 14806f6ba60Sopenharmony_ci line.resize(strlen(line.c_str())); 14906f6ba60Sopenharmony_ci std::vector<std::string> mapTokens = OHOS::Developtools::NativeDaemon::StringSplit(line, " "); 15006f6ba60Sopenharmony_ci const std::string& soRange = mapTokens.front(); 15106f6ba60Sopenharmony_ci std::string& soName = mapTokens.back(); 15206f6ba60Sopenharmony_ci if (IsLegalSoName(soName)) { 15306f6ba60Sopenharmony_ci std::string::size_type concatPos = soRange.find('-'); 15406f6ba60Sopenharmony_ci uint64_t soStart = static_cast<uint64_t>(strtoll(soRange.c_str(), nullptr, BASE_MAX)); 15506f6ba60Sopenharmony_ci uint64_t soEnd = static_cast<uint64_t>(strtoll(soRange.c_str() + concatPos + 1, nullptr, BASE_MAX)); 15606f6ba60Sopenharmony_ci auto [iter, isExit] = g_stdLib.try_emplace(soName, StandardLibrary(soStart, soEnd, soName)); 15706f6ba60Sopenharmony_ci if (!isExit) { 15806f6ba60Sopenharmony_ci if (iter->second.soBegin_ > soStart) { 15906f6ba60Sopenharmony_ci iter->second.soBegin_ = soStart; 16006f6ba60Sopenharmony_ci } else if (iter->second.soEnd_ < soEnd) { 16106f6ba60Sopenharmony_ci iter->second.soEnd_ = soEnd; 16206f6ba60Sopenharmony_ci } 16306f6ba60Sopenharmony_ci } 16406f6ba60Sopenharmony_ci } 16506f6ba60Sopenharmony_ci} 16606f6ba60Sopenharmony_ci 16706f6ba60Sopenharmony_civoid GetMainThreadRuntimeStackRange(std::vector<std::pair<uint64_t, uint64_t>>& filterStaLibRange) 16806f6ba60Sopenharmony_ci{ 16906f6ba60Sopenharmony_ci std::string line; 17006f6ba60Sopenharmony_ci FILE* fp = fopen("/proc/self/maps", "re"); 17106f6ba60Sopenharmony_ci if (fp == nullptr) { 17206f6ba60Sopenharmony_ci return; 17306f6ba60Sopenharmony_ci } 17406f6ba60Sopenharmony_ci while (!feof(fp)) { 17506f6ba60Sopenharmony_ci line.clear(); 17606f6ba60Sopenharmony_ci GetAnUnlimitedLine(fp, line); 17706f6ba60Sopenharmony_ci if (IsEmptyString(line)) { 17806f6ba60Sopenharmony_ci continue; 17906f6ba60Sopenharmony_ci } 18006f6ba60Sopenharmony_ci if (line.find("[stack]") != std::string::npos) { 18106f6ba60Sopenharmony_ci std::string::size_type concatPos = line.find('-'); 18206f6ba60Sopenharmony_ci if (concatPos != std::string::npos) { 18306f6ba60Sopenharmony_ci g_mainStack.start = reinterpret_cast<char*>(CvtStrToInt(line.c_str(), BASE_MAX)); 18406f6ba60Sopenharmony_ci g_mainStack.end = reinterpret_cast<char*>(CvtStrToInt(line.c_str() + concatPos + 1, BASE_MAX)); 18506f6ba60Sopenharmony_ci } 18606f6ba60Sopenharmony_ci } else if (line.find("ld-musl") != std::string::npos || line.find("libc++") != std::string::npos) { 18706f6ba60Sopenharmony_ci GetStandardLibraryRange(line); 18806f6ba60Sopenharmony_ci } 18906f6ba60Sopenharmony_ci } 19006f6ba60Sopenharmony_ci if (fclose(fp) != 0) { 19106f6ba60Sopenharmony_ci printf("fclose failed.\n"); 19206f6ba60Sopenharmony_ci } 19306f6ba60Sopenharmony_ci for (const auto& [soName, stdLibrary]: g_stdLib) { 19406f6ba60Sopenharmony_ci filterStaLibRange.emplace_back(stdLibrary.soBegin_, stdLibrary.soEnd_); 19506f6ba60Sopenharmony_ci } 19606f6ba60Sopenharmony_ci} 19706f6ba60Sopenharmony_ci 19806f6ba60Sopenharmony_cistatic bool IfContained(const char* start, const char* end, const char* ptr) 19906f6ba60Sopenharmony_ci{ 20006f6ba60Sopenharmony_ci bool ret = (ptr >= start && ptr < end); 20106f6ba60Sopenharmony_ci return ret; 20206f6ba60Sopenharmony_ci} 20306f6ba60Sopenharmony_ci 20406f6ba60Sopenharmony_cistatic void GetRuntimeSigalAltStackRange(char** start, char** end) 20506f6ba60Sopenharmony_ci{ 20606f6ba60Sopenharmony_ci *start = nullptr; 20706f6ba60Sopenharmony_ci *end = nullptr; 20806f6ba60Sopenharmony_ci 20906f6ba60Sopenharmony_ci stack_t altStack; 21006f6ba60Sopenharmony_ci 21106f6ba60Sopenharmony_ci if (sigaltstack(nullptr, &altStack) != -1) { 21206f6ba60Sopenharmony_ci if ((altStack.ss_flags & SS_ONSTACK) != 0) { 21306f6ba60Sopenharmony_ci *start = reinterpret_cast<char*>(altStack.ss_sp); 21406f6ba60Sopenharmony_ci *end = reinterpret_cast<char*>(altStack.ss_sp) + altStack.ss_size; 21506f6ba60Sopenharmony_ci } 21606f6ba60Sopenharmony_ci } 21706f6ba60Sopenharmony_ci} 21806f6ba60Sopenharmony_ci 21906f6ba60Sopenharmony_cistatic bool IfSubThread(pid_t pid, pid_t tid) 22006f6ba60Sopenharmony_ci{ 22106f6ba60Sopenharmony_ci return pid != tid; 22206f6ba60Sopenharmony_ci} 22306f6ba60Sopenharmony_ci 22406f6ba60Sopenharmony_civoid GetRuntimeStackEnd(const char* stackptr, const char** end, pid_t pid, pid_t tid) 22506f6ba60Sopenharmony_ci{ 22606f6ba60Sopenharmony_ci const char* start = nullptr; 22706f6ba60Sopenharmony_ci *end = nullptr; 22806f6ba60Sopenharmony_ci bool isSubThread = IfSubThread(pid, tid); 22906f6ba60Sopenharmony_ci if (isSubThread) { 23006f6ba60Sopenharmony_ci GetThreadRuntimeStackRange(&start, end); 23106f6ba60Sopenharmony_ci } else { 23206f6ba60Sopenharmony_ci start = g_mainStack.start; 23306f6ba60Sopenharmony_ci *end = g_mainStack.end; 23406f6ba60Sopenharmony_ci } 23506f6ba60Sopenharmony_ci if (!IfContained(start, *end, stackptr)) { 23606f6ba60Sopenharmony_ci char *sigStackStart = nullptr; 23706f6ba60Sopenharmony_ci char *sigStackEnd = nullptr; 23806f6ba60Sopenharmony_ci GetRuntimeSigalAltStackRange(&sigStackStart, &sigStackEnd); 23906f6ba60Sopenharmony_ci if (IfContained(sigStackStart, sigStackEnd, stackptr)) { 24006f6ba60Sopenharmony_ci *end = sigStackEnd; 24106f6ba60Sopenharmony_ci } else if (!(!isSubThread && stackptr < *end)) { 24206f6ba60Sopenharmony_ci *end = nullptr; 24306f6ba60Sopenharmony_ci } 24406f6ba60Sopenharmony_ci } 24506f6ba60Sopenharmony_ci} 246