#include "perfetto/ext/base/utils.h"
#include <string>
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/pipe.h"
#include "perfetto/ext/base/string_utils.h"
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
#include <mach-o/dyld.h>
#include <mach/vm_page_size.h>
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#include <linux/prctl.h>
#include <sys/prctl.h>
#ifndef PR_GET_TAGGED_ADDR_CTRL
#define PR_GET_TAGGED_ADDR_CTRL …
#endif
#ifndef PR_TAGGED_ADDR_ENABLE
#define PR_TAGGED_ADDR_ENABLE …
#endif
#ifndef PR_MTE_TCF_SYNC
#define PR_MTE_TCF_SYNC …
#endif
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <io.h>
#include <malloc.h>
#endif
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#include <dlfcn.h>
#include <malloc.h>
#ifdef M_PURGE
#define PERFETTO_M_PURGE …
#else
#define PERFETTO_M_PURGE …
#endif
#ifdef M_PURGE_ALL
#define PERFETTO_M_PURGE_ALL …
#else
#define PERFETTO_M_PURGE_ALL …
#endif
namespace {
extern "C" {
using MalloptType = int (*)(int, int);
}
}
#endif
namespace {
#if PERFETTO_BUILDFLAG(PERFETTO_X64_CPU_OPT)
#define PERFETTO_GETCPUID …
uint32_t GetXCR0EAX() {
uint32_t eax = 0, edx = 0;
asm("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
return eax;
}
void PERFETTO_EXPORT_COMPONENT __attribute__((constructor))
CheckCpuOptimizations() {
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
PERFETTO_GETCPUID(eax, ebx, ecx, edx, 1, 0);
static constexpr uint64_t xcr0_xmm_mask = 0x2;
static constexpr uint64_t xcr0_ymm_mask = 0x4;
static constexpr uint64_t xcr0_avx_mask = xcr0_xmm_mask | xcr0_ymm_mask;
const bool have_popcnt = ecx & (1u << 23);
const bool have_sse4_2 = ecx & (1u << 20);
const bool have_avx =
(ecx & (1u << 27)) &&
(ecx & (1u << 28)) &&
((GetXCR0EAX() & xcr0_avx_mask) == xcr0_avx_mask);
PERFETTO_GETCPUID(eax, ebx, ecx, edx, 7, 0);
const bool have_avx2 = have_avx && ((ebx >> 5) & 0x1);
const bool have_bmi = (ebx >> 3) & 0x1;
const bool have_bmi2 = (ebx >> 8) & 0x1;
if (!have_sse4_2 || !have_popcnt || !have_avx2 || !have_bmi || !have_bmi2) {
fprintf(
stderr,
"This executable requires a x86_64 cpu that supports SSE4.2, BMI2 and "
"AVX2.\n"
#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
"On MacOS, this might be caused by running x86_64 binaries on arm64.\n"
"See https://github.com/google/perfetto/issues/294 for more.\n"
#endif
"Rebuild with enable_perfetto_x64_cpu_opt=false.\n");
_exit(126);
}
}
#endif
}
namespace perfetto {
namespace base {
namespace internal {
std::atomic<uint32_t> g_cached_page_size{ … };
uint32_t GetSysPageSizeSlowpath() { … }
}
void MaybeReleaseAllocatorMemToOS() { … }
uid_t GetCurrentUserId() { … }
void SetEnv(const std::string& key, const std::string& value) { … }
void UnsetEnv(const std::string& key) { … }
void Daemonize(std::function<int()> parent_cb) { … }
std::string GetCurExecutablePath() { … }
std::string GetCurExecutableDir() { … }
void* AlignedAlloc(size_t alignment, size_t size) { … }
void AlignedFree(void* ptr) { … }
bool IsSyncMemoryTaggingEnabled() { … }
std::string HexDump(const void* data_void, size_t len, size_t bytes_per_line) { … }
}
}