diff options
Diffstat (limited to 'simpleperf/utils.cpp')
-rw-r--r-- | simpleperf/utils.cpp | 143 |
1 files changed, 78 insertions, 65 deletions
diff --git a/simpleperf/utils.cpp b/simpleperf/utils.cpp index 069676a6..407c5f08 100644 --- a/simpleperf/utils.cpp +++ b/simpleperf/utils.cpp @@ -31,21 +31,13 @@ #include <android-base/file.h> #include <android-base/logging.h> -#include <android-base/parseint.h> #include <android-base/stringprintf.h> -#include <android-base/strings.h> #include <build/version.h> #include <7zCrc.h> #include <Xz.h> #include <XzCrc64.h> -namespace simpleperf { - -using android::base::ParseInt; -using android::base::Split; -using android::base::StringPrintf; - void OneTimeFreeAllocator::Clear() { for (auto& p : v_) { delete[] p; @@ -64,21 +56,21 @@ const char* OneTimeFreeAllocator::AllocateString(std::string_view s) { cur_ = p; end_ = p + alloc_size; } - memcpy(cur_, s.data(), s.size()); - cur_[s.size()] = '\0'; + strcpy(cur_, s.data()); const char* result = cur_; cur_ += size; return result; } + android::base::unique_fd FileHelper::OpenReadOnly(const std::string& filename) { - int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_BINARY)); - return android::base::unique_fd(fd); + int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_BINARY)); + return android::base::unique_fd(fd); } android::base::unique_fd FileHelper::OpenWriteOnly(const std::string& filename) { - int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_BINARY | O_CREAT, 0644)); - return android::base::unique_fd(fd); + int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_BINARY | O_CREAT, 0644)); + return android::base::unique_fd(fd); } std::unique_ptr<ArchiveHelper> ArchiveHelper::CreateInstance(const std::string& filename) { @@ -90,7 +82,7 @@ std::unique_ptr<ArchiveHelper> ArchiveHelper::CreateInstance(const std::string& // files than zip files in a process map. In order to detect invalid zip files fast, we add a // check of magic number here. Note that OpenArchiveFd() detects invalid zip files in a thorough // way, but it usually needs reading at least 64K file data. - static const char zip_preamble[] = {0x50, 0x4b, 0x03, 0x04}; + static const char zip_preamble[] = {0x50, 0x4b, 0x03, 0x04 }; char buf[4]; if (!android::base::ReadFully(fd, buf, 4) || memcmp(buf, zip_preamble, 4) != 0) { return nullptr; @@ -304,9 +296,12 @@ bool XzDecompress(const std::string& compressed_data, std::string* decompressed_ } static std::map<std::string, android::base::LogSeverity> log_severity_map = { - {"verbose", android::base::VERBOSE}, {"debug", android::base::DEBUG}, - {"info", android::base::INFO}, {"warning", android::base::WARNING}, - {"error", android::base::ERROR}, {"fatal", android::base::FATAL}, + {"verbose", android::base::VERBOSE}, + {"debug", android::base::DEBUG}, + {"info", android::base::INFO}, + {"warning", android::base::WARNING}, + {"error", android::base::ERROR}, + {"fatal", android::base::FATAL}, }; bool GetLogSeverity(const std::string& name, android::base::LogSeverity* severity) { auto it = log_severity_map.find(name); @@ -339,6 +334,47 @@ bool IsRoot() { return is_root == 1; } +bool ProcessKernelSymbols(std::string& symbol_data, + const std::function<bool(const KernelSymbol&)>& callback) { + char* p = &symbol_data[0]; + char* data_end = p + symbol_data.size(); + while (p < data_end) { + char* line_end = strchr(p, '\n'); + if (line_end != nullptr) { + *line_end = '\0'; + } + size_t line_size = (line_end != nullptr) ? (line_end - p) : (data_end - p); + // Parse line like: ffffffffa005c4e4 d __warned.41698 [libsas] + char name[line_size]; + char module[line_size]; + strcpy(module, ""); + + KernelSymbol symbol; + int ret = sscanf(p, "%" PRIx64 " %c %s%s", &symbol.addr, &symbol.type, name, module); + if (line_end != nullptr) { + *line_end = '\n'; + p = line_end + 1; + } else { + p = data_end; + } + if (ret >= 3) { + symbol.name = name; + size_t module_len = strlen(module); + if (module_len > 2 && module[0] == '[' && module[module_len - 1] == ']') { + module[module_len - 1] = '\0'; + symbol.module = &module[1]; + } else { + symbol.module = nullptr; + } + + if (callback(symbol)) { + return true; + } + } + } + return false; +} + size_t GetPageSize() { #if defined(__linux__) return sysconf(_SC_PAGE_SIZE); @@ -371,57 +407,34 @@ timeval SecondToTimeval(double time_in_sec) { constexpr int SIMPLEPERF_VERSION = 1; std::string GetSimpleperfVersion() { - return StringPrintf("%d.build.%s", SIMPLEPERF_VERSION, android::build::GetBuildNumber().c_str()); + return android::base::StringPrintf("%d.build.%s", SIMPLEPERF_VERSION, + android::build::GetBuildNumber().c_str()); } -// Parse a line like: 0,1-3, 5, 7-8 -std::optional<std::set<int>> GetCpusFromString(const std::string& s) { - std::string str; - for (char c : s) { - if (!isspace(c)) { - str += c; - } - } - std::set<int> cpus; - int cpu1; - int cpu2; - for (const std::string& p : Split(str, ",")) { - size_t split_pos = p.find('-'); - if (split_pos == std::string::npos) { - if (!ParseInt(p, &cpu1, 0)) { - LOG(ERROR) << "failed to parse cpu: " << p; - return std::nullopt; - } - cpus.insert(cpu1); - } else { - if (!ParseInt(p.substr(0, split_pos), &cpu1, 0) || - !ParseInt(p.substr(split_pos + 1), &cpu2, 0) || cpu1 > cpu2) { - LOG(ERROR) << "failed to parse cpu: " << p; - return std::nullopt; - } - while (cpu1 <= cpu2) { - cpus.insert(cpu1++); +std::vector<int> GetCpusFromString(const std::string& s) { + std::set<int> cpu_set; + bool have_dash = false; + const char* p = s.c_str(); + char* endp; + int last_cpu; + int cpu; + // Parse line like: 0,1-3, 5, 7-8 + while ((cpu = static_cast<int>(strtol(p, &endp, 10))) != 0 || endp != p) { + if (have_dash && !cpu_set.empty()) { + for (int t = last_cpu + 1; t < cpu; ++t) { + cpu_set.insert(t); } } - } - return cpus; -} - -std::optional<std::set<pid_t>> GetTidsFromString(const std::string& s, bool check_if_exists) { - std::set<pid_t> tids; - for (const auto& p : Split(s, ",")) { - int tid; - if (!ParseInt(p.c_str(), &tid, 0)) { - LOG(ERROR) << "Invalid tid '" << p << "'"; - return std::nullopt; - } - if (check_if_exists && !IsDir(StringPrintf("/proc/%d", tid))) { - LOG(ERROR) << "Non existing thread '" << tid << "'"; - return std::nullopt; + have_dash = false; + cpu_set.insert(cpu); + last_cpu = cpu; + p = endp; + while (!isdigit(*p) && *p != '\0') { + if (*p == '-') { + have_dash = true; + } + ++p; } - tids.insert(tid); } - return tids; + return std::vector<int>(cpu_set.begin(), cpu_set.end()); } - -} // namespace simpleperf |