// 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 <string>
// 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)
}
// namespace base
}
// namespace perfetto
#endif // 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.
*/
// gen_amalgamated expanded: #include "perfetto/ext/base/android_utils.h"
// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
#include <string>
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#include <sys/system_properties.h>
#endif
// gen_amalgamated expanded: #include "perfetto/base/compiler.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
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<std::string*>(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<size_t>(len) <
sizeof(value_buf)) {
ret = std::string(value_buf,
static_cast<size_t>(len));
}
#endif
return ret;
}
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
}
// 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/string_view.h
// gen_amalgamated begin header: include/perfetto/ext/base/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_HASH_H_
#define INCLUDE_PERFETTO_EXT_BASE_HASH_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
namespace perfetto {
namespace 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 Hasher {
public:
// Creates an empty hash object
constexpr Hasher() =
default;
// Hashes a numeric value.
template <
typename T,
typename std::enable_if<std::is_arithmetic<T>::value,
bool>::type =
true>
void Update(T data) {
Update(
reinterpret_cast<
const char*>(&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<uint8_t>(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 <
typename T,
typename = std::enable_if_t<T::kHashable>>
constexpr
void Update(
const T& t) {
if constexpr (std::is_member_function_pointer_v<decltype(&T::data)>) {
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 = Hash::Combine(33, false, "ABC", 458L, 3u, 'x');
template <
typename... Ts>
static constexpr uint64_t Combine(Ts&&... args) {
Hasher hasher;
hasher.UpdateAll(std::forward<Ts>(args)...);
return hasher.digest();
}
// Creates a hasher with `args` already hashed.
//
// Usage:
// Hasher partial = Hash::CreatePartial(33, false, "ABC", 458L);
template <
typename... Ts>
static constexpr Hasher CreatePartial(Ts&&... args) {
Hasher hasher;
hasher.UpdateAll(std::forward<Ts>(args)...);
return hasher;
}
// `hasher.UpdateAll(33, false, "ABC")` is shorthand for:
// `hasher.Update(33); hasher.Update(false); hasher.Update("ABC");`
constexpr
void UpdateAll() {}
template <
typename T,
typename... Ts>
constexpr
void UpdateAll(T&& arg, Ts&&... args) {
Update(arg);
UpdateAll(std::forward<Ts>(args)...);
}
private:
static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
static constexpr uint64_t kFnv1a64Prime = 0x100000001b3;
uint64_t result_ = kFnv1a64OffsetBasis;
};
// This is for using already-hashed key into std::unordered_map and avoid the
// cost of re-hashing. Example:
// unordered_map<uint64_t, Value, AlreadyHashed> my_map.
template <
typename T>
struct AlreadyHashed {
size_t
operator()(
const T& x)
const {
return static_cast<size_t>(x); }
};
// base::Hash uses base::Hasher for integer values and falls base 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 <
typename T>
struct Hash {
// Version for ints, using base::Hasher.
template <
typename U = T>
auto operator()(
const U& x) ->
typename std::enable_if<std::is_arithmetic<U>::value, size_t>::type
const {
Hasher hash;
hash.Update(x);
return static_cast<size_t>(hash.digest());
}
// Version for non-ints, falling back to std::hash.
template <
typename U = T>
auto operator()(
const U& x) ->
typename std::enable_if<!std::is_arithmetic<U>::value, size_t>::type
const {
return std::hash<U>()(x);
}
};
}
// namespace base
}
// namespace perfetto
#endif // INCLUDE_PERFETTO_EXT_BASE_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 <string.h>
#include <algorithm>
#include <string>
#include <vector>
// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
// gen_amalgamated expanded: #include "perfetto/base/logging.h"
// gen_amalgamated expanded: #include "perfetto/ext/base/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::Hash.
static constexpr
bool kHashable =
true;
static constexpr size_t npos =
static_cast<size_t>(-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 <
typename T,
typename = std::enable_if<T::kConvertibleToStringView>>
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);
}
// 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<size_t>(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<StringView>& 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::Hasher 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<size_t>(sv.Hash());
}
};
#endif // INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_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 <sys/types.h>
// IWYU pragma: export
#include <cstdint>
// gen_amalgamated expanded: #include "perfetto/base/build_config.h"
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#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 pid_t =
int;
#endif // !GCC
#if defined(_WIN64)
using ssize_t = int64_t;
#else
using ssize_t =
long;
#endif // _WIN64
#endif // OS_WIN
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && !
defined(AID_SHELL)
// From libcutils' android_filesystem_config.h .
#define AID_SHELL 2000
#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<uid_t>(-1);
constexpr pid_t kInvalidPid =
static_cast<pid_t>(-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 <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <atomic>
#include <functional>
#include <memory>
#include <string>
// 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<uint32_t> 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 <
typename T, size_t TSize>
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<int, base::FreeDeleter> foo_ptr(
// static_cast<int*>(malloc(sizeof(int))));
struct FreeDeleter {
inline void operator()(
void* ptr)
const { free(ptr); }
};
template <
typename T>
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 <size_t alignment>
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<
int()> 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 <
typename T>
struct AlignedDeleter {
inline void operator()(T* ptr)
const { AlignedFree(ptr); }
};
// The remove_extent<T> here and below is to allow defining unique_ptr<T[]>.
// As per https://en.cppreference.com/w/cpp/memory/unique_ptr the Deleter takes
// always a T*, not a T[]*.
template <
typename T>
using AlignedUniquePtr =
std::unique_ptr<T, AlignedDeleter<
typename std::remove_extent<T>::type>>;
template <
typename T>
AlignedUniquePtr<T> AlignedAllocTyped(size_t n_membs) {
using TU =
typename std::remove_extent<T>::type;
return AlignedUniquePtr<T>(
static_cast<TU*>(AlignedAlloc(alignof(TU),
sizeof(TU) * n_membs)));
}
// A RAII wrapper to invoke a function when leaving a function/scope.
template <
typename Func>
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 <
typename Func>
PERFETTO_WARN_UNUSED_RESULT OnScopeExitWrapper<Func> OnScopeExit(Func f) {
return OnScopeExitWrapper<Func>(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 <optional>
#include <string>
// 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<std::string> Base64Decode(
const char* src, size_t src_size);
inline std::optional<std::string> 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<
const uint8_t*>(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<uint8_t>((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<uint8_t>((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<ssize_t>(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<ssize_t>(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<uint8_t>((d[0] << 2) | (d[1] >> 4));
dst[wr_size + 1] =
static_cast<uint8_t>((d[1] << 4) | (d[2] >> 2));
dst[wr_size + 2] =
static_cast<uint8_t>((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<ssize_t>(wr_size);
}
std::optional<std::string> Base64Decode(
const char* src, size_t src_size) {
std::string dst;
dst.resize(Base64DecSize(src_size));
auto res = Base64Decode(src, src_size,
reinterpret_cast<uint8_t*>(&dst[0]),
dst.size());
if (res < 0)
return std::nullopt;
// Decoding error.
PERFETTO_CHECK(res <=
static_cast<ssize_t>(dst.size()));
dst.resize(
static_cast<size_t>(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 <algorithm>
#include <atomic>
#include <stdint.h>
#include <string.h>
// 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<
bool> registered_;
std::atomic<Type> type_;
const char*
const name_;
union {
std::atomic<
char> str_value_[kCrashKeyMaxStrSize];
std::atomic<int64_t> 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_
// gen_amalgamated begin header: include/perfetto/ext/base/string_utils.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 <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <charconv>
#include <cinttypes>
#include <optional>
#include <string>
#include <system_error>
#include <vector>
// 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<
char>(c - (
'A' -
'a')) : c;
}
inline char Uppercase(
char c) {
return (
'a' <= c && c <=
'z') ?
static_cast<
char>(c + (
'A' -
'a')) : c;
}
inline std::optional<uint32_t> CStringToUInt32(
const char* s,
int base = 10) {
char* endptr = nullptr;
auto value =
static_cast<uint32_t>(strtoul(s, &endptr, base));
return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
}
inline std::optional<int32_t> CStringToInt32(
const char* s,
int base = 10) {
char* endptr = nullptr;
auto value =
static_cast<int32_t>(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<int64_t> CStringToInt64(
const char* s,
int base = 10) {
char* endptr = nullptr;
auto value =
static_cast<int64_t>(strtoll(s, &endptr, base));
return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
}
inline std::optional<uint64_t> CStringToUInt64(
const char* s,
int base = 10) {
char* endptr = nullptr;
auto value =
static_cast<uint64_t>(strtoull(s, &endptr, base));
return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
}
double StrToD(
const char* nptr,
char** endptr);
inline std::optional<
double> CStringToDouble(
const char* s) {
char* endptr = nullptr;
double value = StrToD(s, &endptr);
std::optional<
double> result(std::nullopt);
if (*s !=
'\0' && *endptr ==
'\0')
result = value;
return result;
}
inline std::optional<uint32_t> StringToUInt32(
const std::string& s,
int base = 10) {
return CStringToUInt32(s.c_str(), base);
}
inline std::optional<int32_t> StringToInt32(
const std::string& s,
int base = 10) {
return CStringToInt32(s.c_str(), base);
}
inline std::optional<uint64_t> StringToUInt64(
const std::string& s,
int base = 10) {
return CStringToUInt64(s.c_str(), base);
}
inline std::optional<int64_t> StringToInt64(
const std::string& s,
int base = 10) {
return CStringToInt64(s.c_str(), base);
}
inline std::optional<
double> StringToDouble(
const std::string& s) {
return CStringToDouble(s.c_str());
}
template <
typename T>
inline std::optional<T> 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<uint32_t> 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<std::optional<uint32_t> >(
StringViewToNumber<int32_t>(sv, base));
}
else {
return StringViewToNumber<uint32_t>(sv, base);
}
}
inline std::optional<int32_t> StringViewToInt32(
const base::StringView& sv,
int base = 10) {
return StringViewToNumber<int32_t>(sv, base);
}
inline std::optional<uint64_t> 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<std::optional<uint64_t> >(
StringViewToNumber<int64_t>(sv, base));
}
else {
return StringViewToNumber<uint64_t>(sv, base);
}
}
inline std::optional<int64_t> StringViewToInt64(
const base::StringView& sv,
int base = 10) {
return StringViewToNumber<int64_t>(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<double> StringViewToDouble(const base::StringView& sv) {
// return StringViewToNumber<double>(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<std::string>& prefixes);
bool Contains(
const std::string& haystack,
const std::string& needle);
bool Contains(
const std::string& haystack,
char 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<std::string>& parts,
const std::string& delim);
std::vector<std::string> 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);
#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<LineWithOffset> 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 <size_t N>
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<size_t>(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/crash_keys.h"
#include <string.h>
#include <atomic>
#include <cinttypes>
// gen_amalgamated expanded: #include "perfetto/ext/base/string_utils.h"
namespace perfetto {
namespace base {
namespace {
constexpr size_t kMaxKeys = 32;
std::atomic<CrashKey*> g_keys[kMaxKeys]{};
std::atomic<uint32_t> 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 <Windows.h>
#include <io.h>
#else
#include <signal.h>
#include <unistd.h>
#endif
namespace perfetto {
namespace base {
namespace {
CtrlCHandlerFunction g_handler = nullptr;
}
void InstallCtrlCHandler(CtrlCHandlerFunction handler) {
PERFETTO_CHECK(g_handler == nullptr);
g_handler = handler;
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
auto trampoline = [](DWORD type) -> int {
if (type == CTRL_C_EVENT) {
g_handler();
return true;
}
return false;
};
::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<decltype(sa.sa_flags)>(SA_RESETHAND | SA_RESTART);
#else // POSIX-compliant
sa.sa_flags = static_cast<decltype(sa.sa_flags)>(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 <stdio.h>
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <dirent.h> // For DIR* / opendir().
#endif
#include <string>
// 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 <typename T, T InvalidValue>
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 <typename T,
int (*CloseFunction)(T),
T InvalidValue,
bool CheckClose = true,
class Checker = internal::DefaultValidityChecker<T, InvalidValue>>
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<int, CloseFile, -1>;
using ScopedFstream = ScopedResource<FILE*, fclose, nullptr>;
// Use this for resources that are HANDLE on Windows. See comments in
// platform_handle.h
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
using ScopedPlatformHandle = ScopedResource<PlatformHandle,
ClosePlatformHandle,
/*InvalidValue=*/nullptr,
/*CheckClose=*/true,
PlatformHandleChecker>;
#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<int, PlatformHandle>::value, "");
using ScopedPlatformHandle = ScopedFile;
// DIR* does not exist on Windows.
using ScopedDir = ScopedResource<DIR*, closedir, nullptr>;
#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"
--> --------------------
--> maximum size reached
--> --------------------