| /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- |
| * Copyright (c) 2023, gperftools Contributors |
| * All rights reserved. |
| * |
| * 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 Inc. 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. |
| */ |
| |
| // mmap_hook.h holds strictly non-public API for hooking mmap/sbrk |
| // events as well invoking mmap/munmap with ability to bypass hooks |
| // (i.e. for low_level_alloc). |
| #ifndef MMAP_HOOK_H |
| #define MMAP_HOOK_H |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include "base/basictypes.h" |
| |
| namespace tcmalloc { |
| |
| struct DirectAnonMMapResult { |
| void* addr; |
| bool success; |
| }; |
| |
| // DirectAnonMMap does mmap of r+w anonymous memory. Optionally |
| // bypassing or not mmap hooks. |
| ATTRIBUTE_VISIBILITY_HIDDEN DirectAnonMMapResult DirectAnonMMap(bool invoke_hooks, size_t length); |
| // DirectMUnMap does munmap of given region optionally bypassing mmap hooks. |
| ATTRIBUTE_VISIBILITY_HIDDEN int DirectMUnMap(bool invoke_hooks, void* start, size_t length); |
| |
| // We use those by tests to see what parts we think should work. |
| extern ATTRIBUTE_VISIBILITY_HIDDEN const bool mmap_hook_works; |
| extern ATTRIBUTE_VISIBILITY_HIDDEN const bool sbrk_hook_works; |
| |
| // MMapEventFn gets this struct with all the details of |
| // mmap/munmap/mremap/sbrk event. |
| struct MappingEvent { |
| MappingEvent() { |
| memset(this, 0, sizeof(*this)); |
| } |
| |
| // before_XXX fields describe address space chunk that was removed |
| // from address space (say via munmap or mremap) |
| void* before_address; |
| size_t before_length; |
| |
| // after_XXX fields describe address space chunk that was added to |
| // address space. |
| void* after_address; |
| size_t after_length; |
| |
| // This group of fields gets populated from mmap file, flags, prot |
| // fields. |
| int prot; |
| int flags; |
| int file_fd; |
| int64_t file_off; |
| |
| unsigned after_valid:1; |
| unsigned before_valid:1; |
| unsigned file_valid:1; |
| unsigned is_sbrk:1; |
| |
| // NOTE, in order to get mapping event backtrace you need to request |
| // it via need_backtrace callback. |
| int stack_depth; |
| void** stack; |
| }; |
| |
| // Pass this to Hook/Unhook function below. Note, nature of |
| // implementation requires that this chunk of memory must be valid |
| // even after unhook. So typical use-case is to use global variable |
| // storage. |
| // |
| // All fields are private. |
| class MappingHookSpace { |
| public: |
| constexpr MappingHookSpace() = default; |
| |
| bool initialized = false; |
| |
| static constexpr size_t kSize = sizeof(void*) * 4; |
| alignas(alignof(void*)) char storage[kSize] = {}; |
| }; |
| |
| using MMapEventFn = void (*)(const MappingEvent& evt); |
| using MMapEventNeedBacktraceFn = int (*)(const MappingEvent& evt); |
| |
| // HookMMapEvents address hook for mmap events, using given place to |
| // store relevant metadata (linked list membership etc). |
| // |
| // It does no memory allocation and is safe to be called from hooks of all kinds. |
| ATTRIBUTE_VISIBILITY_HIDDEN void HookMMapEvents(MappingHookSpace* place, MMapEventFn callback); |
| |
| ATTRIBUTE_VISIBILITY_HIDDEN void HookMMapEventsWithBacktrace(MappingHookSpace* place, MMapEventFn callback, |
| MMapEventNeedBacktraceFn need_backtrace); |
| |
| // UnHookMMapEvents undoes effect of HookMMapEvents. This one is also |
| // entirely safe to be called from out of anywhere. Including from |
| // inside MMapEventFn invokations. |
| // |
| // As noted on MappingHookSpace the place ***must not** be deallocated or |
| // reused for anything even after unhook. This requirement makes |
| // implementation simple enough and fits our internal usage use-case |
| // fine. |
| ATTRIBUTE_VISIBILITY_HIDDEN void UnHookMMapEvents(MappingHookSpace* place); |
| |
| } // namespace tcmalloc |
| |
| |
| #endif // MMAP_HOOK_H |