blob: 4ae9164fbeb9d9784c273ed4814c559cf8714a70 [file] [log] [blame]
Yabin Cui67d3abd2015-04-16 15:26:31 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SIMPLE_PERF_UTILS_H_
18#define SIMPLE_PERF_UTILS_H_
19
20#include <stddef.h>
Thiébaud Weksteene7e750e2020-11-19 15:07:46 +010021#include <stdio.h>
Yabin Cui3e4c5952016-07-26 15:03:27 -070022#include <time.h>
Yabin Cuicc2e59e2015-08-21 14:23:43 -070023
Yabin Cui40eef9e2021-04-13 13:08:31 -070024#include <fstream>
Yabin Cui2a53ff32018-05-21 17:37:00 -070025#include <functional>
Yabin Cuie3ca9982020-10-16 13:16:26 -070026#include <optional>
Namhyung Kima5f1d422019-12-17 17:15:02 +090027#include <set>
Yabin Cui323e9452015-04-20 18:07:17 -070028#include <string>
Yabin Cui9759e1b2015-04-28 15:54:13 -070029#include <vector>
Yabin Cui67d3abd2015-04-16 15:26:31 -070030
Yabin Cui8f680f62016-03-18 18:47:43 -070031#include <android-base/logging.h>
Yabin Cuib1a885b2016-02-14 19:18:02 -080032#include <android-base/macros.h>
Yabin Cuia89a3742021-02-11 13:14:54 -080033#include <android-base/parseint.h>
34#include <android-base/strings.h>
Yabin Cui2a53ff32018-05-21 17:37:00 -070035#include <android-base/unique_fd.h>
Yabin Cuibe7ec662016-03-02 13:56:28 -080036#include <ziparchive/zip_archive.h>
Yabin Cuib1a885b2016-02-14 19:18:02 -080037
Yabin Cuifaa7b922021-01-11 17:35:57 -080038namespace simpleperf {
39
Yabin Cuicfdc7832023-03-02 15:35:01 -080040static constexpr size_t kKilobyte = 1024;
41static constexpr size_t kMegabyte = 1024 * kKilobyte;
42static constexpr uint64_t kGigabyte = 1024 * kMegabyte;
43
Evgeny Eltsin91dbae02020-08-27 15:46:09 +020044static inline uint64_t AlignDown(uint64_t value, uint64_t alignment) {
45 return value & ~(alignment - 1);
46}
47
Yabin Cuia7a0e502016-06-15 11:49:23 -070048static inline uint64_t Align(uint64_t value, uint64_t alignment) {
Evgeny Eltsin91dbae02020-08-27 15:46:09 +020049 return AlignDown(value + alignment - 1, alignment);
Yabin Cuia7a0e502016-06-15 11:49:23 -070050}
Yabin Cui67d3abd2015-04-16 15:26:31 -070051
Yabin Cuiffaa9122016-01-15 15:25:48 -080052#ifdef _WIN32
53#define CLOSE_ON_EXEC_MODE ""
Yabin Cui1b9b1c12018-10-29 14:23:48 -070054#define OS_PATH_SEPARATOR '\\'
Yabin Cuiffaa9122016-01-15 15:25:48 -080055#else
56#define CLOSE_ON_EXEC_MODE "e"
Yabin Cui1b9b1c12018-10-29 14:23:48 -070057#define OS_PATH_SEPARATOR '/'
Yabin Cuiffaa9122016-01-15 15:25:48 -080058#endif
Yabin Cui621a5332015-06-15 16:17:20 -070059
Yabin Cuicc2e59e2015-08-21 14:23:43 -070060// OneTimeAllocator is used to allocate memory many times and free only once at the end.
61// It reduces the cost to free each allocated memory.
62class OneTimeFreeAllocator {
63 public:
Chih-Hung Hsieh5674ed82016-07-12 11:35:16 -070064 explicit OneTimeFreeAllocator(size_t unit_size = 8192u)
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020065 : unit_size_(unit_size), cur_(nullptr), end_(nullptr) {}
Yabin Cuicc2e59e2015-08-21 14:23:43 -070066
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020067 ~OneTimeFreeAllocator() { Clear(); }
Yabin Cuicc2e59e2015-08-21 14:23:43 -070068
69 void Clear();
Martin Stjernholm7c27cc22018-11-28 00:46:00 +000070 const char* AllocateString(std::string_view s);
Yabin Cuicc2e59e2015-08-21 14:23:43 -070071
72 private:
73 const size_t unit_size_;
74 std::vector<char*> v_;
75 char* cur_;
76 char* end_;
77};
78
Thiébaud Weksteene7e750e2020-11-19 15:07:46 +010079class LineReader {
80 public:
Yi Kong73a50212024-05-24 10:07:18 +090081 explicit LineReader(std::string_view file_path) : ifs_(std::string(file_path).c_str()) {}
Yabin Cui40eef9e2021-04-13 13:08:31 -070082 // Return true if open file successfully.
83 bool Ok() const { return ifs_.good(); }
84 // If available, return next line content with new line, otherwise return nullptr.
85 std::string* ReadLine() { return (std::getline(ifs_, buf_)) ? &buf_ : nullptr; }
Thiébaud Weksteene7e750e2020-11-19 15:07:46 +010086
87 private:
Yabin Cui40eef9e2021-04-13 13:08:31 -070088 std::ifstream ifs_;
89 std::string buf_;
Thiébaud Weksteene7e750e2020-11-19 15:07:46 +010090};
91
Yabin Cuib1a885b2016-02-14 19:18:02 -080092class FileHelper {
93 public:
Yabin Cui2a53ff32018-05-21 17:37:00 -070094 static android::base::unique_fd OpenReadOnly(const std::string& filename);
95 static android::base::unique_fd OpenWriteOnly(const std::string& filename);
Yabin Cuib1a885b2016-02-14 19:18:02 -080096};
97
Yabin Cuibe7ec662016-03-02 13:56:28 -080098class ArchiveHelper {
99 public:
Yabin Cui2a53ff32018-05-21 17:37:00 -0700100 static std::unique_ptr<ArchiveHelper> CreateInstance(const std::string& filename);
Yabin Cuibe7ec662016-03-02 13:56:28 -0800101 ~ArchiveHelper();
Yabin Cui2a53ff32018-05-21 17:37:00 -0700102 // Iterate each entry in the zip file. Break the iteration when callback returns false.
103 bool IterateEntries(const std::function<bool(ZipEntry&, const std::string&)>& callback);
104 bool FindEntry(const std::string& name, ZipEntry* entry);
105 bool GetEntryData(ZipEntry& entry, std::vector<uint8_t>* data);
106 int GetFd();
Yabin Cuibe7ec662016-03-02 13:56:28 -0800107
108 private:
Yabin Cui2a53ff32018-05-21 17:37:00 -0700109 ArchiveHelper(ZipArchiveHandle handle, const std::string& filename)
110 : handle_(handle), filename_(filename) {}
111
Yabin Cuibe7ec662016-03-02 13:56:28 -0800112 ZipArchiveHandle handle_;
Yabin Cui2a53ff32018-05-21 17:37:00 -0700113 std::string filename_;
Yabin Cuibe7ec662016-03-02 13:56:28 -0800114
115 DISALLOW_COPY_AND_ASSIGN(ArchiveHelper);
116};
117
Yabin Cuid713f952015-06-23 18:50:36 -0700118template <class T>
119void MoveFromBinaryFormat(T& data, const char*& p) {
Yabin Cui2597ef02016-10-19 11:28:48 -0700120 static_assert(std::is_standard_layout<T>::value, "not standard layout");
Yabin Cuic24dd762016-11-10 15:25:15 -0800121 memcpy(&data, p, sizeof(T));
Yabin Cuid713f952015-06-23 18:50:36 -0700122 p += sizeof(T);
123}
124
Yabin Cui2597ef02016-10-19 11:28:48 -0700125template <class T>
Yabin Cui3d4aa262017-11-01 15:58:55 -0700126void MoveFromBinaryFormat(T& data, char*& p) {
127 static_assert(std::is_standard_layout<T>::value, "not standard layout");
128 memcpy(&data, p, sizeof(T));
129 p += sizeof(T);
130}
131
132template <class T>
Yabin Cui2597ef02016-10-19 11:28:48 -0700133void MoveFromBinaryFormat(T* data_p, size_t n, const char*& p) {
134 static_assert(std::is_standard_layout<T>::value, "not standard layout");
135 size_t size = n * sizeof(T);
136 memcpy(data_p, p, size);
137 p += size;
138}
139
140template <class T>
141void MoveToBinaryFormat(const T& data, char*& p) {
142 static_assert(std::is_standard_layout<T>::value, "not standard layout");
Yabin Cuic24dd762016-11-10 15:25:15 -0800143 memcpy(p, &data, sizeof(T));
Yabin Cui2597ef02016-10-19 11:28:48 -0700144 p += sizeof(T);
145}
146
147template <class T>
148void MoveToBinaryFormat(const T* data_p, size_t n, char*& p) {
149 static_assert(std::is_standard_layout<T>::value, "not standard layout");
150 size_t size = n * sizeof(T);
151 memcpy(p, data_p, size);
152 p += size;
153}
154
Yabin Cui540932c2022-09-13 15:52:33 -0700155// Read info from binary data.
156struct BinaryReader {
157 public:
158 BinaryReader(const char* head, size_t size) : head(head), end(head + size), error(false) {}
159
160 size_t LeftSize() const { return end - head; }
161
162 bool CheckLeftSize(size_t size) {
163 if (UNLIKELY(error)) {
164 return false;
165 }
166 if (UNLIKELY(LeftSize() < size)) {
167 error = true;
168 return false;
169 }
170 return true;
171 }
172
Yabin Cuia9734e32022-12-12 12:03:11 -0800173 void Move(size_t size) {
174 if (CheckLeftSize(size)) {
175 head += size;
176 }
177 }
178
Yabin Cui540932c2022-09-13 15:52:33 -0700179 template <class T>
180 void Read(T& data) {
181 static_assert(std::is_standard_layout<T>::value, "not standard layout");
182 if (UNLIKELY(error)) {
183 return;
184 }
185 if (UNLIKELY(LeftSize() < sizeof(T))) {
186 error = true;
187 } else {
188 memcpy(&data, head, sizeof(T));
189 head += sizeof(T);
190 }
191 }
192
Yabin Cuide7d8eb2022-09-14 10:53:34 -0700193 template <class T>
194 void Read(T* data_p, size_t n) {
195 static_assert(std::is_standard_layout<T>::value, "not standard layout");
196 if (UNLIKELY(error)) {
197 return;
198 }
199 size_t size;
200 if (UNLIKELY(__builtin_mul_overflow(n, sizeof(T), &size) || LeftSize() < size)) {
201 error = true;
202 } else {
203 memcpy(data_p, head, size);
204 head += size;
205 }
206 }
207
Yabin Cui540932c2022-09-13 15:52:33 -0700208 // Read a string ending with '\0'.
209 std::string ReadString() {
210 if (UNLIKELY(error)) {
211 return "";
212 }
213 std::string result;
214 while (head < end && *head != '\0') {
215 result.push_back(*head++);
216 }
217 if (LIKELY(head < end && *head == '\0')) {
218 head++;
219 return result;
220 }
221 error = true;
222 return "";
223 }
224
225 const char* head;
226 const char* end;
227 bool error;
228};
229
Yabin Cui7d59bb42015-05-04 20:27:57 -0700230void PrintIndented(size_t indent, const char* fmt, ...);
Yabin Cui767dd172016-06-02 21:02:43 -0700231void FprintIndented(FILE* fp, size_t indent, const char* fmt, ...);
Yabin Cui7d59bb42015-05-04 20:27:57 -0700232
Yabin Cui9759e1b2015-04-28 15:54:13 -0700233bool IsPowerOfTwo(uint64_t value);
234
Yabin Cui07865862016-08-22 13:39:19 -0700235std::vector<std::string> GetEntriesInDir(const std::string& dirpath);
236std::vector<std::string> GetSubDirs(const std::string& dirpath);
Yabin Cuib032de72015-06-17 21:15:09 -0700237bool IsDir(const std::string& dirpath);
Yabin Cui797116b2015-12-08 17:43:15 -0800238bool IsRegularFile(const std::string& filename);
Yabin Cuib1a885b2016-02-14 19:18:02 -0800239uint64_t GetFileSize(const std::string& filename);
Yabin Cuibe7ec662016-03-02 13:56:28 -0800240bool MkdirWithParents(const std::string& path);
Yabin Cui323e9452015-04-20 18:07:17 -0700241
Yabin Cui05400532016-03-17 21:18:53 -0700242bool XzDecompress(const std::string& compressed_data, std::string* decompressed_data);
243
Yabin Cui8f680f62016-03-18 18:47:43 -0700244bool GetLogSeverity(const std::string& name, android::base::LogSeverity* severity);
Yabin Cui750b3732017-12-18 17:46:36 -0800245std::string GetLogSeverityName();
Yabin Cui8f680f62016-03-18 18:47:43 -0700246
Yabin Cui56335862016-04-18 13:43:20 -0700247bool IsRoot();
248
Yabin Cui4f41df62016-06-01 17:29:06 -0700249size_t GetPageSize();
250
251uint64_t ConvertBytesToValue(const char* bytes, uint32_t size);
252
Yabin Cui3e4c5952016-07-26 15:03:27 -0700253timeval SecondToTimeval(double time_in_sec);
254
Yabin Cuidf6333c2017-05-03 16:34:02 -0700255std::string GetSimpleperfVersion();
256
Yabin Cuie3ca9982020-10-16 13:16:26 -0700257std::optional<std::set<int>> GetCpusFromString(const std::string& s);
258std::optional<std::set<pid_t>> GetTidsFromString(const std::string& s, bool check_if_exists);
Yabin Cui1c6be752023-02-28 11:46:37 -0800259std::optional<std::set<pid_t>> GetPidsFromStrings(const std::vector<std::string>& strs,
260 bool check_if_exists,
261 bool support_progress_name_regex);
Namhyung Kima5f1d422019-12-17 17:15:02 +0900262
Yabin Cuia89a3742021-02-11 13:14:54 -0800263template <typename T>
264std::optional<std::set<T>> ParseUintVector(const std::string& s) {
265 std::set<T> result;
266 T value;
267 for (const auto& p : android::base::Split(s, ",")) {
268 if (!android::base::ParseUint(p.c_str(), &value, std::numeric_limits<T>::max())) {
269 LOG(ERROR) << "Invalid Uint '" << p << "' in " << s;
270 return std::nullopt;
271 }
272 result.insert(value);
273 }
274 return result;
275}
276
Yabin Cuifad7bbe2019-09-18 16:05:51 -0700277// from boost::hash_combine
278template <typename T>
Yabin Cuifaa7b922021-01-11 17:35:57 -0800279static inline void HashCombine(size_t& seed, const T& val) {
Yabin Cuifad7bbe2019-09-18 16:05:51 -0700280 seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
281}
282
Yabin Cui1cb85802021-11-12 17:56:57 -0800283size_t SafeStrlen(const char* s, const char* end);
284
Yabin Cui65b8fab2023-01-31 09:50:53 -0800285struct OverflowResult {
286 bool overflow = false;
287 uint64_t value = 0;
288};
289
290OverflowResult SafeAdd(uint64_t a, uint64_t b);
Yabin Cuif5ff15d2023-04-28 17:42:02 -0700291void OverflowSafeAdd(uint64_t& dest, uint64_t add);
Yabin Cui65b8fab2023-01-31 09:50:53 -0800292
Yabin Cuibb9a0d12023-08-31 15:53:31 -0700293std::string ReadableCount(uint64_t count);
Yabin Cui09136222024-07-16 10:30:21 -0700294std::string ReadableBytes(uint64_t bytes);
Yabin Cuibb9a0d12023-08-31 15:53:31 -0700295
Yabin Cuifaa7b922021-01-11 17:35:57 -0800296} // namespace simpleperf
Yabin Cuifad7bbe2019-09-18 16:05:51 -0700297
Yabin Cui67d3abd2015-04-16 15:26:31 -0700298#endif // SIMPLE_PERF_UTILS_H_