15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat <opensource@google.com>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We define mmap() and mmap64(), which somewhat reimplements libc's mmap
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// syscall stubs.  Unfortunately libc only exports the stubs via weak symbols
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (which we're overriding with our mmap64() and mmap() wrappers) so we can't
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just call through to them.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __linux
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error Should only be including malloc_hook_mmap_linux.h on linux systems.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#if defined(__ANDROID__)
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <sys/syscall.h>
45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <sys/linux-syscalls.h>
46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#else
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <syscall.h>
48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/linux_syscall_support.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// SYS_mmap2, SYS_munmap, SYS_mremap and __off64_t are not defined in Android.
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#if defined(__ANDROID__)
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(__NR_mmap) && !defined(SYS_mmap)
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define SYS_mmap __NR_mmap
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef SYS_mmap2
59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define SYS_mmap2 __NR_mmap2
60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef SYS_munmap
62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define SYS_munmap __NR_munmap
63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef SYS_mremap
65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define SYS_mremap __NR_mremap
66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)typedef off64_t __off64_t;
68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif  // defined(__ANDROID__)
69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The x86-32 case and the x86-64 case differ:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 32b has a mmap2() syscall, 64b does not.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 64b and 32b have different calling conventions for mmap().
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// I test for 64-bit first so I don't have to do things like
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// '#if (defined(__mips__) && !defined(__MIPS64__))' as a mips32 check.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__x86_64__) || defined(__PPC64__) || (defined(_MIPS_SIM) && _MIPS_SIM == _ABI64)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void* do_mmap64(void *start, size_t length,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int prot, int flags,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int fd, __off64_t offset) __THROW {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The original gperftools uses sys_mmap() here.  But, it is not allowed by
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chromium's sandbox.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (void *)syscall(SYS_mmap, start, length, prot, flags, fd, offset);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MALLOC_HOOK_HAVE_DO_MMAP64 1
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__i386__) || defined(__PPC__) || defined(__mips__) || \
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      defined(__arm__)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void* do_mmap64(void *start, size_t length,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int prot, int flags,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int fd, __off64_t offset) __THROW {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *result;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try mmap2() unless it's not supported
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool have_mmap2 = true;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (have_mmap2) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static int pagesize = 0;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pagesize) pagesize = getpagesize();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that the offset is page aligned
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (offset & (pagesize - 1)) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = MAP_FAILED;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errno = EINVAL;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto out;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = (void *)syscall(SYS_mmap2,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             start, length, prot, flags, fd,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (off_t) (offset / pagesize));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != MAP_FAILED || errno != ENOSYS)  goto out;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't have mmap2() after all - don't bother trying it in future
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    have_mmap2 = false;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (((off_t)offset) != offset) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we're trying to map a 64-bit offset, fail now since we don't
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // have 64-bit mmap() support.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = MAP_FAILED;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errno = EINVAL;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto out;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __NR_mmap
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fall back to old 32-bit offset mmap() call
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Old syscall interface cannot handle six args, so pass in an array
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 args[6] = { (int32) start, (int32) length, prot, flags, fd,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      (off_t) offset };
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = (void *)syscall(SYS_mmap, args);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some Linux ports like ARM EABI Linux has no mmap, just mmap2.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MAP_FAILED;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MALLOC_HOOK_HAVE_DO_MMAP64 1
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // #if defined(__x86_64__)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef MALLOC_HOOK_HAVE_DO_MMAP64
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use do_mmap64 abstraction to put MallocHook::InvokeMmapHook
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calls right into mmap and mmap64, so that the stack frames in the caller's
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stack are at the same offsets for all the calls of memory allocating
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Put all callers of MallocHook::Invoke* in this module into
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// malloc_hook section,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so that MallocHook::GetCallerStackTrace can function accurately:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure mmap doesn't get #define'd away by <sys/mman.h>
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# undef mmap
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* mmap64(void *start, size_t length, int prot, int flags,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int fd, __off64_t offset  ) __THROW
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ATTRIBUTE_SECTION(malloc_hook);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* mmap(void *start, size_t length,int prot, int flags,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             int fd, off_t offset) __THROW
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ATTRIBUTE_SECTION(malloc_hook);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int munmap(void* start, size_t length) __THROW
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ATTRIBUTE_SECTION(malloc_hook);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* mremap(void* old_addr, size_t old_size, size_t new_size,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int flags, ...) __THROW
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ATTRIBUTE_SECTION(malloc_hook);
174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#if !defined(__ANDROID__)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* sbrk(ptrdiff_t increment) __THROW
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ATTRIBUTE_SECTION(malloc_hook);
177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void* mmap64(void *start, size_t length, int prot, int flags,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int fd, __off64_t offset) __THROW {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *result;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!MallocHook::InvokeMmapReplacement(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          start, length, prot, flags, fd, offset, &result)) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = do_mmap64(start, length, prot, flags, fd, offset);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void* mmap(void *start, size_t length, int prot, int flags,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int fd, off_t offset) __THROW {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *result;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!MallocHook::InvokeMmapReplacement(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          start, length, prot, flags, fd, offset, &result)) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = do_mmap64(start, length, prot, flags, fd,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       static_cast<size_t>(offset)); // avoid sign extension
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif  // !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int munmap(void* start, size_t length) __THROW {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeMunmapHook(start, length);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The original gperftools uses sys_munmap() here.  But, it is not allowed
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by Chromium's sandbox.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = syscall(SYS_munmap, start, length);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void* mremap(void* old_addr, size_t old_size, size_t new_size,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int flags, ...) __THROW {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list ap;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start(ap, flags);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *new_address = va_arg(ap, void *);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(ap);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The original gperftools uses sys_mremap() here.  But, it is not allowed by
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chromium's sandbox.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* result = (void *)syscall(
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SYS_mremap, old_addr, old_size, new_size, flags, new_address);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeMremapHook(result, old_addr, old_size, new_size, flags,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               new_address);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Don't hook sbrk() in Android, since it doesn't expose __sbrk.
236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#if !defined(__ANDROID__)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// libc's version:
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void* __sbrk(ptrdiff_t increment);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void* sbrk(ptrdiff_t increment) __THROW {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokePreSbrkHook(increment);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *result = __sbrk(increment);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MallocHook::InvokeSbrkHook(result, increment);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif  // !defined(__ANDROID__)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int flags, int fd, off_t offset) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* result;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!MallocHook::InvokeMmapReplacement(
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          start, length, prot, flags, fd, offset, &result)) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = do_mmap64(start, length, prot, flags, fd, offset);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = syscall(SYS_munmap, start, length);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MALLOC_HOOK_HAVE_DO_MMAP64
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // #ifdef MALLOC_HOOK_HAVE_DO_MMAP64
269