diff options
Diffstat (limited to 'src/tracing/ipc/memfd.cc')
-rw-r--r-- | src/tracing/ipc/memfd.cc | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/tracing/ipc/memfd.cc b/src/tracing/ipc/memfd.cc new file mode 100644 index 000000000..64025bf41 --- /dev/null +++ b/src/tracing/ipc/memfd.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "src/tracing/ipc/memfd.h" + +#include <errno.h> + +#define PERFETTO_MEMFD_ENABLED() \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) + +#if PERFETTO_MEMFD_ENABLED() + +#include <stdio.h> +#include <string.h> +#include <sys/syscall.h> +#include <sys/utsname.h> +#include <unistd.h> + +// Some android build bots use a sysroot that doesn't support memfd when +// compiling for the host, so we redefine it if necessary. +#if !defined(__NR_memfd_create) +#if defined(__x86_64__) +#define __NR_memfd_create 319 +#elif defined(__i386__) +#define __NR_memfd_create 356 +#elif defined(__aarch64__) +#define __NR_memfd_create 279 +#elif defined(__arm__) +#define __NR_memfd_create 385 +#else +#error "unsupported sysroot without memfd support" +#endif +#endif // !defined(__NR_memfd_create) + +namespace perfetto { +bool HasMemfdSupport() { + static bool kSupportsMemfd = [] { + // Check kernel version supports memfd_create(). Some older kernels segfault + // executing memfd_create() rather than returning ENOSYS (b/116769556). + static constexpr int kRequiredMajor = 3; + static constexpr int kRequiredMinor = 17; + struct utsname uts; + int major, minor; + if (uname(&uts) == 0 && strcmp(uts.sysname, "Linux") == 0 && + sscanf(uts.release, "%d.%d", &major, &minor) == 2 && + ((major < kRequiredMajor || + (major == kRequiredMajor && minor < kRequiredMinor)))) { + return false; + } + + base::ScopedFile fd; + fd.reset(static_cast<int>(syscall(__NR_memfd_create, "perfetto_shmem", + MFD_CLOEXEC | MFD_ALLOW_SEALING))); + return !!fd; + }(); + return kSupportsMemfd; +} + +base::ScopedFile CreateMemfd(const char* name, unsigned int flags) { + if (!HasMemfdSupport()) { + errno = ENOSYS; + return base::ScopedFile(); + } + return base::ScopedFile( + static_cast<int>(syscall(__NR_memfd_create, name, flags))); +} +} // namespace perfetto + +#else // PERFETTO_MEMFD_ENABLED() + +namespace perfetto { +bool HasMemfdSupport() { + return false; +} +base::ScopedFile CreateMemfd(const char*, unsigned int) { + errno = ENOSYS; + return base::ScopedFile(); +} +} // namespace perfetto + +#endif // PERFETTO_MEMFD_ENABLED() |