mozmemory_wrap.cpp (4399B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include <string.h> 8 #include "mozmemory_wrap.h" 9 #include "mozilla/Types.h" 10 11 // Declare malloc implementation functions with the right return and 12 // argument types. 13 #define NOTHROW_MALLOC_DECL(name, return_type, ...) \ 14 MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__) noexcept(true); 15 #define MALLOC_DECL(name, return_type, ...) \ 16 MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__); 17 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC 18 #include "malloc_decls.h" 19 20 // strndup and strdup may be defined as macros in string.h, which would 21 // clash with the definitions below. 22 #undef strndup 23 #undef strdup 24 25 MOZ_MEMORY_API char* strndup_impl(const char* src, size_t len) { 26 char* dst = (char*)malloc_impl(len + 1); 27 if (dst) { 28 strncpy(dst, src, len); 29 dst[len] = '\0'; 30 } 31 return dst; 32 } 33 34 MOZ_MEMORY_API char* strdup_impl(const char* src) { 35 size_t len = strlen(src); 36 return strndup_impl(src, len); 37 } 38 39 #ifdef ANDROID 40 # include <stdarg.h> 41 # include <stdio.h> 42 43 MOZ_MEMORY_API int vasprintf_impl(char** str, const char* fmt, va_list ap) { 44 char *ptr, *_ptr; 45 int ret; 46 47 if (str == NULL || fmt == NULL) { 48 return -1; 49 } 50 51 ptr = (char*)malloc_impl(128); 52 if (ptr == NULL) { 53 *str = NULL; 54 return -1; 55 } 56 57 ret = vsnprintf(ptr, 128, fmt, ap); 58 if (ret < 0) { 59 free_impl(ptr); 60 *str = NULL; 61 return -1; 62 } 63 64 _ptr = reinterpret_cast<char*>(realloc_impl(ptr, ret + 1)); 65 if (_ptr == NULL) { 66 free_impl(ptr); 67 *str = NULL; 68 return -1; 69 } 70 71 *str = _ptr; 72 73 return ret; 74 } 75 76 MOZ_MEMORY_API int asprintf_impl(char** str, const char* fmt, ...) { 77 int ret; 78 va_list ap; 79 va_start(ap, fmt); 80 81 ret = vasprintf_impl(str, fmt, ap); 82 83 va_end(ap); 84 85 return ret; 86 } 87 #endif 88 89 #ifdef XP_WIN 90 # include <wchar.h> 91 92 // We also need to provide our own impl of wcsdup so that we don't ask 93 // the CRT for memory from its heap (which will then be unfreeable). 94 MOZ_MEMORY_API wchar_t* wcsdup_impl(const wchar_t* src) { 95 size_t len = wcslen(src); 96 wchar_t* dst = (wchar_t*)malloc_impl((len + 1) * sizeof(wchar_t)); 97 if (dst) wcsncpy(dst, src, len + 1); 98 return dst; 99 } 100 101 MOZ_MEMORY_API void* _aligned_malloc_impl(size_t size, size_t alignment) { 102 return memalign_impl(alignment, size); 103 } 104 105 # ifdef __MINGW32__ 106 MOZ_BEGIN_EXTERN_C 107 // As in mozjemalloc.cpp, we generate aliases for functions 108 // redirected in mozglue.def 109 void* _aligned_malloc(size_t size, size_t alignment) 110 __attribute__((alias(MOZ_STRINGIFY(_aligned_malloc_impl)))); 111 void _aligned_free(void* aPtr) __attribute__((alias(MOZ_STRINGIFY(free_impl)))); 112 113 char* strndup(const char* src, size_t len) 114 __attribute__((alias(MOZ_STRINGIFY(strdup_impl)))); 115 char* strdup(const char* src) 116 __attribute__((alias(MOZ_STRINGIFY(strdup_impl)))); 117 char* _strdup(const char* src) 118 __attribute__((alias(MOZ_STRINGIFY(strdup_impl)))); 119 wchar_t* wcsdup(const wchar_t* src) 120 __attribute__((alias(MOZ_STRINGIFY(wcsdup_impl)))); 121 wchar_t* _wcsdup(const wchar_t* src) 122 __attribute__((alias(MOZ_STRINGIFY(wcsdup_impl)))); 123 124 // jemalloc has _aligned_malloc, and friends. libc++.a contains 125 // references to __imp__aligned_malloc (and friends) because it 126 // is declared dllimport in the headers. 127 // 128 // The linker sees jemalloc's _aligned_malloc symbol in our objects, 129 // but then libc++.a comes along and needs __imp__aligned_malloc, which 130 // pulls in those parts of libucrt.a (or libmsvcrt.a in practice), 131 // which define both __imp__aligned_malloc and _aligned_malloc, and 132 // this causes a conflict. (And repeat for each of the symbols defined 133 // here.) 134 // 135 // The fix is to define not only an _aligned_malloc symbol (via an 136 // alias), but also define the __imp__aligned_malloc pointer to it. 137 // This prevents those parts of libucrt from being pulled in and causing 138 // conflicts. 139 // This is done with __MINGW_IMP_SYMBOL to handle x86/x64 differences. 140 void (*__MINGW_IMP_SYMBOL(_aligned_free))(void*) = _aligned_free; 141 void* (*__MINGW_IMP_SYMBOL(_aligned_malloc))(size_t, size_t) = _aligned_malloc; 142 char* (*__MINGW_IMP_SYMBOL(_strdup))(const char* src) = _strdup; 143 MOZ_END_EXTERN_C 144 # endif 145 #endif // XP_WIN