diff --git a/deps/perfetto/BUILD.gn b/deps/perfetto/BUILD.gn new file mode 100644 index 00000000000000..df485c384d920a --- /dev/null +++ b/deps/perfetto/BUILD.gn @@ -0,0 +1,14 @@ +############################################################################## +# # +# DO NOT EDIT THIS FILE! # +# # +############################################################################## + +# This file is used by GN for building, which is NOT the build system used for +# building official binaries. +# Please modify the gyp files if you are making changes to build system. + +import("unofficial.gni") + +perfetto_sdk_gn_build("perfetto_sdk") { +} diff --git a/deps/perfetto/LICENSE b/deps/perfetto/LICENSE new file mode 100644 index 00000000000000..cbdc2881d57d5a --- /dev/null +++ b/deps/perfetto/LICENSE @@ -0,0 +1,265 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +------------------ + +Files: * except those files noted below + + Copyright (c) 2017, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + 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. + + +------------------ + +Files: src/trace_processor/perfetto_sql/stdlib/chromium/*, protos/third_party/chromium/*, test/trace_processor/diff_tests/stdlib/chrome/* + + Copyright 2015 The Chromium Authors + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +------------------ + +Files: src/trace_processor/perfetto_sql/preprocessor/preprocessor_grammar.{c, h} + +The author disclaims copyright to this source code. In place of a legal notice, here is a blessing: + +May you do good and not evil. +May you find forgiveness for yourself and forgive others. +May you share freely, never taking more than you give. + + +------------------ + +Files: src/base/intrusive_tree.cc + +$OpenBSD: tree.h,v 1.31 2023/03/08 04:43:09 guenther Exp $ + +Copyright 2002 Niels Provos +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/deps/perfetto/VERSION b/deps/perfetto/VERSION new file mode 100644 index 00000000000000..517ac763657c22 --- /dev/null +++ b/deps/perfetto/VERSION @@ -0,0 +1 @@ +54.0 diff --git a/deps/perfetto/perfetto.gyp b/deps/perfetto/perfetto.gyp new file mode 100644 index 00000000000000..3836f3424cbd0e --- /dev/null +++ b/deps/perfetto/perfetto.gyp @@ -0,0 +1,22 @@ +{ + 'variables': { + 'perfetto_sdk_sources': [ + 'sdk/perfetto.cc', + 'sdk/perfetto.h', + ] + }, + 'targets': [ + { + 'target_name': 'perfetto_sdk', + 'type': 'static_library', + 'include_dirs': [ 'sdk' ], + 'direct_dependent_settings': { + # Use like `#include "perfetto.h"` + 'include_dirs': [ 'sdk' ], + }, + 'sources': [ + '<@(perfetto_sdk_sources)', + ], + }, + ] +} diff --git a/deps/perfetto/sdk/perfetto.cc b/deps/perfetto/sdk/perfetto.cc new file mode 100644 index 00000000000000..2ccd11f7b8313d --- /dev/null +++ b/deps/perfetto/sdk/perfetto.cc @@ -0,0 +1,82755 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// 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. +// +// This file is automatically generated by gen_amalgamated. Do not edit. + +// gen_amalgamated: predefined macros +#if !defined(PERFETTO_IMPLEMENTATION) +#define PERFETTO_IMPLEMENTATION +#endif +#include "perfetto.h" +// gen_amalgamated begin source: src/base/default_platform.cc +// gen_amalgamated begin header: include/perfetto/ext/base/platform.h +/* + * Copyright (C) 2023 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_PLATFORM_H_ +#define INCLUDE_PERFETTO_EXT_BASE_PLATFORM_H_ + +namespace perfetto { +namespace base { +namespace platform { + +// Executed before entering a syscall (e.g. poll, read, write etc) which might +// block. +// This is overridden in Google internal builds for dealing with userspace +// scheduling. +void BeforeMaybeBlockingSyscall(); + +// Executed after entering a syscall (e.g. poll, read, write etc) which might +// block. +// This is overridden in Google internal builds for dealing with userspace +// scheduling. +void AfterMaybeBlockingSyscall(); + +} // namespace platform +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_PLATFORM_H_ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/platform.h" + +namespace perfetto { +namespace base { +namespace platform { + +// This is a no-op outside of Google3 where we have some custom logic to deal +// with the userspace scheduler. +void BeforeMaybeBlockingSyscall() {} + +// This is a no-op outside of Google3 where we have some custom logic to deal +// with the userspace scheduler. +void AfterMaybeBlockingSyscall() {} + +} // namespace platform +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/android_utils.cc +// gen_amalgamated begin header: include/perfetto/ext/base/android_utils.h +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_ANDROID_UTILS_H_ +#define INCLUDE_PERFETTO_EXT_BASE_ANDROID_UTILS_H_ + +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" + +namespace perfetto { +namespace base { + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + +// Returns the value of the Android system property named `name`. If the +// property does not exist, returns an empty string (a non-existing property is +// the same as a property with an empty value for this API). +std::string GetAndroidProp(const char* name); + +#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + +struct Utsname { + std::string sysname; + std::string version; + std::string machine; + std::string release; +}; + +struct SystemInfo { + std::optional timezone_off_mins; + std::optional utsname_info; + std::optional page_size; + std::optional num_cpus; + std::optional system_ram_bytes; + std::string android_build_fingerprint; + std::string android_device_manufacturer; + std::optional android_sdk_version; + std::string android_soc_model; + std::string android_guest_soc_model; + std::string android_hardware_revision; + std::string android_storage_model; + std::string android_ram_model; + std::string android_serial_console; +}; + +// Returns the device's utsname information. +Utsname GetUtsname(); + +// Returns the device's system information. +SystemInfo GetSystemInfo(); + +// Returns the perfetto machine name. The PERFETTO_MACHINE_NAME env variable +// has the highest precedence in setting the machine name. In Android systems, +// if the env variable isn't set then the traced.machine_name system property +// is used. If no value is externally set, then the OS system name +// (see `uname -s`) is used as the default machine name. +std::string GetPerfettoMachineName(); + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_ANDROID_UTILS_H_ +// gen_amalgamated begin header: include/perfetto/ext/base/string_utils.h +// gen_amalgamated begin header: include/perfetto/ext/base/string_view.h +// gen_amalgamated begin header: include/perfetto/ext/base/fnv_hash.h +/* + * Copyright (C) 2019 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_FNV_HASH_H_ +#define INCLUDE_PERFETTO_EXT_BASE_FNV_HASH_H_ + +#include +#include +#include +#include +#include + +namespace perfetto::base { + +// A helper class which computes a 64-bit hash of the input data. +// The algorithm used is FNV-1a as it is fast and easy to implement and has +// relatively few collisions. +// WARNING: This hash function should not be used for any cryptographic purpose. +class FnvHasher { + public: + // Creates an empty hash object + constexpr FnvHasher() = default; + + // Hashes a numeric value. + template < + typename T, + typename std::enable_if::value, bool>::type = true> + void Update(T data) { + Update(reinterpret_cast(&data), sizeof(data)); + } + + constexpr void Update(char c) { return Update(&c, 1); } + + // Using the loop instead of "Update(str, strlen(str))" to avoid looping twice + constexpr void Update(const char* str) { + for (const auto* p = str; *p; ++p) + Update(*p); + } + + // Hashes a byte array. + constexpr void Update(const char* data, size_t size) { + for (size_t i = 0; i < size; i++) { + result_ ^= static_cast(data[i]); + // Note: Arithmetic overflow of unsigned integers is well defined in C++ + // standard unlike signed integers. + // https://stackoverflow.com/a/41280273 + result_ *= kFnv1a64Prime; + } + } + + // Allow hashing anything that has `data` and `size` and has the kHashable + // trait (e.g., base::StringView). + template > + constexpr void Update(const T& t) { + if constexpr (std::is_member_function_pointer_v) { + Update(t.data(), t.size()); + } else { + Update(t.data, t.size); + } + } + + constexpr void Update(std::string_view s) { Update(s.data(), s.size()); } + + constexpr uint64_t digest() const { return result_; } + + // Usage: + // uint64_t hashed_value = + // FnvHasher::Combine(33, false, "ABC", 458L, 3u, 'x'); + template + static constexpr uint64_t Combine(Ts&&... args) { + FnvHasher hasher; + hasher.UpdateAll(std::forward(args)...); + return hasher.digest(); + } + + // Creates a hasher with `args` already hashed. + // + // Usage: + // FnvHasher partial = FnvHasher::CreatePartial(33, false, "ABC", 458L); + template + static constexpr FnvHasher CreatePartial(Ts&&... args) { + FnvHasher hasher; + hasher.UpdateAll(std::forward(args)...); + return hasher; + } + + // `hasher.UpdateAll(33, false, "ABC")` is shorthand for: + // `hasher.Update(33); hasher.Update(false); hasher.Update("ABC");` + constexpr void UpdateAll() {} + + template + constexpr void UpdateAll(T&& arg, Ts&&... args) { + Update(arg); + UpdateAll(std::forward(args)...); + } + + private: + static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325; + static constexpr uint64_t kFnv1a64Prime = 0x100000001b3; + + uint64_t result_ = kFnv1a64OffsetBasis; +}; + +// base::FnvHash uses base::FnvHasher for integer values and falls back to +// std::hash for other types. This is needed as std::hash for integers is just +// the identity function and Perfetto uses open-addressing hash table, which are +// very sensitive to hash quality and are known to degrade in performance +// when using std::hash. +template +struct FnvHash { + // Version for ints, using base::FnvHasher. + template + auto operator()(const U& x) -> + typename std::enable_if::value, size_t>::type + const { + return FnvHasher::Combine(x); + } + + // Version for non-ints, falling back to std::hash. + template + auto operator()(const U& x) -> + typename std::enable_if::value, size_t>::type + const { + return std::hash()(x); + } +}; + +} // namespace perfetto::base + +#endif // INCLUDE_PERFETTO_EXT_BASE_FNV_HASH_H_ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_ +#define INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_ + +#include + +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/fnv_hash.h" + +namespace perfetto { +namespace base { + +// A string-like object that refers to a non-owned piece of memory. +// Strings are internally NOT null terminated. +class StringView { + public: + // Allow hashing with base::FnvHash. + static constexpr bool kHashable = true; + static constexpr size_t npos = static_cast(-1); + + StringView() : data_(nullptr), size_(0) {} + StringView(const StringView&) = default; + StringView& operator=(const StringView&) = default; + StringView(const char* data, size_t size) : data_(data), size_(size) { + PERFETTO_DCHECK(size == 0 || data != nullptr); + } + + // Allow implicit conversion from any class that has a |data| and |size| field + // and has the kConvertibleToStringView trait (e.g., protozero::ConstChars). + template > + StringView(const T& x) : StringView(x.data, x.size) { + PERFETTO_DCHECK(x.size == 0 || x.data != nullptr); + } + + // Creates a StringView from a null-terminated C string. + // Deliberately not "explicit". + StringView(const char* cstr) : data_(cstr), size_(strlen(cstr)) { + PERFETTO_DCHECK(cstr != nullptr); + } + + StringView(std::string_view str) : data_(str.data()), size_(str.size()) {} + + // This instead has to be explicit, as creating a StringView out of a + // std::string can be subtle. + explicit StringView(const std::string& str) + : data_(str.data()), size_(str.size()) {} + + bool empty() const { return size_ == 0; } + size_t size() const { return size_; } + const char* data() const { return data_; } + const char* begin() const { return data_; } + const char* end() const { return data_ + size_; } + + char at(size_t pos) const { + PERFETTO_DCHECK(pos < size_); + return data_[pos]; + } + + size_t find(char c, size_t start_pos = 0) const { + for (size_t i = start_pos; i < size_; ++i) { + if (data_[i] == c) + return i; + } + return npos; + } + + size_t find(const StringView& str, size_t start_pos = 0) const { + if (start_pos > size()) + return npos; + auto it = std::search(begin() + start_pos, end(), str.begin(), str.end()); + size_t pos = static_cast(it - begin()); + return pos + str.size() <= size() ? pos : npos; + } + + size_t find(const char* str, size_t start_pos = 0) const { + return find(StringView(str), start_pos); + } + + size_t rfind(char c) const { + for (size_t i = size_; i > 0; --i) { + if (data_[i - 1] == c) + return i - 1; + } + return npos; + } + + StringView substr(size_t pos, size_t count = npos) const { + if (pos >= size_) + return StringView("", 0); + size_t rcount = std::min(count, size_ - pos); + return StringView(data_ + pos, rcount); + } + + bool CaseInsensitiveEq(const StringView& other) const { + if (size() != other.size()) + return false; + if (size() == 0) + return true; +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + return _strnicmp(data(), other.data(), size()) == 0; +#else + return strncasecmp(data(), other.data(), size()) == 0; +#endif + } + + bool CaseInsensitiveOneOf(const std::vector& others) const { + for (const StringView& other : others) { + if (CaseInsensitiveEq(other)) { + return true; + } + } + return false; + } + + bool StartsWith(const StringView& other) const { + if (other.size() == 0) + return true; + if (size() == 0) + return false; + if (other.size() > size()) + return false; + return memcmp(data(), other.data(), other.size()) == 0; + } + + bool EndsWith(const StringView& other) const { + if (other.size() == 0) + return true; + if (size() == 0) + return false; + if (other.size() > size()) + return false; + size_t off = size() - other.size(); + return memcmp(data() + off, other.data(), other.size()) == 0; + } + + std::string ToStdString() const { + return size_ == 0 ? "" : std::string(data_, size_); + } + + uint64_t Hash() const { + base::FnvHasher hasher; + hasher.Update(data_, size_); + return hasher.digest(); + } + + private: + const char* data_ = nullptr; + size_t size_ = 0; +}; + +inline bool operator==(const StringView& x, const StringView& y) { + if (x.size() != y.size()) + return false; + if (x.size() == 0) + return true; + return memcmp(x.data(), y.data(), x.size()) == 0; +} + +inline bool operator!=(const StringView& x, const StringView& y) { + return !(x == y); +} + +inline bool operator<(const StringView& x, const StringView& y) { + auto size = std::min(x.size(), y.size()); + if (size == 0) + return x.size() < y.size(); + int result = memcmp(x.data(), y.data(), size); + return result < 0 || (result == 0 && x.size() < y.size()); +} + +inline bool operator>=(const StringView& x, const StringView& y) { + return !(x < y); +} + +inline bool operator>(const StringView& x, const StringView& y) { + return y < x; +} + +inline bool operator<=(const StringView& x, const StringView& y) { + return !(y < x); +} + +} // namespace base +} // namespace perfetto + +template <> +struct std::hash<::perfetto::base::StringView> { + size_t operator()(const ::perfetto::base::StringView& sv) const { + return static_cast(sv.Hash()); + } +}; + +#endif // INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_ +#define INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h" + +namespace perfetto { +namespace base { + +inline char Lowercase(char c) { + return ('A' <= c && c <= 'Z') ? static_cast(c - ('A' - 'a')) : c; +} + +inline char Uppercase(char c) { + return ('a' <= c && c <= 'z') ? static_cast(c + ('A' - 'a')) : c; +} + +// Returns true if the character is an ASCII whitespace character. +// This is a locale-independent version that only considers ASCII whitespace: +// space (0x20), tab (0x09), newline (0x0A), vertical tab (0x0B), +// form feed (0x0C), and carriage return (0x0D). +inline bool IsSpace(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || + c == '\r'; +} + +inline std::optional CStringToUInt32(const char* s, int base = 10) { + char* endptr = nullptr; + auto value = static_cast(strtoul(s, &endptr, base)); + return (*s && !*endptr) ? std::make_optional(value) : std::nullopt; +} + +inline std::optional CStringToInt32(const char* s, int base = 10) { + char* endptr = nullptr; + auto value = static_cast(strtol(s, &endptr, base)); + return (*s && !*endptr) ? std::make_optional(value) : std::nullopt; +} + +// Note: it saturates to 7fffffffffffffff if parsing a hex number >= 0x8000... +inline std::optional CStringToInt64(const char* s, int base = 10) { + char* endptr = nullptr; + auto value = static_cast(strtoll(s, &endptr, base)); + return (*s && !*endptr) ? std::make_optional(value) : std::nullopt; +} + +inline std::optional CStringToUInt64(const char* s, int base = 10) { + char* endptr = nullptr; + auto value = static_cast(strtoull(s, &endptr, base)); + return (*s && !*endptr) ? std::make_optional(value) : std::nullopt; +} + +double StrToD(const char* nptr, char** endptr); + +inline std::optional CStringToDouble(const char* s) { + char* endptr = nullptr; + double value = StrToD(s, &endptr); + std::optional result(std::nullopt); + if (*s != '\0' && *endptr == '\0') + result = value; + return result; +} + +inline std::optional StringToUInt32(const std::string& s, + int base = 10) { + return CStringToUInt32(s.c_str(), base); +} + +inline std::optional StringToInt32(const std::string& s, + int base = 10) { + return CStringToInt32(s.c_str(), base); +} + +inline std::optional StringToUInt64(const std::string& s, + int base = 10) { + return CStringToUInt64(s.c_str(), base); +} + +inline std::optional StringToInt64(const std::string& s, + int base = 10) { + return CStringToInt64(s.c_str(), base); +} + +inline std::optional StringToDouble(const std::string& s) { + return CStringToDouble(s.c_str()); +} + +template +inline std::optional StringViewToNumber(const base::StringView& sv, + int base = 10) { + // std::from_chars() does not regonize the leading '+' character and only + // recognizes '-' so remove the '+' if it exists to avoid errors and match + // the behavior of the other string conversion utilities above. + size_t start_offset = !sv.empty() && sv.at(0) == '+' ? 1 : 0; + T value; + auto result = + std::from_chars(sv.begin() + start_offset, sv.end(), value, base); + if (result.ec == std::errc() && result.ptr == sv.end()) { + return value; + } else { + return std::nullopt; + } +} + +inline std::optional StringViewToUInt32(const base::StringView& sv, + int base = 10) { + // std::from_chars() does not recognize the leading '-' character for + // unsigned conversions, but strtol does. To Mimic the behavior of strtol, + // attempt a signed converion if we see a leading '-', and then cast the + // result back to unsigned. + if (sv.size() > 0 && sv.at(0) == '-') { + return static_cast >( + StringViewToNumber(sv, base)); + } else { + return StringViewToNumber(sv, base); + } +} + +inline std::optional StringViewToInt32(const base::StringView& sv, + int base = 10) { + return StringViewToNumber(sv, base); +} + +inline std::optional StringViewToUInt64(const base::StringView& sv, + int base = 10) { + // std::from_chars() does not recognize the leading '-' character for + // unsigned conversions, but strtol does. To Mimic the behavior of strtol, + // attempt a signed converion if we see a leading '-', and then cast the + // result back to unsigned. + if (sv.size() > 0 && sv.at(0) == '-') { + return static_cast >( + StringViewToNumber(sv, base)); + } else { + return StringViewToNumber(sv, base); + } +} + +inline std::optional StringViewToInt64(const base::StringView& sv, + int base = 10) { + return StringViewToNumber(sv, base); +} + +// TODO: As of Clang 19.0 std::from_chars is unimplemented for type double +// despite being part of C++17 standard, and already being supported by GCC and +// MSVC. Enable this once we have double support in Clang. +// inline std::optional StringViewToDouble(const base::StringView& sv) { +// return StringViewToNumber(sv); +// } + +bool StartsWith(const std::string& str, const std::string& prefix); +bool EndsWith(const std::string& str, const std::string& suffix); +bool StartsWithAny(const std::string& str, + const std::vector& prefixes); +bool Contains(const std::string& haystack, const std::string& needle); +bool Contains(const std::string& haystack, char needle); +bool Contains(const std::vector& haystack, + const std::string& needle); +size_t Find(const StringView& needle, const StringView& haystack); +bool CaseInsensitiveEqual(const std::string& first, const std::string& second); +std::string Join(const std::vector& parts, + const std::string& delim); +std::vector SplitString(const std::string& text, + const std::string& delimiter); +std::string StripPrefix(const std::string& str, const std::string& prefix); +std::string StripSuffix(const std::string& str, const std::string& suffix); +std::string TrimWhitespace(const std::string& str); +std::string ToLower(const std::string& str); +std::string ToUpper(const std::string& str); +std::string StripChars(const std::string& str, + const std::string& chars, + char replacement); +std::string ToHex(const char* data, size_t size); +inline std::string ToHex(const std::string& s) { + return ToHex(s.c_str(), s.size()); +} +std::string IntToHexString(uint32_t number); +std::string Uint64ToHexString(uint64_t number); +std::string Uint64ToHexStringNoPrefix(uint64_t number); +std::string ReplaceAll(std::string str, + const std::string& to_replace, + const std::string& replacement); + +// Checks if all characters in the input string view `str` are ASCII. +// +// If so, the function returns true and `output` is not modified. +// If `str` contains non-ASCII characters, the function returns false, +// removes invalid UTF-8 characters from `str`, and stores the result in +// `output`. +bool CheckAsciiAndRemoveInvalidUTF8(base::StringView str, std::string& output); + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +bool WideToUTF8(const std::wstring& source, std::string& output); +bool UTF8ToWide(const std::string& source, std::wstring& output); +#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + +// A BSD-style strlcpy without the return value. +// Copies at most |dst_size|-1 characters. Unlike strncpy, it always \0 +// terminates |dst|, as long as |dst_size| is not 0. +// Unlike strncpy and like strlcpy it does not zero-pad the rest of |dst|. +// Returns nothing. The BSD strlcpy returns the size of |src|, which might +// be > |dst_size|. Anecdotal experience suggests people assume the return value +// is the number of bytes written in |dst|. That assumption can lead to +// dangerous bugs. +// In order to avoid being subtly uncompliant with strlcpy AND avoid misuse, +// the choice here is to return nothing. +inline void StringCopy(char* dst, const char* src, size_t dst_size) { + for (size_t i = 0; i < dst_size; ++i) { + if ((dst[i] = src[i]) == '\0') { + return; // We hit and copied the null terminator. + } + } + + // We were left off at dst_size. We over copied 1 byte. Null terminate. + if (PERFETTO_LIKELY(dst_size > 0)) + dst[dst_size - 1] = 0; +} + +// Like snprintf() but returns the number of chars *actually* written (without +// counting the null terminator) NOT "the number of chars which would have been +// written to the final string if enough space had been available". +// This should be used in almost all cases when the caller uses the return value +// of snprintf(). If the return value is not used, there is no benefit in using +// this wrapper, as this just calls snprintf() and mangles the return value. +// It always null-terminates |dst| (even in case of errors), unless +// |dst_size| == 0. +// Examples: +// SprintfTrunc(x, 4, "123whatever"): returns 3 and writes "123\0". +// SprintfTrunc(x, 4, "123"): returns 3 and writes "123\0". +// SprintfTrunc(x, 3, "123"): returns 2 and writes "12\0". +// SprintfTrunc(x, 2, "123"): returns 1 and writes "1\0". +// SprintfTrunc(x, 1, "123"): returns 0 and writes "\0". +// SprintfTrunc(x, 0, "123"): returns 0 and writes nothing. +// NOTE: This means that the caller has no way to tell when truncation happens +// vs the edge case of *just* fitting in the buffer. +size_t SprintfTrunc(char* dst, size_t dst_size, const char* fmt, ...) + PERFETTO_PRINTF_FORMAT(3, 4); + +// Line number starts from 1 +struct LineWithOffset { + base::StringView line; + uint32_t line_offset; + uint32_t line_num; +}; + +// For given string and offset Pfinds a line with character for +// which offset points, what number is this line (starts from 1), and the offset +// inside this line. returns std::nullopt if the offset points to +// line break character or exceeds string length. +std::optional FindLineWithOffset(base::StringView str, + uint32_t offset); + +// A helper class to facilitate construction and usage of write-once stack +// strings. +// Example usage: +// StackString<32> x("format %d %s", 42, string_arg); +// TakeString(x.c_str() | x.string_view() | x.ToStdString()); +// Rather than char x[32] + sprintf. +// Advantages: +// - Avoids useless zero-fills caused by people doing `char buf[32] {}` (mainly +// by fearing unknown snprintf failure modes). +// - Makes the code more robust in case of snprintf truncations (len() and +// string_view() will return the truncated length, unlike snprintf). +template +class StackString { + public: + explicit PERFETTO_PRINTF_FORMAT(/* 1=this */ 2, 3) + StackString(const char* fmt, ...) { + buf_[0] = '\0'; + va_list args; + va_start(args, fmt); + int res = vsnprintf(buf_, sizeof(buf_), fmt, args); + va_end(args); + buf_[sizeof(buf_) - 1] = '\0'; + len_ = res < 0 ? 0 : std::min(static_cast(res), sizeof(buf_) - 1); + } + + StringView string_view() const { return StringView(buf_, len_); } + std::string ToStdString() const { return std::string(buf_, len_); } + const char* c_str() const { return buf_; } + size_t len() const { return len_; } + char* mutable_data() { return buf_; } + + private: + char buf_[N]; + size_t len_ = 0; // Does not include the \0. +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/android_utils.h" + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" + +#include + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) +#include +#endif + +// gen_amalgamated expanded: #include "perfetto/base/compiler.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/base/time.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h" + +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) +#include +#include +#endif + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) +#include +#endif + +namespace perfetto { +namespace base { + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + +std::string GetAndroidProp(const char* name) { + std::string ret; +#if __ANDROID_API__ >= 26 + const prop_info* pi = __system_property_find(name); + if (!pi) { + return ret; + } + __system_property_read_callback( + pi, + [](void* dst_void, const char*, const char* value, uint32_t) { + std::string& dst = *static_cast(dst_void); + dst = value; + }, + &ret); +#else // __ANDROID_API__ < 26 + char value_buf[PROP_VALUE_MAX]; + int len = __system_property_get(name, value_buf); + if (len > 0 && static_cast(len) < sizeof(value_buf)) { + ret = std::string(value_buf, static_cast(len)); + } +#endif + return ret; +} + +#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + +Utsname GetUtsname() { + Utsname utsname_info; +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) + struct utsname uname_info; + if (uname(&uname_info) == 0) { + utsname_info.sysname = uname_info.sysname; + utsname_info.version = uname_info.version; + utsname_info.machine = uname_info.machine; + utsname_info.release = uname_info.release; + } else { + PERFETTO_ELOG("Unable to read Utsname information"); + } +#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + return utsname_info; +} + +SystemInfo GetSystemInfo() { + SystemInfo info; + + info.timezone_off_mins = GetTimezoneOffsetMins(); + +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_WASM) + + info.utsname_info = GetUtsname(); + info.page_size = static_cast(sysconf(_SC_PAGESIZE)); + info.num_cpus = static_cast(sysconf(_SC_NPROCESSORS_CONF)); + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + // Use the Linux-specific sysinfo() system call on Linux and Android. + // https://man7.org/linux/man-pages/man2/sysinfo.2.html + struct sysinfo sys_info; + if (sysinfo(&sys_info) == 0) { + info.system_ram_bytes = + static_cast(sys_info.totalram) * sys_info.mem_unit; + } +#else + // POSIX Fallback (macOS, BSD, etc.): Use sysconf() to get physical pages. + long pages = sysconf(_SC_PHYS_PAGES); + if (pages > 0 && info.page_size.has_value()) { + info.system_ram_bytes = static_cast(pages) * (*info.page_size); + } +#endif +#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + info.android_build_fingerprint = GetAndroidProp("ro.build.fingerprint"); + if (info.android_build_fingerprint.empty()) { + PERFETTO_ELOG("Unable to read ro.build.fingerprint"); + } + + info.android_device_manufacturer = GetAndroidProp("ro.product.manufacturer"); + if (info.android_device_manufacturer.empty()) { + PERFETTO_ELOG("Unable to read ro.product.manufacturer"); + } + + std::string sdk_str_value = GetAndroidProp("ro.build.version.sdk"); + info.android_sdk_version = StringToUInt64(sdk_str_value); + if (!info.android_sdk_version.has_value()) { + PERFETTO_ELOG("Unable to read ro.build.version.sdk"); + } + + info.android_soc_model = GetAndroidProp("ro.soc.model"); + if (info.android_soc_model.empty()) { + PERFETTO_ELOG("Unable to read ro.soc.model"); + } + + // guest_soc model is not always present + info.android_guest_soc_model = GetAndroidProp("ro.boot.guest_soc.model"); + + info.android_hardware_revision = GetAndroidProp("ro.boot.hardware.revision"); + if (info.android_hardware_revision.empty()) { + PERFETTO_ELOG("Unable to read ro.boot.hardware.revision"); + } + + info.android_storage_model = GetAndroidProp("ro.boot.hardware.ufs"); + if (info.android_storage_model.empty()) { + PERFETTO_ELOG("Unable to read ro.boot.hardware.ufs"); + } + + info.android_ram_model = GetAndroidProp("ro.boot.hardware.ddr"); + if (info.android_ram_model.empty()) { + PERFETTO_ELOG("Unable to read ro.boot.hardware.ddr"); + } + + info.android_serial_console = GetAndroidProp("init.svc.console"); + if (info.android_serial_console.empty()) { + PERFETTO_ELOG("Unable to read init.svc.console"); + } +#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + + return info; +} + +std::string GetPerfettoMachineName() { + const char* env_name = getenv("PERFETTO_MACHINE_NAME"); + if (env_name) { + return env_name; + } +#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + std::string name = base::GetAndroidProp("traced.machine_name"); + if (name.empty()) { + name = GetUtsname().sysname; + } + return name; +#else + return GetUtsname().sysname; +#endif +} + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/base64.cc +// gen_amalgamated begin header: include/perfetto/ext/base/base64.h +// gen_amalgamated begin header: include/perfetto/ext/base/utils.h +// gen_amalgamated begin header: include/perfetto/ext/base/sys_types.h +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_SYS_TYPES_H_ +#define INCLUDE_PERFETTO_EXT_BASE_SYS_TYPES_H_ + +// This headers deals with sys types commonly used in the codebase that are +// missing on Windows. + +#include // IWYU pragma: export +#include + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + +#ifdef __MINGW32__ + +using uid_t = int; +using gid_t = int; + +#else + +#if !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC) +// MinGW has these. clang-cl and MSVC, which use just the Windows SDK, don't. +using uid_t = int; +using gid_t = int; +using pid_t = int; +#endif // !GCC + +#if defined(_WIN64) +using ssize_t = int64_t; +#else +using ssize_t = long; +#endif // _WIN64 + +#endif // __MINGW32__ + +#endif // OS_WIN + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) +// From libcutils' android_filesystem_config.h +#ifndef AID_ROOT +#define AID_ROOT 0 +#endif +#ifndef AID_STATSD +#define AID_STATSD 1066 +#endif +#ifndef AID_SHELL +#define AID_SHELL 2000 +#endif +#endif + +namespace perfetto { +namespace base { + +// The machine ID used in the tracing core. +using MachineID = uint32_t; +// The default value reserved for the host trace. +constexpr MachineID kDefaultMachineID = 0; + +constexpr uid_t kInvalidUid = static_cast(-1); +constexpr pid_t kInvalidPid = static_cast(-1); + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_SYS_TYPES_H_ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_UTILS_H_ +#define INCLUDE_PERFETTO_EXT_BASE_UTILS_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" +// gen_amalgamated expanded: #include "perfetto/base/compiler.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h" + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +// Even if Windows has errno.h, the all syscall-restart behavior does not apply. +// Trying to handle EINTR can cause more harm than good if errno is left stale. +// Chromium does the same. +#define PERFETTO_EINTR(x) (x) +#else +#define PERFETTO_EINTR(x) \ + ([&] { \ + decltype(x) eintr_wrapper_result; \ + do { \ + eintr_wrapper_result = (x); \ + } while (eintr_wrapper_result == -1 && errno == EINTR); \ + return eintr_wrapper_result; \ + }()) +#endif + +namespace perfetto { +namespace base { + +namespace internal { +extern std::atomic g_cached_page_size; +uint32_t GetSysPageSizeSlowpath(); +} // namespace internal + +// Returns the system's page size. Use this when dealing with mmap, madvise and +// similar mm-related syscalls. +// This function might be called in hot paths. Avoid calling getpagesize() all +// the times, in many implementations getpagesize() calls sysconf() which is +// not cheap. +inline uint32_t GetSysPageSize() { + const uint32_t page_size = + internal::g_cached_page_size.load(std::memory_order_relaxed); + return page_size != 0 ? page_size : internal::GetSysPageSizeSlowpath(); +} + +template +constexpr size_t ArraySize(const T (&)[TSize]) { + return TSize; +} + +// Function object which invokes 'free' on its parameter, which must be +// a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr: +// +// std::unique_ptr foo_ptr( +// static_cast(malloc(sizeof(int)))); +struct FreeDeleter { + inline void operator()(void* ptr) const { free(ptr); } +}; + +template +constexpr T AssumeLittleEndian(T value) { +#if !PERFETTO_IS_LITTLE_ENDIAN() + static_assert(false, "Unimplemented on big-endian archs"); +#endif + return value; +} + +// Round up |size| to a multiple of |alignment| (must be a power of two). +inline constexpr size_t AlignUp(size_t size, size_t alignment) { + return (size + alignment - 1) & ~(alignment - 1); +} + +// TODO(primiano): clean this up and move all existing usages to the constexpr +// version above. +template +constexpr size_t AlignUp(size_t size) { + static_assert((alignment & (alignment - 1)) == 0, "alignment must be a pow2"); + return AlignUp(size, alignment); +} + +inline bool IsAgain(int err) { + return err == EAGAIN || err == EWOULDBLOCK; +} + +// setenv(2)-equivalent. Deals with Windows vs Posix discrepancies. +void SetEnv(const std::string& key, const std::string& value); + +// unsetenv(2)-equivalent. Deals with Windows vs Posix discrepancies. +void UnsetEnv(const std::string& key); + +// Calls mallopt(M_PURGE, 0) on Android. Does nothing on other platforms. +// This forces the allocator to release freed memory. This is used to work +// around various Scudo inefficiencies. See b/170217718. +void MaybeReleaseAllocatorMemToOS(); + +// geteuid() on POSIX OSes, returns 0 on Windows (See comment in utils.cc). +uid_t GetCurrentUserId(); + +// Forks the process. +// Parent: prints the PID of the child, calls |parent_cb| and exits from the +// process with its return value. +// Child: redirects stdio onto /dev/null, chdirs into / and returns. +void Daemonize(std::function parent_cb); + +// Returns the path of the current executable, e.g. /foo/bar/exe. +std::string GetCurExecutablePath(); + +// Returns the directory where the current executable lives in, e.g. /foo/bar. +// This is independent of cwd(). +std::string GetCurExecutableDir(); + +// Memory returned by AlignedAlloc() must be freed via AlignedFree() not just +// free. It makes a difference on Windows where _aligned_malloc() and +// _aligned_free() must be paired. +// Prefer using the AlignedAllocTyped() below which takes care of the pairing. +void* AlignedAlloc(size_t alignment, size_t size); +void AlignedFree(void*); + +// Detects Sync-mode MTE (currently being tested in some Android builds). +// This is known to use extra memory for the stack history buffer. +bool IsSyncMemoryTaggingEnabled(); + +// A RAII version of the above, which takes care of pairing Aligned{Alloc,Free}. +template +struct AlignedDeleter { + inline void operator()(T* ptr) const { AlignedFree(ptr); } +}; + +// The remove_extent here and below is to allow defining unique_ptr. +// As per https://en.cppreference.com/w/cpp/memory/unique_ptr the Deleter takes +// always a T*, not a T[]*. +template +using AlignedUniquePtr = + std::unique_ptr::type>>; + +template +AlignedUniquePtr AlignedAllocTyped(size_t n_membs) { + using TU = typename std::remove_extent::type; + return AlignedUniquePtr( + static_cast(AlignedAlloc(alignof(TU), sizeof(TU) * n_membs))); +} + +// A RAII wrapper to invoke a function when leaving a function/scope. +template +class OnScopeExitWrapper { + public: + explicit OnScopeExitWrapper(Func f) : f_(std::move(f)), active_(true) {} + OnScopeExitWrapper(OnScopeExitWrapper&& other) noexcept + : f_(std::move(other.f_)), active_(other.active_) { + other.active_ = false; + } + ~OnScopeExitWrapper() { + if (active_) + f_(); + } + + private: + Func f_; + bool active_; +}; + +template +PERFETTO_WARN_UNUSED_RESULT OnScopeExitWrapper OnScopeExit(Func f) { + return OnScopeExitWrapper(std::move(f)); +} + +// Returns a xxd-style hex dump (hex + ascii chars) of the input data. +std::string HexDump(const void* data, size_t len, size_t bytes_per_line = 16); +inline std::string HexDump(const std::string& data, + size_t bytes_per_line = 16) { + return HexDump(data.data(), data.size(), bytes_per_line); +} + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_UTILS_H_ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_BASE64_H_ +#define INCLUDE_PERFETTO_EXT_BASE_BASE64_H_ + +#include +#include + +// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h" // For ssize_t. + +namespace perfetto { +namespace base { + +// Returns the length of the destination string (included '=' padding). +// Does NOT include the size of the string null terminator. +inline size_t Base64EncSize(size_t src_size) { + return (src_size + 2) / 3 * 4; +} + +// Returns the upper bound on the length of the destination buffer. +// The actual decoded length might be <= the number returned here. +inline size_t Base64DecSize(size_t src_size) { + return (src_size + 3) / 4 * 3; +} + +// Does NOT null-terminate |dst|. +ssize_t Base64Encode(const void* src, + size_t src_size, + char* dst, + size_t dst_size); + +std::string Base64Encode(const void* src, size_t src_size); + +inline std::string Base64Encode(StringView sv) { + return Base64Encode(sv.data(), sv.size()); +} + +// Returns -1 in case of failure. +ssize_t Base64Decode(const char* src, + size_t src_size, + uint8_t* dst, + size_t dst_size); + +std::optional Base64Decode(const char* src, size_t src_size); + +inline std::optional Base64Decode(StringView sv) { + return Base64Decode(sv.data(), sv.size()); +} + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_BASE64_H_ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/base64.h" + +namespace perfetto { +namespace base { + +namespace { + +constexpr char kPadding = '='; + +constexpr char kEncTable[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static_assert(sizeof(kEncTable) == (1u << 6) + sizeof('\0'), "Bad table size"); + +// Maps an ASCII character to its 6-bit value. It only contains translations +// from '+' to 'z'. Supports the standard (+/) and URL-safe (-_) alphabets. +constexpr uint8_t kX = 0xff; // Value used for invalid characters +constexpr uint8_t kDecTable[] = { + 62, kX, 62, kX, 63, 52, 53, 54, 55, 56, // 00 - 09 + 57, 58, 59, 60, 61, kX, kX, kX, 0, kX, // 10 - 19 + kX, kX, 0, 1, 2, 3, 4, 5, 6, 7, // 20 - 29 + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // 30 - 39 + 18, 19, 20, 21, 22, 23, 24, 25, kX, kX, // 40 - 49 + kX, kX, 63, kX, 26, 27, 28, 29, 30, 31, // 50 - 59 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, // 60 - 69 + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 70 - 79 +}; +constexpr char kMinDecChar = '+'; +constexpr char kMaxDecChar = 'z'; +static_assert(kMaxDecChar - kMinDecChar <= sizeof(kDecTable), "Bad table size"); + +inline uint8_t DecodeChar(char c) { + if (c < kMinDecChar || c > kMaxDecChar) + return kX; + return kDecTable[c - kMinDecChar]; +} + +} // namespace + +ssize_t Base64Encode(const void* src, + size_t src_size, + char* dst, + size_t dst_size) { + const size_t padded_dst_size = Base64EncSize(src_size); + if (dst_size < padded_dst_size) + return -1; // Not enough space in output. + + const uint8_t* rd = static_cast(src); + const uint8_t* const end = rd + src_size; + size_t wr_size = 0; + while (rd < end) { + uint8_t s[3]{}; + s[0] = *(rd++); + dst[wr_size++] = kEncTable[s[0] >> 2]; + + uint8_t carry0 = static_cast((s[0] & 0x03) << 4); + if (PERFETTO_LIKELY(rd < end)) { + s[1] = *(rd++); + dst[wr_size++] = kEncTable[carry0 | (s[1] >> 4)]; + } else { + dst[wr_size++] = kEncTable[carry0]; + dst[wr_size++] = kPadding; + dst[wr_size++] = kPadding; + break; + } + + uint8_t carry1 = static_cast((s[1] & 0x0f) << 2); + if (PERFETTO_LIKELY(rd < end)) { + s[2] = *(rd++); + dst[wr_size++] = kEncTable[carry1 | (s[2] >> 6)]; + } else { + dst[wr_size++] = kEncTable[carry1]; + dst[wr_size++] = kPadding; + break; + } + + dst[wr_size++] = kEncTable[s[2] & 0x3f]; + } + PERFETTO_DCHECK(wr_size == padded_dst_size); + return static_cast(padded_dst_size); +} + +std::string Base64Encode(const void* src, size_t src_size) { + std::string dst; + dst.resize(Base64EncSize(src_size)); + auto res = Base64Encode(src, src_size, &dst[0], dst.size()); + PERFETTO_CHECK(res == static_cast(dst.size())); + return dst; +} + +ssize_t Base64Decode(const char* src, + size_t src_size, + uint8_t* dst, + size_t dst_size) { + const size_t min_dst_size = Base64DecSize(src_size); + if (dst_size < min_dst_size) + return -1; + + const char* rd = src; + const char* const end = src + src_size; + size_t wr_size = 0; + + char s[4]{}; + while (rd < end) { + uint8_t d[4]; + for (uint32_t j = 0; j < 4; j++) { + // Padding is only feasible for the last 2 chars of each group of 4. + s[j] = rd < end ? *(rd++) : (j < 2 ? '\0' : kPadding); + d[j] = DecodeChar(s[j]); + if (d[j] == kX) + return -1; // Invalid input char. + } + dst[wr_size] = static_cast((d[0] << 2) | (d[1] >> 4)); + dst[wr_size + 1] = static_cast((d[1] << 4) | (d[2] >> 2)); + dst[wr_size + 2] = static_cast((d[2] << 6) | (d[3])); + wr_size += 3; + } + + PERFETTO_CHECK(wr_size <= dst_size); + wr_size -= (s[3] == kPadding ? 1 : 0) + (s[2] == kPadding ? 1 : 0); + return static_cast(wr_size); +} + +std::optional Base64Decode(const char* src, size_t src_size) { + std::string dst; + dst.resize(Base64DecSize(src_size)); + auto res = Base64Decode(src, src_size, reinterpret_cast(&dst[0]), + dst.size()); + if (res < 0) + return std::nullopt; // Decoding error. + + PERFETTO_CHECK(res <= static_cast(dst.size())); + dst.resize(static_cast(res)); + return std::make_optional(dst); +} + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/crash_keys.cc +// gen_amalgamated begin header: include/perfetto/ext/base/crash_keys.h +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_CRASH_KEYS_H_ +#define INCLUDE_PERFETTO_EXT_BASE_CRASH_KEYS_H_ + +#include +#include + +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/compiler.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h" + +// Crash keys are very simple global variables with static-storage that +// are reported on crash time for managed crashes (CHECK/FATAL/Watchdog). +// - Translation units can define a CrashKey and register it at some point +// during initialization. +// - CrashKey instances must be long-lived. They should really be just global +// static variable in the anonymous namespace. +// Example: +// subsystem_1.cc +// CrashKey g_client_id("ipc_client_id"); +// ... +// OnIpcReceived(client_id) { +// g_client_id.Set(client_id); +// ... // Process the IPC +// g_client_id.Clear(); +// } +// Or equivalently: +// OnIpcReceived(client_id) { +// auto scoped_key = g_client_id.SetScoped(client_id); +// ... // Process the IPC +// } +// +// If a crash happens while processing the IPC, the crash report will +// have a line "ipc_client_id: 42". +// +// Thread safety considerations: +// CrashKeys can be registered and set/cleared from any thread. +// There is no compelling use-case to have full acquire/release consistency when +// setting a key. This means that if a thread crashes immediately after a +// crash key has been set on another thread, the value printed on the crash +// report could be incomplete. The code guarantees defined behavior and does +// not rely on null-terminated string (in the worst case 32 bytes of random +// garbage will be printed out). + +// The tests live in logging_unittest.cc. + +namespace perfetto { +namespace base { + +constexpr size_t kCrashKeyMaxStrSize = 32; + +// CrashKey instances must be long lived +class CrashKey { + public: + class ScopedClear { + public: + explicit ScopedClear(CrashKey* k) : key_(k) {} + ~ScopedClear() { + if (key_) + key_->Clear(); + } + ScopedClear(const ScopedClear&) = delete; + ScopedClear& operator=(const ScopedClear&) = delete; + ScopedClear& operator=(ScopedClear&&) = delete; + ScopedClear(ScopedClear&& other) noexcept : key_(other.key_) { + other.key_ = nullptr; + } + + private: + CrashKey* key_; + }; + + // constexpr so it can be used in the anon namespace without requiring a + // global constructor. + // |name| must be a long-lived string. + constexpr explicit CrashKey(const char* name) + : registered_{}, type_(Type::kUnset), name_(name), str_value_{} {} + CrashKey(const CrashKey&) = delete; + CrashKey& operator=(const CrashKey&) = delete; + CrashKey(CrashKey&&) = delete; + CrashKey& operator=(CrashKey&&) = delete; + + enum class Type : uint8_t { kUnset = 0, kInt, kStr }; + + void Clear() { + int_value_.store(0, std::memory_order_relaxed); + type_.store(Type::kUnset, std::memory_order_relaxed); + } + + void Set(int64_t value) { + int_value_.store(value, std::memory_order_relaxed); + type_.store(Type::kInt, std::memory_order_relaxed); + if (PERFETTO_UNLIKELY(!registered_.load(std::memory_order_relaxed))) + Register(); + } + + void Set(StringView sv) { + size_t len = std::min(sv.size(), sizeof(str_value_) - 1); + for (size_t i = 0; i < len; ++i) + str_value_[i].store(sv.data()[i], std::memory_order_relaxed); + str_value_[len].store('\0', std::memory_order_relaxed); + type_.store(Type::kStr, std::memory_order_relaxed); + if (PERFETTO_UNLIKELY(!registered_.load(std::memory_order_relaxed))) + Register(); + } + + ScopedClear SetScoped(int64_t value) PERFETTO_WARN_UNUSED_RESULT { + Set(value); + return ScopedClear(this); + } + + ScopedClear SetScoped(StringView sv) PERFETTO_WARN_UNUSED_RESULT { + Set(sv); + return ScopedClear(this); + } + + void Register(); + + int64_t int_value() const { + return int_value_.load(std::memory_order_relaxed); + } + size_t ToString(char* dst, size_t len); + + private: + std::atomic registered_; + std::atomic type_; + const char* const name_; + union { + std::atomic str_value_[kCrashKeyMaxStrSize]; + std::atomic int_value_; + }; +}; + +// Fills |dst| with a string containing one line for each crash key +// (excluding the unset ones). +// Returns number of chars written, without counting the NUL terminator. +// This is used in logging.cc when emitting the crash report abort message. +size_t SerializeCrashKeys(char* dst, size_t len); + +void UnregisterAllCrashKeysForTesting(); + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_CRASH_KEYS_H_ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/crash_keys.h" + +#include + +#include +#include + +// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h" + +namespace perfetto { +namespace base { + +namespace { + +constexpr size_t kMaxKeys = 32; + +std::atomic g_keys[kMaxKeys]{}; +std::atomic g_num_keys{}; +} // namespace + +void CrashKey::Register() { + // If doesn't matter if we fail below. If there are no slots left, don't + // keep trying re-registering on every Set(), the outcome won't change. + + // If two threads raced on the Register(), avoid registering the key twice. + if (registered_.exchange(true)) + return; + + uint32_t slot = g_num_keys.fetch_add(1); + if (slot >= kMaxKeys) { + PERFETTO_LOG("Too many crash keys registered"); + return; + } + g_keys[slot].store(this); +} + +// Returns the number of chars written, without counting the \0. +size_t CrashKey::ToString(char* dst, size_t len) { + if (len > 0) + *dst = '\0'; + switch (type_.load(std::memory_order_relaxed)) { + case Type::kUnset: + break; + case Type::kInt: + return SprintfTrunc(dst, len, "%s: %" PRId64 "\n", name_, + int_value_.load(std::memory_order_relaxed)); + case Type::kStr: + char buf[sizeof(str_value_)]; + for (size_t i = 0; i < sizeof(str_value_); i++) + buf[i] = str_value_[i].load(std::memory_order_relaxed); + + // Don't assume |str_value_| is properly null-terminated. + return SprintfTrunc(dst, len, "%s: %.*s\n", name_, int(sizeof(buf)), buf); + } + return 0; +} + +void UnregisterAllCrashKeysForTesting() { + g_num_keys.store(0); + for (auto& key : g_keys) + key.store(nullptr); +} + +size_t SerializeCrashKeys(char* dst, size_t len) { + size_t written = 0; + uint32_t num_keys = g_num_keys.load(); + if (len > 0) + *dst = '\0'; + for (uint32_t i = 0; i < num_keys && written < len; i++) { + CrashKey* key = g_keys[i].load(); + if (!key) + continue; // Can happen if we hit this between the add and the store. + written += key->ToString(dst + written, len - written); + } + PERFETTO_DCHECK(written <= len); + PERFETTO_DCHECK(len == 0 || dst[written] == '\0'); + return written; +} + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/ctrl_c_handler.cc +// gen_amalgamated begin header: include/perfetto/ext/base/ctrl_c_handler.h +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_ +#define INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_ + +namespace perfetto { +namespace base { + +// On Linux/Android/Mac: installs SIGINT + SIGTERM signal handlers. +// On Windows: installs a SetConsoleCtrlHandler() handler. +// The passed handler must be async safe. +using CtrlCHandlerFunction = void (*)(); +void InstallCtrlCHandler(CtrlCHandlerFunction); + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_CTRL_C_HANDLER_H_ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/ctrl_c_handler.h" + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" +// gen_amalgamated expanded: #include "perfetto/base/compiler.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#include + +#include +#else +#include +#include +#endif + +namespace perfetto { +namespace base { + +namespace { +CtrlCHandlerFunction g_handler = nullptr; + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +BOOL WINAPI Trampoline(DWORD type) { + if (type == CTRL_C_EVENT) { + g_handler(); + return TRUE; + } + return FALSE; +} +#endif +} // namespace + +void InstallCtrlCHandler(CtrlCHandlerFunction handler) { + PERFETTO_CHECK(g_handler == nullptr); + g_handler = handler; + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + ::SetConsoleCtrlHandler(Trampoline, true); +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) + // Setup signal handler. + struct sigaction sa{}; + +// Glibc headers for sa_sigaction trigger this. +#pragma GCC diagnostic push +#if defined(__clang__) +#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" +#endif + sa.sa_handler = [](int) { g_handler(); }; +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_QNX) + sa.sa_flags = static_cast(SA_RESETHAND | SA_RESTART); +#else // POSIX-compliant + sa.sa_flags = static_cast(SA_RESETHAND); +#endif +#pragma GCC diagnostic pop + sigaction(SIGINT, &sa, nullptr); + sigaction(SIGTERM, &sa, nullptr); +#else + // Do nothing on NaCL and Fuchsia. + ignore_result(handler); +#endif +} + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/event_fd.cc +// gen_amalgamated begin header: include/perfetto/ext/base/event_fd.h +// gen_amalgamated begin header: include/perfetto/ext/base/scoped_file.h +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_ +#define INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_ + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" + +#include + +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#include // For DIR* / opendir(). +#endif + +#include + +// gen_amalgamated expanded: #include "perfetto/base/export.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h" + +namespace perfetto { +namespace base { + +namespace internal { +// Used for the most common cases of ScopedResource where there is only one +// invalid value. +template +struct DefaultValidityChecker { + static bool IsValid(T t) { return t != InvalidValue; } +}; +} // namespace internal + +// RAII classes for auto-releasing fds and dirs. +// if T is a pointer type, InvalidValue must be nullptr. Doing otherwise +// causes weird unexpected behaviors (See https://godbolt.org/z/5nGMW4). +template > +class ScopedResource { + public: + using ValidityChecker = Checker; + static constexpr T kInvalid = InvalidValue; + + explicit ScopedResource(T t = InvalidValue) : t_(t) {} + ScopedResource(ScopedResource&& other) noexcept : t_(other.t_) { + other.t_ = InvalidValue; + } + ScopedResource& operator=(ScopedResource&& other) { + reset(other.t_); + other.t_ = InvalidValue; + return *this; + } + T get() const { return t_; } + T operator*() const { return t_; } + explicit operator bool() const { return Checker::IsValid(t_); } + void reset(T r = InvalidValue) { + if (Checker::IsValid(t_)) { + int res = CloseFunction(t_); + if (CheckClose) + PERFETTO_CHECK(res == 0); + } + t_ = r; + } + T release() { + T t = t_; + t_ = InvalidValue; + return t; + } + ~ScopedResource() { reset(InvalidValue); } + + private: + ScopedResource(const ScopedResource&) = delete; + ScopedResource& operator=(const ScopedResource&) = delete; + T t_; +}; + +// Declared in file_utils.h. Forward declared to avoid #include cycles. +int PERFETTO_EXPORT_COMPONENT CloseFile(int fd); + +// Use this for file resources obtained via open() and similar APIs. +using ScopedFile = ScopedResource; +using ScopedFstream = ScopedResource; + +// Use this for resources that are HANDLE on Windows. See comments in +// platform_handle.h +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +using ScopedPlatformHandle = ScopedResource; +#else +// On non-windows systems we alias ScopedPlatformHandle to ScopedFile because +// they are really the same. This is to allow assignments between the two in +// Linux-specific code paths that predate ScopedPlatformHandle. +static_assert(std::is_same::value, ""); +using ScopedPlatformHandle = ScopedFile; + +// DIR* does not exist on Windows. +using ScopedDir = ScopedResource; +#endif + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_ +#define INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_ + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" +// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h" + +namespace perfetto { +namespace base { + +// A waitable event that can be used with poll/select. +// This is really a wrapper around eventfd_create with a pipe-based fallback +// for other platforms where eventfd is not supported. +class EventFd { + public: + EventFd(); + ~EventFd(); + EventFd(EventFd&&) noexcept = default; + EventFd& operator=(EventFd&&) = default; + + // The non-blocking file descriptor that can be polled to wait for the event. + PlatformHandle fd() const { return event_handle_.get(); } + + // Can be called from any thread. + void Notify(); + + // Can be called from any thread. If more Notify() are queued a Clear() call + // can clear all of them (up to 16 per call). + void Clear(); + + private: + // The eventfd, when eventfd is supported, otherwise this is the read end of + // the pipe for fallback mode. + ScopedPlatformHandle event_handle_; + +// QNX is specified because it is a non-Linux UNIX platform but it +// still sets the PERFETTO_OS_LINUX flag to be as compatible as possible +// with the Linux build. +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + // On Mac and other non-Linux UNIX platforms a pipe-based fallback is used. + // The write end of the wakeup pipe. + ScopedFile write_fd_; +#endif +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_ +// gen_amalgamated begin header: include/perfetto/ext/base/pipe.h +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_PIPE_H_ +#define INCLUDE_PERFETTO_EXT_BASE_PIPE_H_ + +// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h" + +namespace perfetto { +namespace base { + +class Pipe { + public: + enum Flags { + kBothBlock = 0, +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + kBothNonBlock, + kRdNonBlock, + kWrNonBlock, +#endif + }; + + static Pipe Create(Flags = kBothBlock); + + Pipe(); + Pipe(Pipe&&) noexcept; + Pipe& operator=(Pipe&&); + + ScopedPlatformHandle rd; + ScopedPlatformHandle wr; +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_PIPE_H_ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" + +#include +#include + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#include + +#include +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_QNX) +#include +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) +#include +#include +#else // Mac, Fuchsia and other non-Linux UNIXes +#include +#endif + +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/event_fd.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/pipe.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h" + +namespace perfetto { +namespace base { + +EventFd::~EventFd() = default; + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +EventFd::EventFd() { + event_handle_.reset( + CreateEventA(/*lpEventAttributes=*/nullptr, /*bManualReset=*/true, + /*bInitialState=*/false, /*bInitialState=*/nullptr)); +} + +void EventFd::Notify() { + if (!SetEvent(event_handle_.get())) // 0: fail, !0: success, unlike UNIX. + PERFETTO_DFATAL("EventFd::Notify()"); +} + +void EventFd::Clear() { + if (!ResetEvent(event_handle_.get())) // 0: fail, !0: success, unlike UNIX. + PERFETTO_DFATAL("EventFd::Clear()"); +} + +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + +EventFd::EventFd() { + event_handle_.reset(eventfd(/*initval=*/0, EFD_CLOEXEC | EFD_NONBLOCK)); + PERFETTO_CHECK(event_handle_); +} + +void EventFd::Notify() { + const uint64_t value = 1; + ssize_t ret = write(event_handle_.get(), &value, sizeof(value)); + if (ret <= 0 && errno != EAGAIN) + PERFETTO_DFATAL("EventFd::Notify()"); +} + +void EventFd::Clear() { + uint64_t value; + ssize_t ret = + PERFETTO_EINTR(read(event_handle_.get(), &value, sizeof(value))); + if (ret <= 0 && errno != EAGAIN) + PERFETTO_DFATAL("EventFd::Clear()"); +} + +#else + +EventFd::EventFd() { + // Make the pipe non-blocking so that we never block the waking thread (either + // the main thread or another one) when scheduling a wake-up. + Pipe pipe = Pipe::Create(Pipe::kBothNonBlock); + event_handle_ = ScopedPlatformHandle(std::move(pipe.rd).release()); + write_fd_ = std::move(pipe.wr); +} + +void EventFd::Notify() { + const uint64_t value = 1; + ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t)); + if (ret <= 0 && errno != EAGAIN) + PERFETTO_DFATAL("EventFd::Notify()"); +} + +void EventFd::Clear() { + // Drain the byte(s) written to the wake-up pipe. We can potentially read + // more than one byte if several wake-ups have been scheduled. + char buffer[16]; + ssize_t ret = + PERFETTO_EINTR(read(event_handle_.get(), &buffer[0], sizeof(buffer))); + if (ret <= 0 && errno != EAGAIN) + PERFETTO_DFATAL("EventFd::Clear()"); +} +#endif + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/file_utils.cc +// gen_amalgamated begin header: include/perfetto/ext/base/file_utils.h +// gen_amalgamated begin header: include/perfetto/base/status.h +/* + * Copyright (C) 2019 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_BASE_STATUS_H_ +#define INCLUDE_PERFETTO_BASE_STATUS_H_ + +#include +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/compiler.h" +// gen_amalgamated expanded: #include "perfetto/base/export.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" + +namespace perfetto { +namespace base { + +// Represents either the success or the failure message of a function. +// This can used as the return type of functions which would usually return an +// bool for success or int for errno but also wants to add some string context +// (ususally for logging). +// +// Similar to absl::Status, an optional "payload" can also be included with more +// context about the error. This allows passing additional metadata about the +// error (e.g. location of errors, potential mitigations etc). +class PERFETTO_EXPORT_COMPONENT Status { + public: + Status() : ok_(true) {} + explicit Status(std::string msg) : ok_(false), message_(std::move(msg)) { + PERFETTO_CHECK(!message_.empty()); + } + + // Copy operations. + Status(const Status&) = default; + Status& operator=(const Status&) = default; + + // Move operations. The moved-from state is valid but unspecified. + Status(Status&&) noexcept = default; + Status& operator=(Status&&) = default; + + bool ok() const { return ok_; } + + // When ok() is false this returns the error message. Returns the empty string + // otherwise. + const std::string& message() const { return message_; } + const char* c_message() const { return message_.c_str(); } + + ////////////////////////////////////////////////////////////////////////////// + // Payload Management APIs + ////////////////////////////////////////////////////////////////////////////// + + // Payloads can be attached to error statuses to provide additional context. + // + // Payloads are (key, value) pairs, where the key is a string acting as a + // unique "type URL" and the value is an opaque string. The "type URL" should + // be unique, follow the format of a URL and, ideally, documentation on how to + // interpret its associated data should be available. + // + // To attach a payload to a status object, call `Status::SetPayload()`. + // Similarly, to extract the payload from a status, call + // `Status::GetPayload()`. + // + // Note: the payload APIs are only meaningful to call when the status is an + // error. Otherwise, all methods are noops. + + // Gets the payload for the given |type_url| if one exists. + // + // Will always return std::nullopt if |ok()|. + std::optional GetPayload(std::string_view type_url) const; + + // Sets the payload for the given key. The key should + // + // Will always do nothing if |ok()|. + void SetPayload(std::string_view type_url, std::string value); + + // Erases the payload for the given string and returns true if the payload + // existed and was erased. + // + // Will always do nothing if |ok()|. + bool ErasePayload(std::string_view type_url); + + private: + struct Payload { + std::string type_url; + std::string payload; + }; + + bool ok_ = false; + std::string message_; + std::vector payloads_; +}; + +// Returns a status object which represents the Ok status. +inline Status OkStatus() { + return Status(); +} + +Status ErrStatus(const char* format, ...) PERFETTO_PRINTF_FORMAT(1, 2); + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_BASE_STATUS_H_ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_ +#define INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_ + +#include // For mode_t & O_RDONLY/RDWR. Exists also on Windows. +#include + +#include +#include +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" +// gen_amalgamated expanded: #include "perfetto/base/export.h" +// gen_amalgamated expanded: #include "perfetto/base/status.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/sys_types.h" + +namespace perfetto { +namespace base { + +class TaskRunner; + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +using FileOpenMode = int; +inline constexpr char kDevNull[] = "NUL"; +inline constexpr char kFopenReadFlag[] = "r"; +#else +using FileOpenMode = mode_t; +inline constexpr char kDevNull[] = "/dev/null"; +inline constexpr char kFopenReadFlag[] = "re"; +#endif + +constexpr FileOpenMode kFileModeInvalid = static_cast(-1); + +bool ReadPlatformHandle(PlatformHandle, std::string* out); +bool ReadFileDescriptor(int fd, std::string* out); +bool ReadFileStream(FILE* f, std::string* out); +bool ReadFile(const std::string& path, std::string* out); + +// A wrapper around read(2). It deals with Linux vs Windows includes. It also +// deals with handling EINTR. Has the same semantics of UNIX's read(2). +ssize_t Read(int fd, void* dst, size_t dst_size); + +// Call write until all data is written or an error is detected. +// +// man 2 write: +// If a write() is interrupted by a signal handler before any bytes are +// written, then the call fails with the error EINTR; if it is +// interrupted after at least one byte has been written, the call +// succeeds, and returns the number of bytes written. +ssize_t WriteAll(int fd, const void* buf, size_t count); + +// Copies all data from |fd_in| to |fd_out|. Saves the offset of |fd_in|, +// rewinds it to the beginning, copies the content, and restores the offset. +// |fd_in| can't be a pipe, socket of FIFO. +base::Status CopyFileContents(int fd_in, int fd_out); + +ssize_t WriteAllHandle(PlatformHandle, const void* buf, size_t count); + +ScopedFile OpenFile(const std::string& path, + int flags, + FileOpenMode = kFileModeInvalid); +ScopedFstream OpenFstream(const std::string& path, const std::string& mode); + +// This is an alias for close(). It's to avoid leaking windows.h in headers. +// Exported because ScopedFile is used in the /include/ext API by Chromium +// component builds. +int PERFETTO_EXPORT_COMPONENT CloseFile(int fd); + +bool FlushFile(int fd); + +// Returns true if mkdir succeeds, false if it fails (see errno in that case). +bool Mkdir(const std::string& path); + +// Calls rmdir() on UNIX, _rmdir() on Windows. +bool Rmdir(const std::string& path); + +// Wrapper around access(path, F_OK). +bool FileExists(const std::string& path); + +// Gets the extension for a filename. If the file has two extensions, returns +// only the last one (foo.pb.gz => .gz). Returns empty string if there is no +// extension. +std::string GetFileExtension(const std::string& filename); + +// Returns the basename component of a path (the final component after the last +// directory separator). Behaves like man 2 basename, but works with both '/' +// and '\' separators for cross-platform compatibility. +// Examples: +// Basename("/usr/bin/ls") => "ls" +// Basename("/usr/bin/") => "bin" +// Basename("/") => "/" +// Basename("foo") => "foo" +// Basename("") => "." +// Basename("C:\\Windows\\System32") => "System32" +std::string Basename(const std::string& path); + +// Returns the directory component of a path (everything up to but not +// including the final component). Behaves like man 2 dirname, but works with +// both '/' and '\' separators for cross-platform compatibility. +// Examples: +// Dirname("/usr/bin/ls") => "/usr/bin" +// Dirname("/usr/bin") => "/usr" +// Dirname("/") => "/" +// Dirname("foo") => "." +// Dirname("") => "." +// Dirname("C:\\Windows\\System32") => "C:\\Windows" +std::string Dirname(const std::string& path); + +// Puts the path to all files under |dir_path| in |output|, recursively walking +// subdirectories. File paths are relative to |dir_path|. Only files are +// included, not directories. Path separator is always '/', even on windows (not +// '\'). +base::Status ListFilesRecursive(const std::string& dir_path, + std::vector& output); + +// Lists immediate subdirectories in |dir_path| (non-recursive). Directory names +// are relative to |dir_path| and do not include the path separator. Returns +// only directories, not files. Works on both Unix and Windows. +base::Status ListDirectories(const std::string& dir_path, + std::vector& output); + +// Sets |path|'s owner group to |group_name| and permission mode bits to +// |mode_bits|. +base::Status SetFilePermissions(const std::string& path, + const std::string& group_name, + const std::string& mode_bits); + +// Returns the size of the file located at |path|, or nullopt in case of error. +std::optional GetFileSize(const std::string& path); + +// Returns the size of the open file |fd|, or nullopt in case of error. +std::optional GetFileSize(PlatformHandle fd); + +// This class uses inotify (on Linux/Android) to watch for the creation of +// files in the filesystem. When the specified file is created, it triggers a +// callback function. +// Destroying the returned unique_ptr will automatically unregister the watch. +// +// Note: This only works with filesystem paths (not abstract sockets or other +// special file types). +// It's only supported on Linux and Android, it's a no-op (returns nullptr) on +// other platforms. +// +// Usage: +// auto watch = LinuxFileWatch::WatchFileCreation( +// task_runner, "/tmp/my_file", []() { +// // Called when /tmp/my_file is created +// }); +class LinuxFileWatch { + public: + // Creates a watcher for file creation. Returns nullptr if the path is not a + // valid filesystem path or if the platform doesn't support inotify. The + // callback will be invoked on the provided TaskRunner when the file is + // created. + static std::unique_ptr WatchFileCreation( + TaskRunner*, + const char* path, + std::function callback); + + virtual ~LinuxFileWatch(); + + protected: + LinuxFileWatch() = default; +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_ +// gen_amalgamated begin header: include/perfetto/base/task_runner.h +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_ +#define INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_ + +#include + +#include + +// gen_amalgamated expanded: #include "perfetto/base/export.h" +// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h" + +namespace perfetto { +namespace base { + +// A generic interface to allow the library clients to interleave the execution +// of the tracing internals in their runtime environment. +// The expectation is that all tasks, which are queued either via PostTask() or +// AddFileDescriptorWatch(), are executed on the same sequence (either on the +// same thread, or on a thread pool that gives sequencing guarantees). +// +// Tasks are never executed synchronously inside PostTask and there is a full +// memory barrier between tasks. +// +// All methods of this interface can be called from any thread. +class PERFETTO_EXPORT_COMPONENT TaskRunner { + public: + virtual ~TaskRunner(); + + // Schedule a task for immediate execution. Immediate tasks are always + // executed in the order they are posted. Can be called from any thread. + virtual void PostTask(std::function) = 0; + + // Schedule a task for execution after |delay_ms|. Note that there is no + // strict ordering guarantee between immediate and delayed tasks. Can be + // called from any thread. + virtual void PostDelayedTask(std::function, uint32_t delay_ms) = 0; + + // Schedule a task to run when the handle becomes readable. The same handle + // can only be monitored by one function. Note that this function only needs + // to be implemented on platforms where the built-in ipc framework is used. + // Can be called from any thread. + // TODO(skyostil): Refactor this out of the shared interface. + virtual void AddFileDescriptorWatch(PlatformHandle, + std::function) = 0; + + // Remove a previously scheduled watch for the handle. If this is run on the + // target thread of this TaskRunner, guarantees that the task registered to + // this handle will not be executed after this function call. + // Can be called from any thread. + virtual void RemoveFileDescriptorWatch(PlatformHandle) = 0; + + // Checks if the current thread is the same thread where the TaskRunner's task + // run. This allows single threaded task runners (like the ones used in + // perfetto) to inform the caller that anything posted will run on the same + // thread/sequence. This can allow some callers to skip PostTask and instead + // directly execute the code. Can be called from any thread. + virtual bool RunsTasksOnCurrentThread() const = 0; +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_ +// gen_amalgamated begin header: include/perfetto/ext/base/weak_ptr.h +// gen_amalgamated begin header: include/perfetto/ext/base/thread_checker.h +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_ +#define INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_ + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" + +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#include +#endif +#include + +// gen_amalgamated expanded: #include "perfetto/base/export.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h" + +namespace perfetto { +namespace base { + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +using ThreadID = unsigned long; +#else +using ThreadID = pthread_t; +#endif + +class PERFETTO_EXPORT_COMPONENT ThreadChecker { + public: + ThreadChecker(); + ~ThreadChecker(); + ThreadChecker(const ThreadChecker&); + ThreadChecker& operator=(const ThreadChecker&); + bool CalledOnValidThread() const PERFETTO_WARN_UNUSED_RESULT; + void DetachFromThread(); + + private: + mutable std::atomic thread_id_; +}; + +#if PERFETTO_DCHECK_IS_ON() && !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) +// TODO(primiano) Use Chromium's thread checker in Chromium. +#define PERFETTO_THREAD_CHECKER(name) base::ThreadChecker name; +#define PERFETTO_DCHECK_THREAD(name) \ + PERFETTO_DCHECK((name).CalledOnValidThread()) +#define PERFETTO_DETACH_FROM_THREAD(name) (name).DetachFromThread() +#else +#define PERFETTO_THREAD_CHECKER(name) +#define PERFETTO_DCHECK_THREAD(name) +#define PERFETTO_DETACH_FROM_THREAD(name) +#endif // PERFETTO_DCHECK_IS_ON() + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_ +#define INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_ + +// gen_amalgamated expanded: #include "perfetto/ext/base/thread_checker.h" + +#include + +namespace perfetto { +namespace base { + +// A simple WeakPtr for single-threaded cases. +// Generally keep the WeakPtrFactory as last fields in classes: it makes the +// WeakPtr(s) invalidate as first thing in the class dtor. +// Usage: +// class MyClass { +// MyClass() : weak_factory_(this) {} +// WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } +// +// private: +// WeakPtrFactory weak_factory_; +// } +// +// int main() { +// std::unique_ptr foo(new MyClass); +// auto wptr = foo.GetWeakPtr(); +// ASSERT_TRUE(wptr); +// ASSERT_EQ(foo.get(), wptr->get()); +// foo.reset(); +// ASSERT_FALSE(wptr); +// ASSERT_EQ(nullptr, wptr->get()); +// } + +template +class WeakPtrFactory; // Forward declaration, defined below. + +template +class WeakPtr { + public: + WeakPtr() {} + WeakPtr(const WeakPtr&) = default; + WeakPtr& operator=(const WeakPtr&) = default; + WeakPtr(WeakPtr&&) = default; + WeakPtr& operator=(WeakPtr&&) = default; + + T* get() const { + PERFETTO_DCHECK_THREAD(thread_checker); + return handle_ ? *handle_.get() : nullptr; + } + T* operator->() const { return get(); } + T& operator*() const { return *get(); } + + explicit operator bool() const { return !!get(); } + + private: + friend class WeakPtrFactory; + explicit WeakPtr(const std::shared_ptr& handle) : handle_(handle) {} + + std::shared_ptr handle_; + PERFETTO_THREAD_CHECKER(thread_checker) +}; + +template +class WeakPtrFactory { + public: + explicit WeakPtrFactory(T* owner) : weak_ptr_(std::make_shared(owner)) { + PERFETTO_DCHECK_THREAD(thread_checker); + } + + ~WeakPtrFactory() { + PERFETTO_DCHECK_THREAD(thread_checker); + *(weak_ptr_.handle_.get()) = nullptr; + } + + // Can be safely called on any thread, since it simply copies |weak_ptr_|. + // Note that any accesses to the returned pointer need to be made on the + // thread that created/reset the factory. + WeakPtr GetWeakPtr() const { return weak_ptr_; } + + // Reset the factory to a new owner & thread. May only be called before any + // weak pointers were passed out. Future weak pointers will be valid on the + // calling thread. + void Reset(T* owner) { + // Reset thread checker to current thread. + PERFETTO_DETACH_FROM_THREAD(thread_checker); + PERFETTO_DCHECK_THREAD(thread_checker); + + // We should not have passed out any weak pointers yet at this point. + PERFETTO_DCHECK(weak_ptr_.handle_.use_count() == 1); + + weak_ptr_ = WeakPtr(std::make_shared(owner)); + } + + private: + WeakPtrFactory(const WeakPtrFactory&) = delete; + WeakPtrFactory& operator=(const WeakPtrFactory&) = delete; + + WeakPtr weak_ptr_; + PERFETTO_THREAD_CHECKER(thread_checker) +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/file_utils.h" + +#include +#include + +#include +#include +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/build_config.h" +// gen_amalgamated expanded: #include "perfetto/base/compiler.h" +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/base/platform_handle.h" +// gen_amalgamated expanded: #include "perfetto/base/status.h" +// gen_amalgamated expanded: #include "perfetto/base/task_runner.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/platform.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/scoped_file.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/utils.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/weak_ptr.h" + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#include + +#include +#include +#include +#else +#include +#include +#endif + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_FREEBSD) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) +#define PERFETTO_SET_FILE_PERMISSIONS +#include +#include +#include +#include +#include +#endif + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) +// For inotify. QNX doesn't have full support for inotify_init1(). +#include +#endif + +namespace perfetto { +namespace base { +namespace { +constexpr size_t kBufSize = 2048; + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +// Wrap FindClose to: (1) make the return unix-style; (2) deal with stdcall. +int CloseFindHandle(HANDLE h) { + return FindClose(h) ? 0 : -1; +} + +std::optional ToUtf16(const std::string& str) { + int len = MultiByteToWideChar(CP_UTF8, 0, str.data(), + static_cast(str.size()), nullptr, 0); + if (len < 0) { + return std::nullopt; + } + std::vector tmp; + tmp.resize(static_cast::size_type>(len)); + len = + MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), + tmp.data(), static_cast(tmp.size())); + if (len < 0) { + return std::nullopt; + } + PERFETTO_CHECK(static_cast::size_type>(len) == + tmp.size()); + return std::wstring(tmp.data(), tmp.size()); +} + +#endif + +} // namespace + +ssize_t Read(int fd, void* dst, size_t dst_size) { + ssize_t ret; + platform::BeforeMaybeBlockingSyscall(); +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + ret = _read(fd, dst, static_cast(dst_size)); +#else + ret = PERFETTO_EINTR(read(fd, dst, dst_size)); +#endif + platform::AfterMaybeBlockingSyscall(); + return ret; +} + +bool ReadFileDescriptor(int fd, std::string* out) { + // Do not override existing data in string. + size_t i = out->size(); + + struct stat buf{}; + if (fstat(fd, &buf) != -1) { + if (buf.st_size > 0) + out->resize(i + static_cast(buf.st_size)); + } + + ssize_t bytes_read; + for (;;) { + if (out->size() < i + kBufSize) + out->resize(out->size() + kBufSize); + + bytes_read = Read(fd, &((*out)[i]), kBufSize); + if (bytes_read > 0) { + i += static_cast(bytes_read); + } else { + out->resize(i); + return bytes_read == 0; + } + } +} + +bool ReadPlatformHandle(PlatformHandle h, std::string* out) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + // Do not override existing data in string. + size_t i = out->size(); + + for (;;) { + if (out->size() < i + kBufSize) + out->resize(out->size() + kBufSize); + DWORD bytes_read = 0; + auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr); + if (res && bytes_read > 0) { + i += static_cast(bytes_read); + } else { + out->resize(i); + const bool is_eof = res && bytes_read == 0; + auto err = res ? 0 : GetLastError(); + // The "Broken pipe" error on Windows is slightly different than Unix: + // On Unix: a "broken pipe" error can happen only on the writer side. On + // the reader there is no broken pipe, just a EOF. + // On windows: the reader also sees a broken pipe error. + // Here we normalize on the Unix behavior, treating broken pipe as EOF. + return is_eof || err == ERROR_BROKEN_PIPE; + } + } +#else + return ReadFileDescriptor(h, out); +#endif +} + +bool ReadFileStream(FILE* f, std::string* out) { + return ReadFileDescriptor(fileno(f), out); +} + +bool ReadFile(const std::string& path, std::string* out) { + base::ScopedFile fd = base::OpenFile(path, O_RDONLY); + if (!fd) + return false; + + return ReadFileDescriptor(*fd, out); +} + +ssize_t WriteAll(int fd, const void* buf, size_t count) { + size_t written = 0; + while (written < count) { + // write() on windows takes an unsigned int size. + uint32_t bytes_left = static_cast( + std::min(count - written, static_cast(UINT32_MAX))); + platform::BeforeMaybeBlockingSyscall(); + ssize_t wr = PERFETTO_EINTR( + write(fd, static_cast(buf) + written, bytes_left)); + platform::AfterMaybeBlockingSyscall(); + if (wr == 0) + break; + if (wr < 0) + return wr; + written += static_cast(wr); + } + return static_cast(written); +} + +base::Status CopyFileContents(int fd_in, int fd_out) { + off_t original_offset = lseek(fd_in, 0, SEEK_CUR); + if (original_offset == -1) { + return base::ErrStatus( + "Can't get offset in 'fd_in', lseek error: %s (errno: %d)", + strerror(errno), errno); + } + + if (lseek(fd_in, 0, SEEK_SET) == -1) { + return base::ErrStatus( + "Can't change the offset in 'fd_in', lseek error: %s (errno: %d)", + strerror(errno), errno); + } + + auto restore_offset_on_exit = OnScopeExit([fd_in, original_offset] { + // 'lseek' should never fail here, but if it fails, we crash, to prevent + // possible data loss/overwrite in the 'fd_in'. + PERFETTO_CHECK(lseek(fd_in, original_offset, SEEK_SET) >= 0); + }); + + // Use bigger buffer when copy files. + constexpr size_t kCopyFileBufSize = 32 * 1024; // 32KB. + static_assert(kCopyFileBufSize > kBufSize); + // Don't allocate that much memory on stack. + std::vector buffer(kCopyFileBufSize); + for (;;) { + ssize_t bytes_read = Read(fd_in, buffer.data(), buffer.size()); + if (bytes_read == 0) + break; + if (bytes_read < 0) { + return base::ErrStatus("Read failed: %s (errno: %d)", strerror(errno), + errno); + } + ssize_t written = + WriteAll(fd_out, buffer.data(), static_cast(bytes_read)); + if (written != bytes_read) { + return base::ErrStatus("Write failed: %s (errno: %d)", strerror(errno), + errno); + } + } + return base::OkStatus(); +} + +ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + DWORD wsize = 0; + if (::WriteFile(h, buf, static_cast(count), &wsize, nullptr)) { + return wsize; + } else { + return -1; + } +#else + return WriteAll(h, buf, count); +#endif +} + +bool FlushFile(int fd) { + PERFETTO_DCHECK(fd != 0); +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + return !PERFETTO_EINTR(fdatasync(fd)); +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + return !PERFETTO_EINTR(_commit(fd)); +#else + return !PERFETTO_EINTR(fsync(fd)); +#endif +} + +bool Mkdir(const std::string& path) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + return _mkdir(path.c_str()) == 0; +#else + return mkdir(path.c_str(), 0755) == 0; +#endif +} + +bool Rmdir(const std::string& path) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + return _rmdir(path.c_str()) == 0; +#else + return rmdir(path.c_str()) == 0; +#endif +} + +int CloseFile(int fd) { + return close(fd); +} + +ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) { + // If a new file might be created, ensure that the permissions for the new + // file are explicitly specified. + PERFETTO_CHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid); +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + // Always use O_BINARY on Windows, to avoid silly EOL translations. + ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode)); +#else + // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec. + ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode)); +#endif + return fd; +} + +ScopedFstream OpenFstream(const std::string& path, const std::string& mode) { + ScopedFstream file; + // On Windows fopen interprets filename using the ANSI or OEM codepage but + // sqlite3_value_text returns a UTF-8 string. To make sure we interpret the + // filename correctly we use _wfopen and a UTF-16 string on windows. + // + // On Windows fopen also open files in the text mode by default, but we want + // to open them in the binary mode, to avoid silly EOL translations (and to be + // consistent with base::OpenFile). So we check the mode first and append 'b' + // mode only when it makes sense. +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + std::string s_mode(mode); + // Windows supports non-standard mode extension that sets encoding in text + // mode. If you need to open a FILE* in text mode, use the fopen API directly. + bool is_text_mode = Contains(s_mode, "ccs=") || Contains(s_mode, "t"); + PERFETTO_CHECK(!is_text_mode); + bool is_binary_mode = Contains(s_mode, 'b'); + if (!is_binary_mode) + s_mode += 'b'; + + auto w_path = ToUtf16(path); + auto w_mode = ToUtf16(s_mode); + if (w_path && w_mode) { + file.reset(_wfopen(w_path->c_str(), w_mode->c_str())); + } +#else + file.reset(fopen(path.c_str(), mode.c_str())); +#endif + return file; +} + +bool FileExists(const std::string& path) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + return _access(path.c_str(), 0) == 0; +#else + return access(path.c_str(), F_OK) == 0; +#endif +} + +// Declared in base/platform_handle.h. +int ClosePlatformHandle(PlatformHandle handle) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + // Make the return value UNIX-style. + return CloseHandle(handle) ? 0 : -1; +#else + return close(handle); +#endif +} + +base::Status ListFilesRecursive(const std::string& dir_path, + std::vector& output) { + std::string root_dir_path = dir_path; + if (root_dir_path.back() == '\\') { + root_dir_path.back() = '/'; + } else if (root_dir_path.back() != '/') { + root_dir_path.push_back('/'); + } + + // dir_queue contains full paths to the directories. The paths include the + // root_dir_path at the beginning and the trailing slash at the end. + std::deque dir_queue; + dir_queue.push_back(root_dir_path); + + while (!dir_queue.empty()) { + const std::string cur_dir = std::move(dir_queue.front()); + dir_queue.pop_front(); +#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) + return base::ErrStatus("ListFilesRecursive not supported yet"); +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + std::string glob_path = cur_dir + "*"; + // + 1 because we also have to count the NULL terminator. + if (glob_path.length() + 1 > MAX_PATH) + return base::ErrStatus("Directory path %s is too long", dir_path.c_str()); + WIN32_FIND_DATAA ffd; + + base::ScopedResource + hFind(FindFirstFileA(glob_path.c_str(), &ffd)); + if (!hFind) { + // For empty directories, there should be at least one entry '.'. + // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory + // couldn't be accessed. + return base::ErrStatus("Failed to open directory %s", cur_dir.c_str()); + } + do { + if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) + continue; + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + std::string subdir_path = cur_dir + ffd.cFileName + '/'; + dir_queue.push_back(subdir_path); + } else { + const std::string full_path = cur_dir + ffd.cFileName; + PERFETTO_CHECK(full_path.length() > root_dir_path.length()); + output.push_back(full_path.substr(root_dir_path.length())); + } + } while (FindNextFileA(*hFind, &ffd)); +#else + ScopedDir dir = ScopedDir(opendir(cur_dir.c_str())); + if (!dir) { + return base::ErrStatus("Failed to open directory %s", cur_dir.c_str()); + } + for (auto* dirent = readdir(dir.get()); dirent != nullptr; + dirent = readdir(dir.get())) { + if (strcmp(dirent->d_name, ".") == 0 || + strcmp(dirent->d_name, "..") == 0) { + continue; + } + struct stat dirstat; + std::string full_path = cur_dir + dirent->d_name; + PERFETTO_CHECK(stat(full_path.c_str(), &dirstat) == 0); + if (S_ISDIR(dirstat.st_mode)) { + dir_queue.push_back(full_path + '/'); + } else if (S_ISREG(dirstat.st_mode)) { + PERFETTO_CHECK(full_path.length() > root_dir_path.length()); + output.push_back(full_path.substr(root_dir_path.length())); + } + } +#endif + } + return base::OkStatus(); +} + +base::Status ListDirectories(const std::string& dir_path, + std::vector& output) { + std::string normalized_path = dir_path; + if (!normalized_path.empty() && normalized_path.back() != '/' && + normalized_path.back() != '\\') { + normalized_path.push_back('/'); + } + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL) + return base::ErrStatus("ListDirectories not supported yet"); +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + std::string glob_path = normalized_path + "*"; + if (glob_path.length() + 1 > MAX_PATH) { + return base::ErrStatus("Directory path %s is too long", dir_path.c_str()); + } + WIN32_FIND_DATAA ffd; + + base::ScopedResource + hFind(FindFirstFileA(glob_path.c_str(), &ffd)); + if (!hFind) { + return base::ErrStatus("Failed to open directory %s", + normalized_path.c_str()); + } + do { + if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) { + continue; + } + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + output.push_back(ffd.cFileName); + } + } while (FindNextFileA(*hFind, &ffd)); +#else + ScopedDir dir = ScopedDir(opendir(normalized_path.c_str())); + if (!dir) { + return base::ErrStatus("Failed to open directory %s", + normalized_path.c_str()); + } + for (auto* dirent = readdir(dir.get()); dirent != nullptr; + dirent = readdir(dir.get())) { + if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) { + continue; + } + std::string full_path = normalized_path + dirent->d_name; + struct stat dirstat; + if (stat(full_path.c_str(), &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) { + output.push_back(dirent->d_name); + } + } +#endif + return base::OkStatus(); +} + +std::string GetFileExtension(const std::string& filename) { + auto ext_idx = filename.rfind('.'); + if (ext_idx == std::string::npos) + return std::string(); + return filename.substr(ext_idx); +} + +std::string Basename(const std::string& path) { + // Handle empty path + if (path.empty()) + return "."; + + // Make a copy to work with + std::string p = path; + + // Strip trailing slashes (both / and \) + while (p.size() > 1 && (p.back() == '/' || p.back() == '\\')) { + p.pop_back(); + } + + // If the path is now empty or just a single slash, return it + if (p.empty() || p == "/" || p == "\\") + return p.empty() ? "/" : p; + + // Find the last directory separator (either / or \) + size_t last_sep = p.find_last_of("/\\"); + + if (last_sep == std::string::npos) { + // No separator found, the whole path is the basename + return p; + } + + // Return everything after the last separator + return p.substr(last_sep + 1); +} + +std::string Dirname(const std::string& path) { + // Handle empty path + if (path.empty()) + return "."; + + // Make a copy to work with + std::string p = path; + + // Strip trailing slashes (both / and \) + while (p.size() > 1 && (p.back() == '/' || p.back() == '\\')) { + p.pop_back(); + } + + // If the path is now just a single slash, return it + if (p == "/" || p == "\\") + return p; + + // Find the last directory separator (either / or \) + size_t last_sep = p.find_last_of("/\\"); + + if (last_sep == std::string::npos) { + // No separator found, return "." + return "."; + } + + // If the separator is at position 0, return the root + if (last_sep == 0) + return p.substr(0, 1); // Return "/" or "\" + + // Strip trailing slashes from the dirname part + while (last_sep > 0 && (p[last_sep - 1] == '/' || p[last_sep - 1] == '\\')) { + --last_sep; + } + + // If we've consumed all characters, return the root + if (last_sep == 0) + return p.substr(0, 1); + + // Return everything up to (but not including) the last separator + return p.substr(0, last_sep); +} + +base::Status SetFilePermissions(const std::string& file_path, + const std::string& group_name_or_id, + const std::string& mode_bits) { +#ifdef PERFETTO_SET_FILE_PERMISSIONS + PERFETTO_CHECK(!file_path.empty()); + PERFETTO_CHECK(!group_name_or_id.empty()); + + // Default |group_id| to -1 for not changing the group ownership. + gid_t group_id = static_cast(-1); + auto maybe_group_id = base::StringToUInt32(group_name_or_id); + if (maybe_group_id) { // A numerical group ID. + group_id = *maybe_group_id; + } else { // A group name. + struct group* file_group = nullptr; + // Query the group ID of |group|. + do { + file_group = getgrnam(group_name_or_id.c_str()); + } while (file_group == nullptr && errno == EINTR); + if (file_group == nullptr) { + return base::ErrStatus("Failed to get group information of %s ", + group_name_or_id.c_str()); + } + group_id = file_group->gr_gid; + } + + if (PERFETTO_EINTR(chown(file_path.c_str(), geteuid(), group_id))) { + return base::ErrStatus("Failed to chown %s ", file_path.c_str()); + } + + // |mode| accepts values like "0660" as "rw-rw----" mode bits. + auto mode_value = base::StringToInt32(mode_bits, 8); + if (!(mode_bits.size() == 4 && mode_value.has_value())) { + return base::ErrStatus( + "The chmod mode bits must be a 4-digit octal number, e.g. 0660"); + } + if (PERFETTO_EINTR( + chmod(file_path.c_str(), static_cast(mode_value.value())))) { + return base::ErrStatus("Failed to chmod %s", file_path.c_str()); + } + return base::OkStatus(); +#else + base::ignore_result(file_path); + base::ignore_result(group_name_or_id); + base::ignore_result(mode_bits); + return base::ErrStatus( + "Setting file permissions is not supported on this platform"); +#endif +} + +std::optional GetFileSize(const std::string& file_path) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + // This does not use base::OpenFile to avoid getting an exclusive lock. + base::ScopedPlatformHandle fd( + CreateFileA(file_path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)); +#else + base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC)); +#endif + if (!fd) { + return std::nullopt; + } + return GetFileSize(*fd); +} + +std::optional GetFileSize(PlatformHandle fd) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + LARGE_INTEGER file_size; + file_size.QuadPart = 0; + if (!GetFileSizeEx(fd, &file_size)) { + return std::nullopt; + } + static_assert(sizeof(decltype(file_size.QuadPart)) <= sizeof(uint64_t)); + return static_cast(file_size.QuadPart); +#else + struct stat buf{}; + if (fstat(fd, &buf) == -1) { + return std::nullopt; + } + static_assert(sizeof(decltype(buf.st_size)) <= sizeof(uint64_t)); + return static_cast(buf.st_size); +#endif +} + +// LinuxFileWatch + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX_BUT_NOT_QNX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) + +namespace { + +// Implementation class extends LinuxFileWatch +class FileWatchImpl : public LinuxFileWatch { + public: + FileWatchImpl(TaskRunner* tr, + std::string fn, + ScopedFile ifd, + std::function cb) + : task_runner_(tr), + file_base_name_(std::move(fn)), + inotify_fd_(std::move(ifd)), + callback_(std::move(cb)), + weak_ptr_factory_(this) { + task_runner_->AddFileDescriptorWatch( + *inotify_fd_, [weak_handle = weak_ptr_factory_.GetWeakPtr()] { + if (!weak_handle) + return; + alignas(struct inotify_event) char buf[4096]; + ssize_t rsize = + base::Read(*weak_handle->inotify_fd_, buf, sizeof(buf)); + if (rsize <= 0) + return; + for (ssize_t i = 0; i < rsize;) { + auto* evt = reinterpret_cast(&buf[i]); + i += static_cast(sizeof(inotify_event) + evt->len); + if (evt->len > 0 && (evt->mask & IN_CREATE)) { + if (weak_handle->file_base_name_ == evt->name) { + weak_handle->task_runner_->PostTask(weak_handle->callback_); + return; + } + } + } // for(evt); + }); + } + + ~FileWatchImpl() override { + if (!inotify_fd_) + return; + task_runner_->RemoveFileDescriptorWatch(*inotify_fd_); + inotify_fd_.reset(); + } + + private: + TaskRunner* task_runner_ = nullptr; + std::string file_base_name_; // Only the name without the path. + ScopedFile inotify_fd_; + std::function callback_; + WeakPtrFactory weak_ptr_factory_; // Keep last. +}; + +} // namespace + +std::unique_ptr LinuxFileWatch::WatchFileCreation( + TaskRunner* task_runner, + const char* path, + std::function callback) { + if (!path || path[0] == '\0') { + // We can add a inotify watch only for valid filesystem paths. + return nullptr; + } + + ScopedFile inotify_fd(inotify_init1(IN_CLOEXEC | IN_NONBLOCK)); + if (!inotify_fd) { + PERFETTO_DLOG("inotify_init() failed"); + return nullptr; + } + + // Here we watch the parent dir, not the file itself. We cannot watch for + // a file that doesn't exist yet, because the kernel internally attaches the + // watch to an inode, and a non-existing file doesn't have inodes. + // We are not interested in IN_MOVED_TO because we don't mv files. + std::string file_dir = Dirname(path); + if (inotify_add_watch(*inotify_fd, file_dir.c_str(), IN_CREATE) < 0) { + PERFETTO_DLOG("inotify_add_watch(%s) failed", file_dir.c_str()); + return nullptr; + } + + std::string file_base_name = Basename(path); + + return std::unique_ptr( + new FileWatchImpl(task_runner, std::move(file_base_name), + std::move(inotify_fd), std::move(callback))); +} + +LinuxFileWatch::~LinuxFileWatch() = default; + +#else + +std::unique_ptr LinuxFileWatch::WatchFileCreation( + TaskRunner*, + const char*, + std::function) { + return nullptr; // Not supported on other platforms. +} + +LinuxFileWatch::~LinuxFileWatch() = default; + +#endif // OS_LINUX || OS_ANDROID + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/fixed_string_writer.cc +// gen_amalgamated begin header: include/perfetto/ext/base/fixed_string_writer.h +/* + * Copyright (C) 2019 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_FIXED_STRING_WRITER_H_ +#define INCLUDE_PERFETTO_EXT_BASE_FIXED_STRING_WRITER_H_ + +#include + +#include +#include +#include +#include +#include +#include + +// gen_amalgamated expanded: #include "perfetto/base/logging.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h" +// gen_amalgamated expanded: #include "perfetto/ext/base/string_view.h" + +namespace perfetto { +namespace base { + +// A helper class which writes formatted data to a string buffer. +// This is used in the trace processor where we write O(GBs) of strings and +// sprintf is too slow. +class FixedStringWriter { + public: + // Creates a string buffer from a char buffer and length. + FixedStringWriter(char* buffer, size_t size) : buffer_(buffer), size_(size) {} + + // Appends n instances of a char to the buffer. + void AppendChar(char in, size_t n = 1) { + PERFETTO_DCHECK(pos_ + n <= size_); + memset(&buffer_[pos_], in, n); + pos_ += n; + } + + // Appends a length delimited string to the buffer. + void AppendString(const char* in, size_t n) { + PERFETTO_DCHECK(pos_ + n <= size_); + memcpy(&buffer_[pos_], in, n); + pos_ += n; + } + + void AppendStringView(StringView sv) { AppendString(sv.data(), sv.size()); } + + // Appends a null-terminated string literal to the buffer. + template + inline void AppendLiteral(const char (&in)[N]) { + AppendString(in, N - 1); + } + + // Appends a StringView to the buffer. + void AppendString(StringView data) { AppendString(data.data(), data.size()); } + + // Appends an integer to the buffer. + void AppendInt(int64_t value) { AppendPaddedInt<'0', 0>(value); } + + // Appends an integer to the buffer, padding with |padchar| if the number of + // digits of the integer is less than |padding|. + template + void AppendPaddedInt(int64_t sign_value) { + const bool negate = std::signbit(static_cast(sign_value)); + uint64_t absolute_value; + if (sign_value == std::numeric_limits::min()) { + absolute_value = + static_cast(std::numeric_limits::max()) + 1; + } else { + absolute_value = static_cast(std::abs(sign_value)); + } + AppendPaddedInt(absolute_value, negate); + } + + void AppendUnsignedInt(uint64_t value) { + AppendPaddedUnsignedInt<'0', 0>(value); + } + + // Appends an unsigned integer to the buffer, padding with |padchar| if the + // number of digits of the integer is less than |padding|. + template + void AppendPaddedUnsignedInt(uint64_t value) { + AppendPaddedInt(value, false); + } + + template + void AppendPaddedHexInt(IntType value, char padchar, uint64_t padding) { + using UnsignedType = std::make_unsigned_t; + constexpr size_t kMaxHexDigits = sizeof(IntType) * 2; + // 32 bytes is more than enough for any integer type (max 16 hex digits for + // 64-bit) + constexpr size_t kBufferSize = 32; + auto size_needed = + kMaxHexDigits > padding ? kMaxHexDigits : static_cast(padding); + PERFETTO_DCHECK(size_needed <= kBufferSize); + PERFETTO_DCHECK(pos_ + size_needed <= size_); + + std::array data; + constexpr char hex_asc[] = "0123456789abcdef"; + + size_t idx = size_needed - 1; + auto uvalue = static_cast(value); + do { + data[idx--] = hex_asc[uvalue & 0xF]; + uvalue >>= 4; + } while (uvalue != 0); + + if (padding > 0) { + const auto num_digits = static_cast(size_needed - 1 - idx); + // std::max() needed to work around GCC not being able to tell that + // padding > 0. + for (auto i = num_digits; i < std::max(uint64_t{1u}, padding); i++) { + data[idx--] = padchar; + } + } + AppendString(&data[idx + 1], size_needed - idx - 1); + } + + // Appends a hex integer to the buffer. + template + void AppendHexInt(IntType value) { + AppendPaddedHexInt(value, '0', 0); + } + + // Appends a hex string to the buffer. + void AppendHexString(const uint8_t* data, size_t size, char separator); + + void AppendHexString(StringView data, char separator) { + AppendHexString(reinterpret_cast(data.data()), data.size(), + separator); + } + + // Appends a double to the buffer. + void AppendDouble(double value) { + // TODO(lalitm): trying to optimize this is premature given we almost never + // print doubles. Reevaluate this in the future if we do print them more. + size_t res = base::SprintfTrunc(buffer_ + pos_, size_ - pos_, "%lf", value); + PERFETTO_DCHECK(pos_ + res <= size_); + pos_ += res; + } + + void AppendBool(bool value) { + if (value) { + AppendLiteral("true"); + return; + } + AppendLiteral("false"); + } + + StringView GetStringView() { + PERFETTO_DCHECK(pos_ <= size_); + return StringView(buffer_, pos_); + } + + char* CreateStringCopy() { + char* dup = reinterpret_cast(malloc(pos_ + 1)); + if (dup) { + memcpy(dup, buffer_, pos_); + dup[pos_] = '\0'; + } + return dup; + } + + size_t pos() const { return pos_; } + size_t size() const { return size_; } + void reset() { pos_ = 0; } + + private: + template + void AppendPaddedInt(uint64_t absolute_value, bool negate) { + // Need to add 2 to the number of digits to account for minus sign and + // rounding down of digits10. + constexpr auto kMaxDigits = std::numeric_limits::digits10 + 2; + constexpr auto kSizeNeeded = kMaxDigits > padding ? kMaxDigits : padding; + PERFETTO_DCHECK(pos_ + kSizeNeeded <= size_); + + char data[kSizeNeeded]; + + size_t idx; + for (idx = kSizeNeeded - 1; absolute_value >= 10;) { + char digit = absolute_value % 10; + absolute_value /= 10; + data[idx--] = digit + '0'; + } + data[idx--] = static_cast(absolute_value) + '0'; + + if (padding > 0) { + size_t num_digits = kSizeNeeded - 1 - idx; + // std::max() needed to work around GCC not being able to tell that + // padding > 0. + for (size_t i = num_digits; i < std::max(uint64_t{1u}, padding); i++) { + data[idx--] = padchar; + } + } + + if (negate) + buffer_[pos_++] = '-'; + AppendString(&data[idx + 1], kSizeNeeded - idx - 1); + } + + char* buffer_ = nullptr; + size_t size_ = 0; + size_t pos_ = 0; +}; + +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_FIXED_STRING_WRITER_H_ +/* + * Copyright (C) 2026 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/fixed_string_writer.h" + +#include +#include +#include + +namespace perfetto { +namespace base { + +void FixedStringWriter::AppendHexString(const uint8_t* data, + size_t size, + char separator) { + // Truncate to 64 bytes, as this is the maximum supported by the Linux + // kernel's vsnprintf implementation. + size_t printed_size = std::min(size, size_t{64}); + // Remove trailing separator from calculation if printed_size > 0. + size_t max_chars = printed_size * 3 - (printed_size > 0 ? 1 : 0); + PERFETTO_DCHECK(pos_ + max_chars <= size_); + + if (printed_size) { + AppendPaddedHexInt(data[0], '0', 2); + } + for (size_t pos = 1; pos < printed_size; pos++) { + AppendChar(separator); + AppendPaddedHexInt(data[pos], '0', 2); + } +} + +} // namespace base +} // namespace perfetto +// gen_amalgamated begin source: src/base/getopt_compat.cc +// gen_amalgamated begin header: include/perfetto/ext/base/getopt_compat.h +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_ +#define INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_ + +#include // For std::nullptr_t + +// No translation units other than base/getopt.h and getopt_compat_unittest.cc +// should directly include this file. Use base/getopt.h instead. + +namespace perfetto { +namespace base { +namespace getopt_compat { + +// A tiny getopt() replacement for Windows, which doesn't have . +// This implementation is based on the subset of features that we use in the +// Perfetto codebase. It doesn't even try to deal with the full surface of GNU's +// getopt(). +// Limitations: +// - getopt_long_only() is not supported. +// - optional_argument is not supported. That is extremely subtle and caused us +// problems in the past with GNU's getopt. +// - It does not reorder non-option arguments. It behaves like MacOS getopt, or +// GNU's when POSIXLY_CORRECT=1. +// - Doesn't expose optopt or opterr. +// - option.flag and longindex are not supported and must be nullptr. + +enum { + no_argument = 0, + required_argument = 1, +}; + +struct option { + const char* name; + int has_arg; + std::nullptr_t flag; // Only nullptr is supported. + int val; +}; + +extern char* optarg; +extern int optind; +extern int optopt; +extern int opterr; + +int getopt_long(int argc, + char** argv, + const char* shortopts, + const option* longopts, + std::nullptr_t /*longindex is not supported*/); + +int getopt(int argc, char** argv, const char* shortopts); + +} // namespace getopt_compat +} // namespace base +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_EXT_BASE_GETOPT_COMPAT_H_ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * 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. + */ + +// gen_amalgamated expanded: #include "perfetto/ext/base/getopt_compat.h" + +#include +#include +#include + +#include + +// gen_amalgamated expanded: #include "perfetto/base/logging.h" + +namespace perfetto { +namespace base { +namespace getopt_compat { + +char* optarg = nullptr; +int optind = 0; +int optopt = 0; +int opterr = 1; + +namespace { + +char* nextchar = nullptr; + +const option* LookupLongOpt(const std::vector