static void InitMalloc(MallocDebug* table, int debug_level, const char* prefix) { /* BEGIN mtk-modified: log for debug 15 and 16 */ if (debug_level == 15 || debug_level == 16) { __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s: using MALLOC_DEBUG = %d\n", __progname, debug_level); } else __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n", __progname, debug_level, prefix); /* END mtk-modified. */ char symbol[128]; snprintf(symbol, sizeof(symbol), "%s_malloc", prefix); table->malloc = reinterpret_cast<MallocDebugMalloc>(dlsym(libc_malloc_impl_handle, symbol)); if (table->malloc == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_free", prefix); table->free = reinterpret_cast<MallocDebugFree>(dlsym(libc_malloc_impl_handle, symbol)); if (table->free == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_calloc", prefix); table->calloc = reinterpret_cast<MallocDebugCalloc>(dlsym(libc_malloc_impl_handle, symbol)); if (table->calloc == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_realloc", prefix); table->realloc = reinterpret_cast<MallocDebugRealloc>(dlsym(libc_malloc_impl_handle, symbol)); if (table->realloc == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_memalign", prefix); table->memalign = reinterpret_cast<MallocDebugMemalign>(dlsym(libc_malloc_impl_handle, symbol)); if (table->memalign == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } }
/* * Runtime implementation of __umask_chk. * * Validate that umask is called with sane mode. * * This umask check is called if _FORTIFY_SOURCE is defined and * greater than 0. */ extern "C" mode_t __umask_chk(mode_t mode) { if ((mode & 0777) != mode) { __libc_android_log_print(ANDROID_LOG_FATAL, "libc", "*** FORTIFY_SOURCE: umask called with invalid mask ***\n"); abort(); } return umask(mode); }
/* * Runtime implementation of __builtin____memset_chk. * * See * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html * http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html * for details. * * This memset check is called if _FORTIFY_SOURCE is defined and * greater than 0. */ extern "C" void *__memset_chk (void *dest, int c, size_t n, size_t dest_len) { if (n > dest_len) { __libc_android_log_print(ANDROID_LOG_FATAL, "libc", "*** memset buffer overflow detected ***\n"); __libc_android_log_event_uid(BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW); abort(); } return memset(dest, c, n); }
/* * __strlcat_chk. Called in place of strlcat() when we know the * size of the buffer we're writing into. * * See * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html * http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html * for details. * * This strlcat check is called if _FORTIFY_SOURCE is defined and * greater than 0. */ extern "C" size_t __strlcat_chk(char *dest, const char *src, size_t supplied_size, size_t dest_len_from_compiler) { if (supplied_size > dest_len_from_compiler) { __libc_android_log_print(ANDROID_LOG_FATAL, "libc", "*** strlcat buffer overflow detected ***\n"); abort(); } return strlcat(dest, src, supplied_size); }
/* * Runtime implementation of __memcpy_chk. * * See * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html * http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html * for details. * * This memcpy check is called if _FORTIFY_SOURCE is defined and * greater than 0. */ extern "C" void *__memcpy_chk(void *dest, const void *src, size_t copy_amount, size_t dest_len) { if (__builtin_expect(copy_amount > dest_len, 0)) { __libc_android_log_print(ANDROID_LOG_FATAL, "libc", "*** memcpy buffer overflow detected ***\n"); __libc_android_log_event_uid(BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW); abort(); } return memcpy(dest, src, copy_amount); }
/* * Runtime implementation of __builtin____memmove_chk. * * See * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html * http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html * for details. * * This memmove check is called if _FORTIFY_SOURCE is defined and * greater than 0. */ extern "C" void *__memmove_chk (void *dest, const void *src, size_t len, size_t dest_len) { if (len > dest_len) { __libc_android_log_print(ANDROID_LOG_FATAL, "libc", "*** memmove buffer overflow detected ***\n"); __libc_android_log_event_uid(BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW); abort(); } return memmove(dest, src, len); }
static void InitMalloc(MallocDebug* table, int debug_level, const char* prefix) { __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s: using libc.debug.malloc %d (%s)\n", __progname, debug_level, prefix); char symbol[128]; snprintf(symbol, sizeof(symbol), "%s_malloc", prefix); table->malloc = reinterpret_cast<MallocDebugMalloc>(dlsym(libc_malloc_impl_handle, symbol)); if (table->malloc == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_free", prefix); table->free = reinterpret_cast<MallocDebugFree>(dlsym(libc_malloc_impl_handle, symbol)); if (table->free == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_calloc", prefix); table->calloc = reinterpret_cast<MallocDebugCalloc>(dlsym(libc_malloc_impl_handle, symbol)); if (table->calloc == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_realloc", prefix); table->realloc = reinterpret_cast<MallocDebugRealloc>(dlsym(libc_malloc_impl_handle, symbol)); if (table->realloc == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } snprintf(symbol, sizeof(symbol), "%s_memalign", prefix); table->memalign = reinterpret_cast<MallocDebugMemalign>(dlsym(libc_malloc_impl_handle, symbol)); if (table->memalign == NULL) { error_log("%s: dlsym(\"%s\") failed", __progname, symbol); } }
/* Initializes memory allocation framework once per process. */ static void malloc_init_impl(void) { const char* so_name = NULL; MallocDebugInit malloc_debug_initialize = NULL; unsigned int qemu_running = 0; unsigned int debug_level = 0; unsigned int memcheck_enabled = 0; char env[PROP_VALUE_MAX]; char memcheck_tracing[PROP_VALUE_MAX]; // added by zmj mspace_malloc_stat = NULL; mspace_free_stat = NULL; #ifdef _MTK_ENG_ debug_level = 15; #else debug_level = 0; #endif /* Get custom malloc debug level. Note that emulator started with * memory checking option will have priority over debug level set in * libc.debug.malloc system property. */ if (__system_property_get("ro.kernel.qemu", env) && atoi(env)) { qemu_running = 1; if (__system_property_get("ro.kernel.memcheck", memcheck_tracing)) { if (memcheck_tracing[0] != '0') { // Emulator has started with memory tracing enabled. Enforce it. debug_level = 20; memcheck_enabled = 1; } } } /* If debug level has not been set by memcheck option in the emulator, * lets grab it from libc.debug.malloc system property. */ if ((debug_level != 20) && __system_property_get("libc.debug.malloc", env)) { debug_level = atoi(env); } if ((debug_level != 20) && __system_property_get("persist.libc.debug.malloc", env)) { debug_level = atoi(env); } if (__system_property_get("ro.build.type", env)) { if(strncmp(env, "eng", 3)) debug_level = 0; } /* Debug level 0 means that we should use dlxxx allocation * routines (default). */ if (!debug_level) { return; } // Lets see which .so must be loaded for the requested debug level switch (debug_level) { case 1: case 5: case 10: so_name = "/system/lib/libc_malloc_debug_leak.so"; break; case 15: case 16: so_name = "/system/lib/libc_malloc_debug_mtk.so"; break; case 20: // Quick check: debug level 20 can only be handled in emulator. if (!qemu_running) { error_log("%s: Debug level %d can only be set in emulator\n", __progname, debug_level); return; } // Make sure that memory checking has been enabled in emulator. if (!memcheck_enabled) { error_log("%s: Memory checking is not enabled in the emulator\n", __progname); return; } so_name = "/system/lib/libc_malloc_debug_qemu.so"; break; default: error_log("%s: Debug level %d is unknown\n", __progname, debug_level); return; } // Load .so that implements the required malloc debugging functionality. libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY); if (libc_malloc_impl_handle == NULL) { error_log("%s: Missing module %s required for malloc debug level %d\n", __progname, so_name, debug_level); return; } // Initialize malloc debugging in the loaded module. malloc_debug_initialize = dlsym(libc_malloc_impl_handle, "malloc_debug_initialize"); if (malloc_debug_initialize == NULL) { error_log("%s: Initialization routine is not found in %s\n", __progname, so_name); dlclose(libc_malloc_impl_handle); return; } if (malloc_debug_initialize()) { dlclose(libc_malloc_impl_handle); return; } if (debug_level == 20) { // For memory checker we need to do extra initialization. int (*memcheck_initialize)(int, const char*) = dlsym(libc_malloc_impl_handle, "memcheck_initialize"); if (memcheck_initialize == NULL) { error_log("%s: memcheck_initialize routine is not found in %s\n", __progname, so_name); dlclose(libc_malloc_impl_handle); return; } if (memcheck_initialize(MALLOC_ALIGNMENT, memcheck_tracing)) { dlclose(libc_malloc_impl_handle); return; } } if (debug_level == 15) { int sig = 0; // For debug 15 we need to do extra initialization. int (*debug15_extra_initialize)(int) = dlsym(libc_malloc_impl_handle, "debug15_extra_initialize"); if (debug15_extra_initialize == NULL) { error_log("%s: malloc_debug_extra_initialize routine is not found in %s\n", __progname, so_name); dlclose(libc_malloc_impl_handle); return; } if (__system_property_get("persist.debug15.sig", env)) { sig = atoi(env); } if (debug15_extra_initialize(sig)) { dlclose(libc_malloc_impl_handle); return; } // to indicate that debug 15 is on. __system_property_set("libc.debug15.status", "on"); } // Initialize malloc dispatch table with appropriate routines. switch (debug_level) { case 1: __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s using MALLOC_DEBUG = %d (leak checker)\n", __progname, debug_level); gMallocUse.malloc = dlsym(libc_malloc_impl_handle, "leak_malloc"); gMallocUse.free = dlsym(libc_malloc_impl_handle, "leak_free"); gMallocUse.calloc = dlsym(libc_malloc_impl_handle, "leak_calloc"); gMallocUse.realloc = dlsym(libc_malloc_impl_handle, "leak_realloc"); gMallocUse.memalign = dlsym(libc_malloc_impl_handle, "leak_memalign"); break; case 5: __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s using MALLOC_DEBUG = %d (fill)\n", __progname, debug_level); gMallocUse.malloc = dlsym(libc_malloc_impl_handle, "fill_malloc"); gMallocUse.free = dlsym(libc_malloc_impl_handle, "fill_free"); gMallocUse.calloc = dlcalloc; gMallocUse.realloc = dlsym(libc_malloc_impl_handle, "fill_realloc"); gMallocUse.memalign = dlsym(libc_malloc_impl_handle, "fill_memalign"); break; case 10: __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s using MALLOC_DEBUG = %d (sentinels, fill)\n", __progname, debug_level); gMallocUse.malloc = dlsym(libc_malloc_impl_handle, "chk_malloc"); gMallocUse.free = dlsym(libc_malloc_impl_handle, "chk_free"); gMallocUse.calloc = dlsym(libc_malloc_impl_handle, "chk_calloc"); gMallocUse.realloc = dlsym(libc_malloc_impl_handle, "chk_realloc"); gMallocUse.memalign = dlsym(libc_malloc_impl_handle, "chk_memalign"); break; case 15: __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s using MALLOC_DEBUG = %d(dlmalloc, BT)\n", __progname, debug_level); gMallocUse.malloc = dlsym(libc_malloc_impl_handle, "mtk_malloc"); gMallocUse.free = dlsym(libc_malloc_impl_handle, "mtk_free"); gMallocUse.calloc = dlsym(libc_malloc_impl_handle, "mtk_calloc"); gMallocUse.realloc = dlsym(libc_malloc_impl_handle, "mtk_realloc"); gMallocUse.memalign = dlsym(libc_malloc_impl_handle, "mtk_memalign"); gpMallocFullBacktrace = dlsym(libc_malloc_impl_handle, "mtk_malloc_full_backtrace"); gpFreeFullBacktrace = dlsym(libc_malloc_impl_handle, "mtk_free_full_backtrace"); break; case 16: __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s using MALLOC_DEBUG = %d (dlmalloc, mspace, BT)\n", __progname, debug_level); gMallocUse.malloc = dlsym(libc_malloc_impl_handle, "mtk_malloc"); gMallocUse.free = dlsym(libc_malloc_impl_handle, "mtk_free"); gMallocUse.calloc = dlsym(libc_malloc_impl_handle, "mtk_calloc"); gMallocUse.realloc = dlsym(libc_malloc_impl_handle, "mtk_realloc"); gMallocUse.memalign = dlsym(libc_malloc_impl_handle, "mtk_memalign"); mspace_malloc_stat = dlsym(libc_malloc_impl_handle, "mtk_mspace_malloc_stat"); mspace_free_stat = dlsym(libc_malloc_impl_handle, "mtk_mspace_free_stat"); break; case 20: __libc_android_log_print(ANDROID_LOG_INFO, "libc", "%s[%u] using MALLOC_DEBUG = %d (instrumented for emulator)\n", __progname, getpid(), debug_level); gMallocUse.malloc = dlsym(libc_malloc_impl_handle, "qemu_instrumented_malloc"); gMallocUse.free = dlsym(libc_malloc_impl_handle, "qemu_instrumented_free"); gMallocUse.calloc = dlsym(libc_malloc_impl_handle, "qemu_instrumented_calloc"); gMallocUse.realloc = dlsym(libc_malloc_impl_handle, "qemu_instrumented_realloc"); gMallocUse.memalign = dlsym(libc_malloc_impl_handle, "qemu_instrumented_memalign"); break; default: break; } // Make sure dispatch table is initialized if ((gMallocUse.malloc == NULL) || (gMallocUse.free == NULL) || (gMallocUse.calloc == NULL) || (gMallocUse.realloc == NULL) || (gMallocUse.memalign == NULL)) { error_log("%s: Cannot initialize malloc dispatch table for debug level" " %d: %p, %p, %p, %p, %p\n", __progname, debug_level, gMallocUse.malloc, gMallocUse.free, gMallocUse.calloc, gMallocUse.realloc, gMallocUse.memalign); dlclose(libc_malloc_impl_handle); libc_malloc_impl_handle = NULL; } else { __libc_malloc_dispatch = &gMallocUse; } }