2023-01-28 04:54:20 +00:00
|
|
|
|
// Copyright 2017 The Crashpad Authors
|
2022-04-02 01:21:55 +00:00
|
|
|
|
//
|
|
|
|
|
// 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 <sys/mman.h>
|
|
|
|
|
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include "dlfcn_internal.h"
|
|
|
|
|
#include "util/misc/no_cfi_icall.h"
|
|
|
|
|
|
|
|
|
|
#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 21
|
|
|
|
|
|
|
|
|
|
// Bionic has provided a wrapper for __mmap2() since the beginning of time. See
|
|
|
|
|
// bionic/libc/SYSCALLS.TXT in any Android version.
|
|
|
|
|
extern "C" void* __mmap2(void* addr,
|
|
|
|
|
size_t size,
|
|
|
|
|
int prot,
|
|
|
|
|
int flags,
|
|
|
|
|
int fd,
|
|
|
|
|
size_t pgoff);
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
T Align(T value, size_t alignment) {
|
|
|
|
|
return (value + alignment - 1) & ~(alignment - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adapted from Android 8.0.0 bionic/libc/bionic/mmap.cpp.
|
|
|
|
|
void* LocalMmap64(void* addr,
|
|
|
|
|
size_t size,
|
|
|
|
|
int prot,
|
|
|
|
|
int flags,
|
|
|
|
|
int fd,
|
|
|
|
|
off64_t offset) {
|
|
|
|
|
constexpr int kMmap2Shift = 12;
|
|
|
|
|
|
|
|
|
|
if (offset < 0 || (offset & ((1UL << kMmap2Shift) - 1)) != 0) {
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return MAP_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const size_t rounded = Align(size, getpagesize());
|
|
|
|
|
if (rounded < size || rounded > PTRDIFF_MAX) {
|
|
|
|
|
errno = ENOMEM;
|
|
|
|
|
return MAP_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool is_private_anonymous =
|
|
|
|
|
(flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
|
|
|
|
|
const bool is_stack_or_grows_down =
|
|
|
|
|
(flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
|
|
|
|
|
|
|
|
|
|
void* const result =
|
|
|
|
|
__mmap2(addr, size, prot, flags, fd, offset >> kMmap2Shift);
|
|
|
|
|
|
|
|
|
|
static bool kernel_has_MADV_MERGEABLE = true;
|
|
|
|
|
if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
|
|
|
|
|
is_private_anonymous && !is_stack_or_grows_down) {
|
|
|
|
|
const int saved_errno = errno;
|
|
|
|
|
const int rc = madvise(result, size, MADV_MERGEABLE);
|
|
|
|
|
if (rc == -1 && errno == EINVAL) {
|
|
|
|
|
kernel_has_MADV_MERGEABLE = false;
|
|
|
|
|
}
|
|
|
|
|
errno = saved_errno;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
|
|
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
|
|
|
|
|
// Use the system’s mmap64() wrapper if available. It will be available on
|
|
|
|
|
// Android 5.0 (“Lollipop”) and later.
|
|
|
|
|
static const crashpad::NoCfiIcall<decltype(LocalMmap64)*> mmap64(
|
|
|
|
|
crashpad::internal::Dlsym(RTLD_DEFAULT, "mmap64"));
|
|
|
|
|
if (mmap64) {
|
|
|
|
|
return mmap64(addr, size, prot, flags, fd, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise, use the local implementation, which should amount to exactly the
|
|
|
|
|
// same thing.
|
|
|
|
|
return LocalMmap64(addr, size, prot, flags, fd, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // extern "C"
|
|
|
|
|
|
|
|
|
|
#endif // defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 21
|