1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include "utils.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <dirent.h>
20*288bf522SAndroid Build Coastguard Worker #include <errno.h>
21*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
22*288bf522SAndroid Build Coastguard Worker #include <inttypes.h>
23*288bf522SAndroid Build Coastguard Worker #include <stdarg.h>
24*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
25*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
26*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
27*288bf522SAndroid Build Coastguard Worker
28*288bf522SAndroid Build Coastguard Worker #include <algorithm>
29*288bf522SAndroid Build Coastguard Worker #include <map>
30*288bf522SAndroid Build Coastguard Worker #include <string>
31*288bf522SAndroid Build Coastguard Worker
32*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
33*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
34*288bf522SAndroid Build Coastguard Worker #include <android-base/parseint.h>
35*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
36*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
37*288bf522SAndroid Build Coastguard Worker #include <build/version.h>
38*288bf522SAndroid Build Coastguard Worker
39*288bf522SAndroid Build Coastguard Worker #include <7zCrc.h>
40*288bf522SAndroid Build Coastguard Worker #include <Xz.h>
41*288bf522SAndroid Build Coastguard Worker #include <XzCrc64.h>
42*288bf522SAndroid Build Coastguard Worker
43*288bf522SAndroid Build Coastguard Worker #include "RegEx.h"
44*288bf522SAndroid Build Coastguard Worker #include "environment.h"
45*288bf522SAndroid Build Coastguard Worker
46*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
47*288bf522SAndroid Build Coastguard Worker
48*288bf522SAndroid Build Coastguard Worker using android::base::ParseInt;
49*288bf522SAndroid Build Coastguard Worker using android::base::Split;
50*288bf522SAndroid Build Coastguard Worker using android::base::StringPrintf;
51*288bf522SAndroid Build Coastguard Worker
Clear()52*288bf522SAndroid Build Coastguard Worker void OneTimeFreeAllocator::Clear() {
53*288bf522SAndroid Build Coastguard Worker for (auto& p : v_) {
54*288bf522SAndroid Build Coastguard Worker delete[] p;
55*288bf522SAndroid Build Coastguard Worker }
56*288bf522SAndroid Build Coastguard Worker v_.clear();
57*288bf522SAndroid Build Coastguard Worker cur_ = nullptr;
58*288bf522SAndroid Build Coastguard Worker end_ = nullptr;
59*288bf522SAndroid Build Coastguard Worker }
60*288bf522SAndroid Build Coastguard Worker
AllocateString(std::string_view s)61*288bf522SAndroid Build Coastguard Worker const char* OneTimeFreeAllocator::AllocateString(std::string_view s) {
62*288bf522SAndroid Build Coastguard Worker size_t size = s.size() + 1;
63*288bf522SAndroid Build Coastguard Worker if (cur_ + size > end_) {
64*288bf522SAndroid Build Coastguard Worker size_t alloc_size = std::max(size, unit_size_);
65*288bf522SAndroid Build Coastguard Worker char* p = new char[alloc_size];
66*288bf522SAndroid Build Coastguard Worker v_.push_back(p);
67*288bf522SAndroid Build Coastguard Worker cur_ = p;
68*288bf522SAndroid Build Coastguard Worker end_ = p + alloc_size;
69*288bf522SAndroid Build Coastguard Worker }
70*288bf522SAndroid Build Coastguard Worker memcpy(cur_, s.data(), s.size());
71*288bf522SAndroid Build Coastguard Worker cur_[s.size()] = '\0';
72*288bf522SAndroid Build Coastguard Worker const char* result = cur_;
73*288bf522SAndroid Build Coastguard Worker cur_ += size;
74*288bf522SAndroid Build Coastguard Worker return result;
75*288bf522SAndroid Build Coastguard Worker }
76*288bf522SAndroid Build Coastguard Worker
OpenReadOnly(const std::string & filename)77*288bf522SAndroid Build Coastguard Worker android::base::unique_fd FileHelper::OpenReadOnly(const std::string& filename) {
78*288bf522SAndroid Build Coastguard Worker int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_BINARY));
79*288bf522SAndroid Build Coastguard Worker return android::base::unique_fd(fd);
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker
OpenWriteOnly(const std::string & filename)82*288bf522SAndroid Build Coastguard Worker android::base::unique_fd FileHelper::OpenWriteOnly(const std::string& filename) {
83*288bf522SAndroid Build Coastguard Worker int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_BINARY | O_CREAT, 0644));
84*288bf522SAndroid Build Coastguard Worker return android::base::unique_fd(fd);
85*288bf522SAndroid Build Coastguard Worker }
86*288bf522SAndroid Build Coastguard Worker
CreateInstance(const std::string & filename)87*288bf522SAndroid Build Coastguard Worker std::unique_ptr<ArchiveHelper> ArchiveHelper::CreateInstance(const std::string& filename) {
88*288bf522SAndroid Build Coastguard Worker android::base::unique_fd fd = FileHelper::OpenReadOnly(filename);
89*288bf522SAndroid Build Coastguard Worker if (fd == -1) {
90*288bf522SAndroid Build Coastguard Worker return nullptr;
91*288bf522SAndroid Build Coastguard Worker }
92*288bf522SAndroid Build Coastguard Worker // Simpleperf relies on ArchiveHelper to check if a file is zip file. We expect much more elf
93*288bf522SAndroid Build Coastguard Worker // files than zip files in a process map. In order to detect invalid zip files fast, we add a
94*288bf522SAndroid Build Coastguard Worker // check of magic number here. Note that OpenArchiveFd() detects invalid zip files in a thorough
95*288bf522SAndroid Build Coastguard Worker // way, but it usually needs reading at least 64K file data.
96*288bf522SAndroid Build Coastguard Worker static const char zip_preamble[] = {0x50, 0x4b, 0x03, 0x04};
97*288bf522SAndroid Build Coastguard Worker char buf[4];
98*288bf522SAndroid Build Coastguard Worker if (!android::base::ReadFully(fd, buf, 4) || memcmp(buf, zip_preamble, 4) != 0) {
99*288bf522SAndroid Build Coastguard Worker return nullptr;
100*288bf522SAndroid Build Coastguard Worker }
101*288bf522SAndroid Build Coastguard Worker if (lseek(fd, 0, SEEK_SET) == -1) {
102*288bf522SAndroid Build Coastguard Worker return nullptr;
103*288bf522SAndroid Build Coastguard Worker }
104*288bf522SAndroid Build Coastguard Worker ZipArchiveHandle handle;
105*288bf522SAndroid Build Coastguard Worker int result = OpenArchiveFd(fd.release(), filename.c_str(), &handle);
106*288bf522SAndroid Build Coastguard Worker if (result != 0) {
107*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to open archive " << filename << ": " << ErrorCodeString(result);
108*288bf522SAndroid Build Coastguard Worker return nullptr;
109*288bf522SAndroid Build Coastguard Worker }
110*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<ArchiveHelper>(new ArchiveHelper(handle, filename));
111*288bf522SAndroid Build Coastguard Worker }
112*288bf522SAndroid Build Coastguard Worker
~ArchiveHelper()113*288bf522SAndroid Build Coastguard Worker ArchiveHelper::~ArchiveHelper() {
114*288bf522SAndroid Build Coastguard Worker CloseArchive(handle_);
115*288bf522SAndroid Build Coastguard Worker }
116*288bf522SAndroid Build Coastguard Worker
IterateEntries(const std::function<bool (ZipEntry &,const std::string &)> & callback)117*288bf522SAndroid Build Coastguard Worker bool ArchiveHelper::IterateEntries(
118*288bf522SAndroid Build Coastguard Worker const std::function<bool(ZipEntry&, const std::string&)>& callback) {
119*288bf522SAndroid Build Coastguard Worker void* iteration_cookie;
120*288bf522SAndroid Build Coastguard Worker if (StartIteration(handle_, &iteration_cookie) < 0) {
121*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to iterate " << filename_;
122*288bf522SAndroid Build Coastguard Worker return false;
123*288bf522SAndroid Build Coastguard Worker }
124*288bf522SAndroid Build Coastguard Worker ZipEntry zentry;
125*288bf522SAndroid Build Coastguard Worker std::string zname;
126*288bf522SAndroid Build Coastguard Worker int result;
127*288bf522SAndroid Build Coastguard Worker while ((result = Next(iteration_cookie, &zentry, &zname)) == 0) {
128*288bf522SAndroid Build Coastguard Worker if (!callback(zentry, zname)) {
129*288bf522SAndroid Build Coastguard Worker break;
130*288bf522SAndroid Build Coastguard Worker }
131*288bf522SAndroid Build Coastguard Worker }
132*288bf522SAndroid Build Coastguard Worker EndIteration(iteration_cookie);
133*288bf522SAndroid Build Coastguard Worker if (result == -2) {
134*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to iterate " << filename_;
135*288bf522SAndroid Build Coastguard Worker return false;
136*288bf522SAndroid Build Coastguard Worker }
137*288bf522SAndroid Build Coastguard Worker return true;
138*288bf522SAndroid Build Coastguard Worker }
139*288bf522SAndroid Build Coastguard Worker
FindEntry(const std::string & name,ZipEntry * entry)140*288bf522SAndroid Build Coastguard Worker bool ArchiveHelper::FindEntry(const std::string& name, ZipEntry* entry) {
141*288bf522SAndroid Build Coastguard Worker int result = ::FindEntry(handle_, name, entry);
142*288bf522SAndroid Build Coastguard Worker if (result != 0) {
143*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to find " << name << " in " << filename_;
144*288bf522SAndroid Build Coastguard Worker return false;
145*288bf522SAndroid Build Coastguard Worker }
146*288bf522SAndroid Build Coastguard Worker return true;
147*288bf522SAndroid Build Coastguard Worker }
148*288bf522SAndroid Build Coastguard Worker
GetEntryData(ZipEntry & entry,std::vector<uint8_t> * data)149*288bf522SAndroid Build Coastguard Worker bool ArchiveHelper::GetEntryData(ZipEntry& entry, std::vector<uint8_t>* data) {
150*288bf522SAndroid Build Coastguard Worker data->resize(entry.uncompressed_length);
151*288bf522SAndroid Build Coastguard Worker if (ExtractToMemory(handle_, &entry, data->data(), data->size()) != 0) {
152*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to extract entry at " << entry.offset << " in " << filename_;
153*288bf522SAndroid Build Coastguard Worker return false;
154*288bf522SAndroid Build Coastguard Worker }
155*288bf522SAndroid Build Coastguard Worker return true;
156*288bf522SAndroid Build Coastguard Worker }
157*288bf522SAndroid Build Coastguard Worker
GetFd()158*288bf522SAndroid Build Coastguard Worker int ArchiveHelper::GetFd() {
159*288bf522SAndroid Build Coastguard Worker return GetFileDescriptor(handle_);
160*288bf522SAndroid Build Coastguard Worker }
161*288bf522SAndroid Build Coastguard Worker
PrintIndented(size_t indent,const char * fmt,...)162*288bf522SAndroid Build Coastguard Worker void PrintIndented(size_t indent, const char* fmt, ...) {
163*288bf522SAndroid Build Coastguard Worker va_list ap;
164*288bf522SAndroid Build Coastguard Worker va_start(ap, fmt);
165*288bf522SAndroid Build Coastguard Worker printf("%*s", static_cast<int>(indent * 2), "");
166*288bf522SAndroid Build Coastguard Worker vprintf(fmt, ap);
167*288bf522SAndroid Build Coastguard Worker va_end(ap);
168*288bf522SAndroid Build Coastguard Worker }
169*288bf522SAndroid Build Coastguard Worker
FprintIndented(FILE * fp,size_t indent,const char * fmt,...)170*288bf522SAndroid Build Coastguard Worker void FprintIndented(FILE* fp, size_t indent, const char* fmt, ...) {
171*288bf522SAndroid Build Coastguard Worker va_list ap;
172*288bf522SAndroid Build Coastguard Worker va_start(ap, fmt);
173*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%*s", static_cast<int>(indent * 2), "");
174*288bf522SAndroid Build Coastguard Worker vfprintf(fp, fmt, ap);
175*288bf522SAndroid Build Coastguard Worker va_end(ap);
176*288bf522SAndroid Build Coastguard Worker }
177*288bf522SAndroid Build Coastguard Worker
IsPowerOfTwo(uint64_t value)178*288bf522SAndroid Build Coastguard Worker bool IsPowerOfTwo(uint64_t value) {
179*288bf522SAndroid Build Coastguard Worker return (value != 0 && ((value & (value - 1)) == 0));
180*288bf522SAndroid Build Coastguard Worker }
181*288bf522SAndroid Build Coastguard Worker
GetEntriesInDir(const std::string & dirpath)182*288bf522SAndroid Build Coastguard Worker std::vector<std::string> GetEntriesInDir(const std::string& dirpath) {
183*288bf522SAndroid Build Coastguard Worker std::vector<std::string> result;
184*288bf522SAndroid Build Coastguard Worker DIR* dir = opendir(dirpath.c_str());
185*288bf522SAndroid Build Coastguard Worker if (dir == nullptr) {
186*288bf522SAndroid Build Coastguard Worker PLOG(DEBUG) << "can't open dir " << dirpath;
187*288bf522SAndroid Build Coastguard Worker return result;
188*288bf522SAndroid Build Coastguard Worker }
189*288bf522SAndroid Build Coastguard Worker dirent* entry;
190*288bf522SAndroid Build Coastguard Worker while ((entry = readdir(dir)) != nullptr) {
191*288bf522SAndroid Build Coastguard Worker if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
192*288bf522SAndroid Build Coastguard Worker continue;
193*288bf522SAndroid Build Coastguard Worker }
194*288bf522SAndroid Build Coastguard Worker result.push_back(entry->d_name);
195*288bf522SAndroid Build Coastguard Worker }
196*288bf522SAndroid Build Coastguard Worker closedir(dir);
197*288bf522SAndroid Build Coastguard Worker return result;
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker
GetSubDirs(const std::string & dirpath)200*288bf522SAndroid Build Coastguard Worker std::vector<std::string> GetSubDirs(const std::string& dirpath) {
201*288bf522SAndroid Build Coastguard Worker std::vector<std::string> entries = GetEntriesInDir(dirpath);
202*288bf522SAndroid Build Coastguard Worker std::vector<std::string> result;
203*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < entries.size(); ++i) {
204*288bf522SAndroid Build Coastguard Worker if (IsDir(dirpath + OS_PATH_SEPARATOR + entries[i])) {
205*288bf522SAndroid Build Coastguard Worker result.push_back(std::move(entries[i]));
206*288bf522SAndroid Build Coastguard Worker }
207*288bf522SAndroid Build Coastguard Worker }
208*288bf522SAndroid Build Coastguard Worker return result;
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker
IsDir(const std::string & dirpath)211*288bf522SAndroid Build Coastguard Worker bool IsDir(const std::string& dirpath) {
212*288bf522SAndroid Build Coastguard Worker struct stat st;
213*288bf522SAndroid Build Coastguard Worker if (stat(dirpath.c_str(), &st) == 0) {
214*288bf522SAndroid Build Coastguard Worker if (S_ISDIR(st.st_mode)) {
215*288bf522SAndroid Build Coastguard Worker return true;
216*288bf522SAndroid Build Coastguard Worker }
217*288bf522SAndroid Build Coastguard Worker }
218*288bf522SAndroid Build Coastguard Worker return false;
219*288bf522SAndroid Build Coastguard Worker }
220*288bf522SAndroid Build Coastguard Worker
IsRegularFile(const std::string & filename)221*288bf522SAndroid Build Coastguard Worker bool IsRegularFile(const std::string& filename) {
222*288bf522SAndroid Build Coastguard Worker struct stat st;
223*288bf522SAndroid Build Coastguard Worker if (stat(filename.c_str(), &st) == 0) {
224*288bf522SAndroid Build Coastguard Worker if (S_ISREG(st.st_mode)) {
225*288bf522SAndroid Build Coastguard Worker return true;
226*288bf522SAndroid Build Coastguard Worker }
227*288bf522SAndroid Build Coastguard Worker }
228*288bf522SAndroid Build Coastguard Worker return false;
229*288bf522SAndroid Build Coastguard Worker }
230*288bf522SAndroid Build Coastguard Worker
GetFileSize(const std::string & filename)231*288bf522SAndroid Build Coastguard Worker uint64_t GetFileSize(const std::string& filename) {
232*288bf522SAndroid Build Coastguard Worker struct stat st;
233*288bf522SAndroid Build Coastguard Worker if (stat(filename.c_str(), &st) == 0) {
234*288bf522SAndroid Build Coastguard Worker return static_cast<uint64_t>(st.st_size);
235*288bf522SAndroid Build Coastguard Worker }
236*288bf522SAndroid Build Coastguard Worker return 0;
237*288bf522SAndroid Build Coastguard Worker }
238*288bf522SAndroid Build Coastguard Worker
MkdirWithParents(const std::string & path)239*288bf522SAndroid Build Coastguard Worker bool MkdirWithParents(const std::string& path) {
240*288bf522SAndroid Build Coastguard Worker size_t prev_end = 0;
241*288bf522SAndroid Build Coastguard Worker while (prev_end < path.size()) {
242*288bf522SAndroid Build Coastguard Worker size_t next_end = path.find('/', prev_end + 1);
243*288bf522SAndroid Build Coastguard Worker if (next_end == std::string::npos) {
244*288bf522SAndroid Build Coastguard Worker break;
245*288bf522SAndroid Build Coastguard Worker }
246*288bf522SAndroid Build Coastguard Worker std::string dir_path = path.substr(0, next_end);
247*288bf522SAndroid Build Coastguard Worker if (!IsDir(dir_path)) {
248*288bf522SAndroid Build Coastguard Worker #if defined(_WIN32)
249*288bf522SAndroid Build Coastguard Worker int ret = mkdir(dir_path.c_str());
250*288bf522SAndroid Build Coastguard Worker #else
251*288bf522SAndroid Build Coastguard Worker int ret = mkdir(dir_path.c_str(), 0755);
252*288bf522SAndroid Build Coastguard Worker #endif
253*288bf522SAndroid Build Coastguard Worker if (ret != 0) {
254*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to create dir " << dir_path;
255*288bf522SAndroid Build Coastguard Worker return false;
256*288bf522SAndroid Build Coastguard Worker }
257*288bf522SAndroid Build Coastguard Worker }
258*288bf522SAndroid Build Coastguard Worker prev_end = next_end;
259*288bf522SAndroid Build Coastguard Worker }
260*288bf522SAndroid Build Coastguard Worker return true;
261*288bf522SAndroid Build Coastguard Worker }
262*288bf522SAndroid Build Coastguard Worker
xz_alloc(ISzAllocPtr,size_t size)263*288bf522SAndroid Build Coastguard Worker static void* xz_alloc(ISzAllocPtr, size_t size) {
264*288bf522SAndroid Build Coastguard Worker return malloc(size);
265*288bf522SAndroid Build Coastguard Worker }
266*288bf522SAndroid Build Coastguard Worker
xz_free(ISzAllocPtr,void * address)267*288bf522SAndroid Build Coastguard Worker static void xz_free(ISzAllocPtr, void* address) {
268*288bf522SAndroid Build Coastguard Worker free(address);
269*288bf522SAndroid Build Coastguard Worker }
270*288bf522SAndroid Build Coastguard Worker
XzDecompress(const std::string & compressed_data,std::string * decompressed_data)271*288bf522SAndroid Build Coastguard Worker bool XzDecompress(const std::string& compressed_data, std::string* decompressed_data) {
272*288bf522SAndroid Build Coastguard Worker ISzAlloc alloc;
273*288bf522SAndroid Build Coastguard Worker CXzUnpacker state;
274*288bf522SAndroid Build Coastguard Worker alloc.Alloc = xz_alloc;
275*288bf522SAndroid Build Coastguard Worker alloc.Free = xz_free;
276*288bf522SAndroid Build Coastguard Worker XzUnpacker_Construct(&state, &alloc);
277*288bf522SAndroid Build Coastguard Worker CrcGenerateTable();
278*288bf522SAndroid Build Coastguard Worker Crc64GenerateTable();
279*288bf522SAndroid Build Coastguard Worker size_t src_offset = 0;
280*288bf522SAndroid Build Coastguard Worker size_t dst_offset = 0;
281*288bf522SAndroid Build Coastguard Worker std::string dst(compressed_data.size(), ' ');
282*288bf522SAndroid Build Coastguard Worker
283*288bf522SAndroid Build Coastguard Worker ECoderStatus status = CODER_STATUS_NOT_FINISHED;
284*288bf522SAndroid Build Coastguard Worker while (status == CODER_STATUS_NOT_FINISHED) {
285*288bf522SAndroid Build Coastguard Worker dst.resize(dst.size() * 2);
286*288bf522SAndroid Build Coastguard Worker size_t src_remaining = compressed_data.size() - src_offset;
287*288bf522SAndroid Build Coastguard Worker size_t dst_remaining = dst.size() - dst_offset;
288*288bf522SAndroid Build Coastguard Worker int res = XzUnpacker_Code(&state, reinterpret_cast<Byte*>(&dst[dst_offset]), &dst_remaining,
289*288bf522SAndroid Build Coastguard Worker reinterpret_cast<const Byte*>(&compressed_data[src_offset]),
290*288bf522SAndroid Build Coastguard Worker &src_remaining, true, CODER_FINISH_ANY, &status);
291*288bf522SAndroid Build Coastguard Worker if (res != SZ_OK) {
292*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "LZMA decompression failed with error " << res;
293*288bf522SAndroid Build Coastguard Worker XzUnpacker_Free(&state);
294*288bf522SAndroid Build Coastguard Worker return false;
295*288bf522SAndroid Build Coastguard Worker }
296*288bf522SAndroid Build Coastguard Worker src_offset += src_remaining;
297*288bf522SAndroid Build Coastguard Worker dst_offset += dst_remaining;
298*288bf522SAndroid Build Coastguard Worker }
299*288bf522SAndroid Build Coastguard Worker XzUnpacker_Free(&state);
300*288bf522SAndroid Build Coastguard Worker if (!XzUnpacker_IsStreamWasFinished(&state)) {
301*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "LZMA decompresstion failed due to incomplete stream";
302*288bf522SAndroid Build Coastguard Worker return false;
303*288bf522SAndroid Build Coastguard Worker }
304*288bf522SAndroid Build Coastguard Worker dst.resize(dst_offset);
305*288bf522SAndroid Build Coastguard Worker *decompressed_data = std::move(dst);
306*288bf522SAndroid Build Coastguard Worker return true;
307*288bf522SAndroid Build Coastguard Worker }
308*288bf522SAndroid Build Coastguard Worker
309*288bf522SAndroid Build Coastguard Worker static std::map<std::string, android::base::LogSeverity> log_severity_map = {
310*288bf522SAndroid Build Coastguard Worker {"verbose", android::base::VERBOSE}, {"debug", android::base::DEBUG},
311*288bf522SAndroid Build Coastguard Worker {"info", android::base::INFO}, {"warning", android::base::WARNING},
312*288bf522SAndroid Build Coastguard Worker {"error", android::base::ERROR}, {"fatal", android::base::FATAL},
313*288bf522SAndroid Build Coastguard Worker };
GetLogSeverity(const std::string & name,android::base::LogSeverity * severity)314*288bf522SAndroid Build Coastguard Worker bool GetLogSeverity(const std::string& name, android::base::LogSeverity* severity) {
315*288bf522SAndroid Build Coastguard Worker auto it = log_severity_map.find(name);
316*288bf522SAndroid Build Coastguard Worker if (it != log_severity_map.end()) {
317*288bf522SAndroid Build Coastguard Worker *severity = it->second;
318*288bf522SAndroid Build Coastguard Worker return true;
319*288bf522SAndroid Build Coastguard Worker }
320*288bf522SAndroid Build Coastguard Worker return false;
321*288bf522SAndroid Build Coastguard Worker }
322*288bf522SAndroid Build Coastguard Worker
GetLogSeverityName()323*288bf522SAndroid Build Coastguard Worker std::string GetLogSeverityName() {
324*288bf522SAndroid Build Coastguard Worker android::base::LogSeverity severity = android::base::GetMinimumLogSeverity();
325*288bf522SAndroid Build Coastguard Worker for (auto& pair : log_severity_map) {
326*288bf522SAndroid Build Coastguard Worker if (severity == pair.second) {
327*288bf522SAndroid Build Coastguard Worker return pair.first;
328*288bf522SAndroid Build Coastguard Worker }
329*288bf522SAndroid Build Coastguard Worker }
330*288bf522SAndroid Build Coastguard Worker return "info";
331*288bf522SAndroid Build Coastguard Worker }
332*288bf522SAndroid Build Coastguard Worker
IsRoot()333*288bf522SAndroid Build Coastguard Worker bool IsRoot() {
334*288bf522SAndroid Build Coastguard Worker static int is_root = -1;
335*288bf522SAndroid Build Coastguard Worker if (is_root == -1) {
336*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
337*288bf522SAndroid Build Coastguard Worker is_root = (getuid() == 0) ? 1 : 0;
338*288bf522SAndroid Build Coastguard Worker #else
339*288bf522SAndroid Build Coastguard Worker is_root = 0;
340*288bf522SAndroid Build Coastguard Worker #endif
341*288bf522SAndroid Build Coastguard Worker }
342*288bf522SAndroid Build Coastguard Worker return is_root == 1;
343*288bf522SAndroid Build Coastguard Worker }
344*288bf522SAndroid Build Coastguard Worker
GetPageSize()345*288bf522SAndroid Build Coastguard Worker size_t GetPageSize() {
346*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
347*288bf522SAndroid Build Coastguard Worker return sysconf(_SC_PAGE_SIZE);
348*288bf522SAndroid Build Coastguard Worker #else
349*288bf522SAndroid Build Coastguard Worker return 4096;
350*288bf522SAndroid Build Coastguard Worker #endif
351*288bf522SAndroid Build Coastguard Worker }
352*288bf522SAndroid Build Coastguard Worker
ConvertBytesToValue(const char * bytes,uint32_t size)353*288bf522SAndroid Build Coastguard Worker uint64_t ConvertBytesToValue(const char* bytes, uint32_t size) {
354*288bf522SAndroid Build Coastguard Worker if (size > 8) {
355*288bf522SAndroid Build Coastguard Worker LOG(FATAL) << "unexpected size " << size << " in ConvertBytesToValue";
356*288bf522SAndroid Build Coastguard Worker }
357*288bf522SAndroid Build Coastguard Worker uint64_t result = 0;
358*288bf522SAndroid Build Coastguard Worker int shift = 0;
359*288bf522SAndroid Build Coastguard Worker for (uint32_t i = 0; i < size; ++i) {
360*288bf522SAndroid Build Coastguard Worker uint64_t tmp = static_cast<unsigned char>(bytes[i]);
361*288bf522SAndroid Build Coastguard Worker result |= tmp << shift;
362*288bf522SAndroid Build Coastguard Worker shift += 8;
363*288bf522SAndroid Build Coastguard Worker }
364*288bf522SAndroid Build Coastguard Worker return result;
365*288bf522SAndroid Build Coastguard Worker }
366*288bf522SAndroid Build Coastguard Worker
SecondToTimeval(double time_in_sec)367*288bf522SAndroid Build Coastguard Worker timeval SecondToTimeval(double time_in_sec) {
368*288bf522SAndroid Build Coastguard Worker timeval tv;
369*288bf522SAndroid Build Coastguard Worker tv.tv_sec = static_cast<time_t>(time_in_sec);
370*288bf522SAndroid Build Coastguard Worker tv.tv_usec = static_cast<int>((time_in_sec - tv.tv_sec) * 1000000);
371*288bf522SAndroid Build Coastguard Worker return tv;
372*288bf522SAndroid Build Coastguard Worker }
373*288bf522SAndroid Build Coastguard Worker
374*288bf522SAndroid Build Coastguard Worker constexpr int SIMPLEPERF_VERSION = 1;
375*288bf522SAndroid Build Coastguard Worker
GetSimpleperfVersion()376*288bf522SAndroid Build Coastguard Worker std::string GetSimpleperfVersion() {
377*288bf522SAndroid Build Coastguard Worker return StringPrintf("%d.build.%s", SIMPLEPERF_VERSION, android::build::GetBuildNumber().c_str());
378*288bf522SAndroid Build Coastguard Worker }
379*288bf522SAndroid Build Coastguard Worker
380*288bf522SAndroid Build Coastguard Worker // Parse a line like: 0,1-3, 5, 7-8
GetCpusFromString(const std::string & s)381*288bf522SAndroid Build Coastguard Worker std::optional<std::set<int>> GetCpusFromString(const std::string& s) {
382*288bf522SAndroid Build Coastguard Worker std::string str;
383*288bf522SAndroid Build Coastguard Worker for (char c : s) {
384*288bf522SAndroid Build Coastguard Worker if (!isspace(c)) {
385*288bf522SAndroid Build Coastguard Worker str += c;
386*288bf522SAndroid Build Coastguard Worker }
387*288bf522SAndroid Build Coastguard Worker }
388*288bf522SAndroid Build Coastguard Worker std::set<int> cpus;
389*288bf522SAndroid Build Coastguard Worker int cpu1;
390*288bf522SAndroid Build Coastguard Worker int cpu2;
391*288bf522SAndroid Build Coastguard Worker for (const std::string& p : Split(str, ",")) {
392*288bf522SAndroid Build Coastguard Worker size_t split_pos = p.find('-');
393*288bf522SAndroid Build Coastguard Worker if (split_pos == std::string::npos) {
394*288bf522SAndroid Build Coastguard Worker if (!ParseInt(p, &cpu1, 0)) {
395*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "failed to parse cpu: " << p;
396*288bf522SAndroid Build Coastguard Worker return std::nullopt;
397*288bf522SAndroid Build Coastguard Worker }
398*288bf522SAndroid Build Coastguard Worker cpus.insert(cpu1);
399*288bf522SAndroid Build Coastguard Worker } else {
400*288bf522SAndroid Build Coastguard Worker if (!ParseInt(p.substr(0, split_pos), &cpu1, 0) ||
401*288bf522SAndroid Build Coastguard Worker !ParseInt(p.substr(split_pos + 1), &cpu2, 0) || cpu1 > cpu2) {
402*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "failed to parse cpu: " << p;
403*288bf522SAndroid Build Coastguard Worker return std::nullopt;
404*288bf522SAndroid Build Coastguard Worker }
405*288bf522SAndroid Build Coastguard Worker while (cpu1 <= cpu2) {
406*288bf522SAndroid Build Coastguard Worker cpus.insert(cpu1++);
407*288bf522SAndroid Build Coastguard Worker }
408*288bf522SAndroid Build Coastguard Worker }
409*288bf522SAndroid Build Coastguard Worker }
410*288bf522SAndroid Build Coastguard Worker return cpus;
411*288bf522SAndroid Build Coastguard Worker }
412*288bf522SAndroid Build Coastguard Worker
GetTidsFromString(const std::string & s,bool check_if_exists)413*288bf522SAndroid Build Coastguard Worker std::optional<std::set<pid_t>> GetTidsFromString(const std::string& s, bool check_if_exists) {
414*288bf522SAndroid Build Coastguard Worker std::set<pid_t> tids;
415*288bf522SAndroid Build Coastguard Worker for (const auto& p : Split(s, ",")) {
416*288bf522SAndroid Build Coastguard Worker int tid;
417*288bf522SAndroid Build Coastguard Worker if (!ParseInt(p.c_str(), &tid, 0)) {
418*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid tid '" << p << "'";
419*288bf522SAndroid Build Coastguard Worker return std::nullopt;
420*288bf522SAndroid Build Coastguard Worker }
421*288bf522SAndroid Build Coastguard Worker if (check_if_exists && !IsDir(StringPrintf("/proc/%d", tid))) {
422*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Non existing thread '" << tid << "'";
423*288bf522SAndroid Build Coastguard Worker return std::nullopt;
424*288bf522SAndroid Build Coastguard Worker }
425*288bf522SAndroid Build Coastguard Worker tids.insert(tid);
426*288bf522SAndroid Build Coastguard Worker }
427*288bf522SAndroid Build Coastguard Worker return tids;
428*288bf522SAndroid Build Coastguard Worker }
429*288bf522SAndroid Build Coastguard Worker
GetPidsFromStrings(const std::vector<std::string> & strs,bool check_if_exists,bool support_progress_name_regex)430*288bf522SAndroid Build Coastguard Worker std::optional<std::set<pid_t>> GetPidsFromStrings(const std::vector<std::string>& strs,
431*288bf522SAndroid Build Coastguard Worker bool check_if_exists,
432*288bf522SAndroid Build Coastguard Worker bool support_progress_name_regex) {
433*288bf522SAndroid Build Coastguard Worker std::set<pid_t> pids;
434*288bf522SAndroid Build Coastguard Worker std::vector<std::unique_ptr<RegEx>> regs;
435*288bf522SAndroid Build Coastguard Worker for (const auto& s : strs) {
436*288bf522SAndroid Build Coastguard Worker for (const auto& p : Split(s, ",")) {
437*288bf522SAndroid Build Coastguard Worker int pid;
438*288bf522SAndroid Build Coastguard Worker if (ParseInt(p.c_str(), &pid, 0)) {
439*288bf522SAndroid Build Coastguard Worker if (check_if_exists && !IsDir(StringPrintf("/proc/%d", pid))) {
440*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "no process with pid " << pid;
441*288bf522SAndroid Build Coastguard Worker return std::nullopt;
442*288bf522SAndroid Build Coastguard Worker }
443*288bf522SAndroid Build Coastguard Worker pids.insert(pid);
444*288bf522SAndroid Build Coastguard Worker } else if (support_progress_name_regex) {
445*288bf522SAndroid Build Coastguard Worker auto reg = RegEx::Create(p);
446*288bf522SAndroid Build Coastguard Worker if (!reg) {
447*288bf522SAndroid Build Coastguard Worker return std::nullopt;
448*288bf522SAndroid Build Coastguard Worker }
449*288bf522SAndroid Build Coastguard Worker regs.emplace_back(std::move(reg));
450*288bf522SAndroid Build Coastguard Worker } else {
451*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "invalid pid: " << p;
452*288bf522SAndroid Build Coastguard Worker return std::nullopt;
453*288bf522SAndroid Build Coastguard Worker }
454*288bf522SAndroid Build Coastguard Worker }
455*288bf522SAndroid Build Coastguard Worker }
456*288bf522SAndroid Build Coastguard Worker if (!regs.empty()) {
457*288bf522SAndroid Build Coastguard Worker #if defined(__linux__)
458*288bf522SAndroid Build Coastguard Worker for (pid_t pid : GetAllProcesses()) {
459*288bf522SAndroid Build Coastguard Worker std::string process_name = GetCompleteProcessName(pid);
460*288bf522SAndroid Build Coastguard Worker if (process_name.empty()) {
461*288bf522SAndroid Build Coastguard Worker continue;
462*288bf522SAndroid Build Coastguard Worker }
463*288bf522SAndroid Build Coastguard Worker for (const auto& reg : regs) {
464*288bf522SAndroid Build Coastguard Worker if (reg->Search(process_name)) {
465*288bf522SAndroid Build Coastguard Worker pids.insert(pid);
466*288bf522SAndroid Build Coastguard Worker break;
467*288bf522SAndroid Build Coastguard Worker }
468*288bf522SAndroid Build Coastguard Worker }
469*288bf522SAndroid Build Coastguard Worker }
470*288bf522SAndroid Build Coastguard Worker #else // defined(__linux__)
471*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "progress name regex isn't supported";
472*288bf522SAndroid Build Coastguard Worker return std::nullopt;
473*288bf522SAndroid Build Coastguard Worker #endif // defined(__linux__)
474*288bf522SAndroid Build Coastguard Worker }
475*288bf522SAndroid Build Coastguard Worker return pids;
476*288bf522SAndroid Build Coastguard Worker }
477*288bf522SAndroid Build Coastguard Worker
SafeStrlen(const char * s,const char * end)478*288bf522SAndroid Build Coastguard Worker size_t SafeStrlen(const char* s, const char* end) {
479*288bf522SAndroid Build Coastguard Worker const char* p = s;
480*288bf522SAndroid Build Coastguard Worker while (p < end && *p != '\0') {
481*288bf522SAndroid Build Coastguard Worker p++;
482*288bf522SAndroid Build Coastguard Worker }
483*288bf522SAndroid Build Coastguard Worker return p - s;
484*288bf522SAndroid Build Coastguard Worker }
485*288bf522SAndroid Build Coastguard Worker
SafeAdd(uint64_t a,uint64_t b)486*288bf522SAndroid Build Coastguard Worker OverflowResult SafeAdd(uint64_t a, uint64_t b) {
487*288bf522SAndroid Build Coastguard Worker OverflowResult result;
488*288bf522SAndroid Build Coastguard Worker if (__builtin_add_overflow(a, b, &result.value)) {
489*288bf522SAndroid Build Coastguard Worker result.overflow = true;
490*288bf522SAndroid Build Coastguard Worker }
491*288bf522SAndroid Build Coastguard Worker return result;
492*288bf522SAndroid Build Coastguard Worker }
493*288bf522SAndroid Build Coastguard Worker
OverflowSafeAdd(uint64_t & dest,uint64_t add)494*288bf522SAndroid Build Coastguard Worker void OverflowSafeAdd(uint64_t& dest, uint64_t add) {
495*288bf522SAndroid Build Coastguard Worker if (__builtin_add_overflow(dest, add, &dest)) {
496*288bf522SAndroid Build Coastguard Worker LOG(WARNING) << "Branch count overflow happened.";
497*288bf522SAndroid Build Coastguard Worker dest = UINT64_MAX;
498*288bf522SAndroid Build Coastguard Worker }
499*288bf522SAndroid Build Coastguard Worker }
500*288bf522SAndroid Build Coastguard Worker
501*288bf522SAndroid Build Coastguard Worker // Convert big numbers to human friendly mode. For example,
502*288bf522SAndroid Build Coastguard Worker // 1000000 will be converted to 1,000,000.
ReadableCount(uint64_t count)503*288bf522SAndroid Build Coastguard Worker std::string ReadableCount(uint64_t count) {
504*288bf522SAndroid Build Coastguard Worker std::string s = std::to_string(count);
505*288bf522SAndroid Build Coastguard Worker for (size_t i = s.size() - 1, j = 1; i > 0; --i, ++j) {
506*288bf522SAndroid Build Coastguard Worker if (j == 3) {
507*288bf522SAndroid Build Coastguard Worker s.insert(s.begin() + i, ',');
508*288bf522SAndroid Build Coastguard Worker j = 0;
509*288bf522SAndroid Build Coastguard Worker }
510*288bf522SAndroid Build Coastguard Worker }
511*288bf522SAndroid Build Coastguard Worker return s;
512*288bf522SAndroid Build Coastguard Worker }
513*288bf522SAndroid Build Coastguard Worker
514*288bf522SAndroid Build Coastguard Worker // Convert bytes to human friendly mode.
ReadableBytes(uint64_t bytes)515*288bf522SAndroid Build Coastguard Worker std::string ReadableBytes(uint64_t bytes) {
516*288bf522SAndroid Build Coastguard Worker if (bytes >= kMegabyte) {
517*288bf522SAndroid Build Coastguard Worker return StringPrintf("%.2f MB", static_cast<double>(bytes) / kMegabyte);
518*288bf522SAndroid Build Coastguard Worker }
519*288bf522SAndroid Build Coastguard Worker if (bytes >= kKilobyte) {
520*288bf522SAndroid Build Coastguard Worker return StringPrintf("%.2f KB", static_cast<double>(bytes) / kKilobyte);
521*288bf522SAndroid Build Coastguard Worker }
522*288bf522SAndroid Build Coastguard Worker return StringPrintf("%" PRIu64 " B", bytes);
523*288bf522SAndroid Build Coastguard Worker }
524*288bf522SAndroid Build Coastguard Worker
525*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
526