/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Description: KernelSymbolsParser class implements */ #include "kernel_symbols_parser.h" #include "file_utils.h" #include "logging.h" #include "string_utils.h" #include // for std::sort #include // for std::stringstream namespace { constexpr int ADDR_VALUE_BASE = 16; } // namespace FTRACE_NS_BEGIN KernelSymbolsParser::KernelSymbolsParser() { HILOG_INFO(LOG_CORE, "KernelSymbolsParser create!"); } KernelSymbolsParser::~KernelSymbolsParser() { HILOG_INFO(LOG_CORE, "KernelSymbolsParser destroy!"); } void KernelSymbolsParser::Accept(const std::function& visitor) { std::for_each(kernelSymbols_.begin(), kernelSymbols_.end(), visitor); } bool KernelSymbolsParser::IsValidTextSymbol(const KernelSymbol& a) { if (a.addr == 0 || a.name.empty()) { return false; } if (a.name[0] == '$') { return false; } if (a.type != 't' && a.type != 'T') { return false; } return true; } bool KernelSymbolsParser::CompareSymbolInfo(const KernelSymbol& a, const KernelSymbol& b) { if (a.addr != b.addr) { return a.addr < b.addr; } if (a.name != b.name) { return a.name < b.name; } return a.type < b.type; } bool KernelSymbolsParser::Parse(const std::string& kallsyms) { std::string line; std::stringstream sin(kallsyms); while (std::getline(sin, line)) { // one of following format: // c0109b3c T arm_elf_read_implies_exec // bf004fd8 t media_mem_init [hi_osal] std::stringstream ss(line); KernelSymbol info; std::string addrStr; if (ss >> addrStr >> info.type >> info.name) { info.addr = strtoull(addrStr.c_str(), nullptr, ADDR_VALUE_BASE); } if (info.addr == 0) { continue; } if (StringUtils::EndsWith(info.name, ".cfi")) { info.name = info.name.substr(0, info.name.size() - (sizeof(".cfi") - 1)); } if (IsValidTextSymbol(info)) { kernelSymbols_.emplace_back(std::move(info)); } } std::sort(kernelSymbols_.begin(), kernelSymbols_.end(), CompareSymbolInfo); kernelSymbols_.shrink_to_fit(); return kernelSymbols_.size(); } FTRACE_NS_END