Replace malloc_hook with preload
authorSung-jae Park <nicesj.park@samsung.com>
Fri, 23 Aug 2013 08:40:23 +0000 (17:40 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Fri, 23 Aug 2013 08:40:44 +0000 (17:40 +0900)
Change-Id: Icc6979bc5e64b6cfd98e862d44b28a580749963b

CMakeLists.txt
include/allocator.h [new file with mode: 0644]
include/debug.h [new file with mode: 0644]
include/heap-monitor.h
include/heap-monitor_internal.h [new file with mode: 0644]
packaging/libheap-monitor.spec
src/allocator.c [new file with mode: 0644]
src/dlist.c
src/heap-monitor.c

index e0469e8..78549d7 100644 (file)
@@ -13,32 +13,26 @@ set(CMAKE_SKIP_BUILD_RPATH true)
 
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
 
-INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED
-       dlog
-)
-
-FOREACH(flag ${pkgs_CFLAGS})
-       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
-ENDFOREACH(flag)
-
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline -fno-builtin-malloc -O3 -g -Wno-error=deprecated-declarations")
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wno-error=deprecated-declarations")
 
 ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
 ADD_DEFINITIONS("-DNDEBUG")
+ADD_DEFINITIONS("-DFLOG")
 ADD_DEFINITIONS("-DLOG_TAG=\"HEAP_MONITOR\"")
 ADD_DEFINITIONS("-D_THREAD_SAFETY")
+ADD_DEFINITIONS("-D_ESTIMATE_PERFORMANCE")
 
 ADD_LIBRARY(${PROJECT_NAME} SHARED
-       src/heap-monitor.c
+       src/allocator.c
        src/dlist.c
+       src/heap-monitor.c
 )
 
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} "-lpthread")
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} "-lpthread -ldl")
 
 CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
 SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc")
diff --git a/include/allocator.h b/include/allocator.h
new file mode 100644 (file)
index 0000000..406ec06
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+struct allocator;
+extern struct allocator *allocator_init(unsigned int base, unsigned int size);
+extern int allocator_fini(struct allocator *handle);
+extern void *allocator_alloc(struct allocator *handle, int size);
+extern void allocator_free(struct allocator *handle, void *ptr);
+extern unsigned int allocator_allocated_size(void *ptr);
+extern int allocator_in_scope(struct allocator *handle, void *addr);
+
+/* End of a file */
diff --git a/include/debug.h b/include/debug.h
new file mode 100644 (file)
index 0000000..ac0cb53
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#if !defined(FLOG)
+#define DbgPrint(format, arg...)
+#define ErrPrint(format, arg...)
+#define WarnPrint(format, arg...)
+#else
+extern FILE *__file_log_fp;
+#define DbgPrint(format, arg...) do { if (__file_log_fp) { fprintf(__file_log_fp, "[LOG] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } } while (0)
+#define ErrPrint(format, arg...) do { if (__file_log_fp) { fprintf(__file_log_fp, "[ERR] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } } while (0)
+#define WarnPrint(format, arg...) do { if (__file_log_fp) { fprintf(__file_log_fp, "[WRN] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } } while (0)
+#endif
+
+#if defined(_ESTIMATE_PERFORMANCE)
+#define ESTIMATE_START() \
+do { \
+       struct timeval stv; \
+       struct timeval etv; \
+       struct timeval rtv; \
+       static struct timeval ttv; \
+       static int initialized = 0; \
+       if (!initialized) { \
+               timerclear(&ttv); \
+               initialized = 1; \
+       } \
+       DbgPrint("Start\n"); \
+       gettimeofday(&stv, NULL)
+
+#define ESTIMATE_END() \
+       gettimeofday(&etv, NULL); \
+       gettimeofday(&etv, NULL); \
+       timersub(&etv, &stv, &rtv); \
+       timeradd(&rtv, &ttv, &ttv); \
+       DbgPrint("Elapsed time: %lu.%lf\n", rtv.tv_sec, (double)rtv.tv_usec / 1000000.0f); \
+       DbgPrint("Total: %lu.%lf\n", ttv.tv_sec, (double)ttv.tv_usec / 1000000.0f); \
+} while (0)
+
+
+#else
+#define ESTIMATE_START() // pthread_mutex_lock(&s_info.mutex)
+#define ESTIMATE_END() // pthread_mutex_unlock(&s_info.mutex)
+#endif
+
+#if defined(_THREAD_SAFETY)
+#define CRITICAL_SECTION_BEGIN(handle) \
+do { \
+       int ret; \
+       ret = pthread_mutex_lock(handle); \
+       if (ret != 0) { \
+               ErrPrint("Failed to lock: %s\n", strerror(ret)); \
+       } \
+} while (0)
+
+#define CRITICAL_SECTION_END(handle) \
+do { \
+       int ret; \
+       ret = pthread_mutex_unlock(handle); \
+       if (ret != 0) { \
+               ErrPrint("Failed to unlock: %s\n", strerror(ret)); \
+       } \
+} while (0)
+
+#define CANCEL_SECTION_BEGIN() do { \
+       int ret; \
+       ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); \
+       if (ret != 0) { \
+               ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \
+       } \
+} while (0)
+
+#define CANCEL_SECTION_END() do { \
+       int ret; \
+       ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); \
+       if (ret != 0) { \
+               ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \
+       } \
+} while (0)
+
+#else
+#define CRITICAL_SECTION_BEGIN(handle)
+#define CRITICAL_SECTION_END(handle)
+#define CANCEL_SECTION_BEGIN(handle)
+#define CANCEL_SECTION_END(handle)
+#endif
+
index e8a460b..2de6adf 100644 (file)
  */
 
 extern int heap_monitor_initialized(void);
-extern void heap_monitor_init(void);
-extern void heap_monitor_start(void);
-extern void heap_monitor_stop(void);
 extern size_t heap_monitor_target_usage(const char *name);
 extern int heap_monitor_add_target(const char *name);
 extern int heap_monitor_del_target(const char *name);
-extern void heap_monitor_set_stack_boundary(unsigned long stack_boundary);
+extern void heap_monitor_fini(void);
+extern void heap_monitor_init(void);
 
 /* End of a file */
diff --git a/include/heap-monitor_internal.h b/include/heap-monitor_internal.h
new file mode 100644 (file)
index 0000000..699eaf1
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+extern void *malloc_wrapper(size_t size);
+extern void *realloc_wrapper(void *ptr, size_t size);
+extern void free_wrapper(void *ptr);
+extern void *memalign_wrapper(size_t align, size_t size);
+
+/* End of all */
index d6227cf..8c1e010 100644 (file)
@@ -1,12 +1,11 @@
 Name: libheap-monitor
 Summary: Library for monitoring the heap usage
-Version: 0.0.15
+Version: 0.0.16
 Release: 1
 Group: HomeTF/Livebox
 License: Flora License
 Source0: %{name}-%{version}.tar.gz
 BuildRequires: cmake, gettext-tools, coreutils
-BuildRequires: pkgconfig(dlog)
 
 %description
 Monitoring the heap usage to manage them safely.
@@ -28,7 +27,7 @@ export CFLAGS="${CFLAGS} -DTIZEN_ENGINEER_MODE"
 export CXXFLAGS="${CXXFLAGS} -DTIZEN_ENGINEER_MODE"
 export FFLAGS="${FFLAGS} -DTIZEN_ENGINEER_MODE"
 %endif
-%cmake .
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
 CFLAGS+="${CFLAGS} -fvisibility=hidden -Wall -Werror -Winline -fno-builtin-malloc" make %{?jobs:-j%jobs}
 
 %install
diff --git a/src/allocator.c b/src/allocator.c
new file mode 100644 (file)
index 0000000..347aa0c
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <stdio.h>
+#include <sys/time.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <errno.h>
+#include <string.h>
+
+#include "debug.h"
+
+int errno;
+
+struct chunk {
+       struct chunk *prev;
+       struct chunk *next;
+
+       unsigned int size;
+       char data[];
+};
+
+struct allocator {
+       pthread_mutex_t mutex;
+       unsigned int size;
+       struct chunk *used;
+       struct chunk *freed;
+       char data[];
+};
+
+struct allocator *allocator_init(unsigned int base, unsigned int size)
+{
+       struct allocator *handle = (struct allocator *)base;
+       struct chunk *chunk;
+
+       handle->size = size - sizeof(*handle);
+
+       chunk = (struct chunk *)handle->data;
+
+       pthread_mutex_init(&handle->mutex, NULL);
+
+       handle->freed = chunk;
+       handle->used = NULL;
+
+       chunk->size = handle->size - sizeof(*chunk);
+       chunk->next = chunk;
+       chunk->prev = chunk;
+
+       return handle;
+}
+
+int allocator_fini(struct allocator *handle)
+{
+       pthread_mutex_destroy(&handle->mutex);
+       return 0;
+}
+
+unsigned int allocator_allocated_size(void *ptr)
+{
+       struct chunk *tmp = (struct chunk *)ptr;
+       return tmp->size;
+}
+
+void *allocator_alloc(struct allocator *handle, int size)
+{
+       struct chunk *tmp;
+       struct chunk *chunk;
+       void *ret = NULL;
+
+       if (!handle) {
+               return NULL;
+       }
+
+       CRITICAL_SECTION_BEGIN(&handle->mutex);
+       tmp = handle->freed;
+       if (!tmp) {
+               goto out;
+       }
+
+       do {
+               if (size > tmp->size) {
+                       continue;
+               } else if (tmp->size <= size + sizeof(*tmp)) {
+                       /*!
+                        * \note
+                        * If the remained free size is more smaller than "chunk structure" size,
+                        * Allocating a new chunk does not need make a new free node.
+                        * It cannot be used anymore, in this case,
+                        * Don't divide it into more smaller chunks.
+                        *
+                        * We call this "INTERNAL FRAGMENTATION".
+                        */
+                       chunk = tmp;
+
+                       chunk->prev->next = chunk->next;
+                       chunk->next->prev = chunk->prev;
+
+                       if (chunk == handle->freed) {
+                               handle->freed = chunk->next;
+
+                               if (handle->freed == chunk) {
+                                       handle->freed = NULL;
+                               }
+                       }
+               } else {
+                       tmp->size -= size + sizeof(*chunk);
+
+                       chunk = (struct chunk *)(tmp->data + tmp->size);
+                       chunk->size = size;
+               }
+
+               if (!handle->used) {
+                       handle->used = chunk;
+                       ret = (void *)chunk->data;
+
+                       chunk->next = chunk;
+                       chunk->prev = chunk;
+                       break;
+               }
+
+               /*!
+                * \note
+                * Now, we can re-use the "tmp".
+                * Because we will not take outer loop anymore.
+                * So re-use the "tmp" for insertion sorting.
+                */
+               tmp = handle->used;
+               if (tmp > chunk) {
+                       /*!
+                        * \note
+                        * Reassign the "chunk" to handle->used.
+                        */
+                       handle->used = chunk;
+               } else {
+                       do {
+                               if (tmp > chunk) {
+                                       break;
+                               }
+                       } while ((tmp = tmp->next) && tmp != handle->used);
+               }
+
+               tmp->prev->next = chunk;
+               chunk->prev = tmp->prev;
+               chunk->next = tmp;
+               tmp->prev = chunk;
+               ret = (void *)chunk->data;
+               break;
+       } while ((tmp = tmp->next) && tmp != handle->freed);
+
+out:
+       CRITICAL_SECTION_END(&handle->mutex);
+       return ret;
+}
+
+void allocator_free(struct allocator *handle, void *ptr)
+{
+       struct chunk *tmp;
+       struct chunk *chunk;
+
+       if (!ptr) {
+               return;
+       }
+
+       chunk = (struct chunk *)(((char *)ptr) - (unsigned int)(&((struct chunk *)0)->data));
+
+       CRITICAL_SECTION_BEGIN(&handle->mutex);
+       /*!
+        * \note
+        * Disconnecting from the used list.
+        */
+       chunk->prev->next = chunk->next;
+       chunk->next->prev = chunk->prev;
+
+       if (chunk == handle->used) {
+               handle->used = chunk->next;
+               if (handle->used == chunk) {
+                       handle->used = NULL;
+               }
+       }
+
+       /*!
+        * \note
+        * Insert a chunk to the free'd list.
+        */
+       if (!handle->freed) {
+               handle->freed = chunk;
+               chunk->next = chunk;
+               chunk->prev = chunk;
+               goto out;
+       }
+
+       tmp = handle->freed;
+
+       do {
+               if (tmp > chunk) {
+                       break;
+               }
+       } while ((tmp = tmp->next) && tmp != handle->freed);
+
+       if ((unsigned int)(chunk->data + chunk->size) == (unsigned int)tmp) {
+               /*!
+                * \note
+                * tmp is merged with the chunk.
+                * and if the tmp is same with handle->freed,
+                * assign chunk to handle->freed.
+                */
+               chunk->size += tmp->size + sizeof(*tmp);
+
+               chunk->next = tmp->next;
+               chunk->prev = tmp->prev;
+               chunk->next->prev = chunk;
+               chunk->prev->next = chunk;
+
+               if (handle->freed == tmp) {
+                       handle->freed = chunk;
+               }
+
+               /* Previous node is changed. try to merge with prev node again */
+               tmp = chunk->prev;
+               if ((unsigned int)(tmp->data + tmp->size) == (unsigned int)chunk) {
+                       tmp->size += chunk->size + sizeof(*chunk);
+
+                       tmp->next = chunk->next;
+                       chunk->next->prev = tmp;
+
+                       if (handle->freed == chunk) {
+                               handle->freed = tmp;
+                       }
+               }
+       } else if ((unsigned int)(tmp->data + tmp->size) == (unsigned int)chunk) {
+               /*!
+                * \note
+                * chunk is merged with the tmp.
+                * and if the chunk is same with handle->freed.
+                * assign tmp to handle->freed.
+                */
+               tmp->size += chunk->size + sizeof(*chunk);
+
+               /* Size of the node is changed. try to merge with next node again */
+               chunk = tmp->next;
+               if ((unsigned int)(tmp->data + tmp->size) == (unsigned int)chunk) {
+                       tmp->size += chunk->size + sizeof(*chunk);
+
+                       tmp->next = chunk->next;
+                       chunk->next->prev = tmp;
+               }
+       } else {
+               chunk->prev = tmp->prev;
+               tmp->prev->next = chunk;
+
+               chunk->next = tmp;
+               tmp->prev = chunk;
+       }
+
+out:
+       CRITICAL_SECTION_END(&handle->mutex);
+}
+
+int allocator_in_scope(struct allocator *handle, void *addr)
+{
+       unsigned int base = (unsigned int)handle;
+       unsigned int size = handle->size;
+       int valid;
+
+       valid = (base <= (unsigned int)addr && (unsigned int)addr < (base + size));
+       DbgPrint("Validate: %p (%d)\n", addr, valid);
+       return valid;
+}
+
+/* End of a file */
index 3ae571b..f947edc 100644 (file)
@@ -19,6 +19,7 @@
 #include <assert.h>
 
 #include "dlist.h"
+#include "heap-monitor_internal.h"
 
 /*!
  * \brief
@@ -44,7 +45,7 @@ struct dlist *dlist_append(struct dlist *list, void *data)
 {
        struct dlist *item;
 
-       item = malloc(sizeof(*item));
+       item = malloc_wrapper(sizeof(*item));
        if (!item) {
                return NULL;
        }
@@ -71,7 +72,7 @@ struct dlist *dlist_prepend(struct dlist *list, void *data)
 {
        struct dlist *item;
 
-       item = malloc(sizeof(*item));
+       item = malloc_wrapper(sizeof(*item));
        if (!item) {
                return NULL;
        }
@@ -123,7 +124,7 @@ struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
                list->prev = l->prev;
        }
 
-       free(l);
+       free_wrapper(l);
        return list;
 }
 
index 054a76a..5e91cec 100644 (file)
 #include <pthread.h>
 #include <link.h>
 #include <elf.h>
+#include <unistd.h>
+#include <stddef.h>
 #include <mcheck.h>
 
-#include <dlog.h>
-
 #include "dlist.h"
 #include "heap-monitor.h"
-
-#if !defined(SECURE_LOGD)
-#define SECURE_LOGD LOGD
-#endif
-
-#if !defined(SECURE_LOGE)
-#define SECURE_LOGE LOGE
-#endif
-
-#if !defined(SECURE_LOGW)
-#define SECURE_LOGW LOGW
-#endif
-
-#if !defined(FLOG)
-#define DbgPrint(format, arg...)       SECURE_LOGD("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
-#define ErrPrint(format, arg...)       SECURE_LOGE("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
-#else
-extern FILE *__file_log_fp;
-#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
-
-#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
-#endif
-/* End of a file */
+#include "allocator.h"
+#include "debug.h"
+#include "heap-monitor_internal.h"
 
 #define container_of(ptr, type, member) \
         ({ const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-        (type *)( (char *)__mptr - offsetof(type,member) );})
+        (type *)( (char *)__mptr - offsetof(type, member) );})
 
 #define API __attribute__((visibility("default")))
 #define DUMP_DEPTH 80000
 
-#if defined(_ESTIMATE_PERFORMANCE)
-#define ESTIMATE_START() \
-do { \
-       struct timeval stv; \
-       struct timeval etv; \
-       struct timeval rtv; \
-       static struct timeval ttv; \
-       static int initialized = 0; \
-       if (!initialized) { \
-               timerclear(&ttv); \
-               initialized = 1; \
-       } \
-       gettimeofday(&stv, NULL)
-
-#define ESTIMATE_END() \
-       gettimeofday(&etv, NULL); \
-       gettimeofday(&etv, NULL); \
-       timersub(&etv, &stv, &rtv); \
-       timeradd(&rtv, &ttv, &ttv); \
-       DbgPrint("Elapsed time: %lu.%lf\n", rtv.tv_sec, (double)rtv.tv_usec / 1000000.0f); \
-       DbgPrint("Total: %lu.%lf\n", ttv.tv_sec, (double)ttv.tv_usec / 1000000.0f); \
-} while (0)
-#else
-#define ESTIMATE_START() // pthread_mutex_lock(&s_info.mutex)
-#define ESTIMATE_END() // pthread_mutex_unlock(&s_info.mutex)
-#endif
-
-#if defined(_THREAD_SAFETY)
-#define LOCK() pthread_mutex_lock(&s_info.mutex)
-#define UNLOCK() pthread_mutex_unlock(&s_info.mutex)
-#else
-#define LOCK()
-#define UNLOCK()
-#endif
+typedef void *(*malloc_t)(size_t size);
+typedef void *(*realloc_t)(void *ptr, size_t size);
+typedef void (*free_t)(void *ptr);
+typedef void *(*memalign_t)(size_t align, size_t size);
+typedef void *(*calloc_t)(size_t nmemb, size_t size);
 
-typedef void *(*malloc_t)(size_t size, const void *caller);
-typedef void *(*realloc_t)(void *ptr, size_t size, const void *caller);
-typedef void (*free_t)(void *ptr, const void *caller);
-typedef void *(*memalign_t)(size_t align, size_t size, const void *caller);
+extern char etext, edata, end;
+FILE *__file_log_fp;
 
 int errno;
 
+enum state {
+       VALID = 0xbeefbeef,
+       INVALID = 0xdeaddead,
+       STACK = 0x00beef00,
+};
+
 struct chunk {
        struct target *info;
        int size;
        int pad;
-       enum {
-               VALID = 0xbeefbeef,
-               INVALID = 0xdeaddead
-       } state;
+       int state;
        char data[];
 };
 
-#define SET_PAD(ptr, pad) (*(((int *)ptr) - 2) = (pad))
-#define SET_STATE(ptr, state) (*(((int *)ptr) - 1) = (state))
-#define PAD(ptr) (*(((int *)ptr) - 2))
-#define STATE(ptr) (*(((int *)ptr) - 1))
-
 struct target {
        char *name;
        int usage;
@@ -137,15 +84,19 @@ static struct {
        struct dlist *target_list;
        int hook;
        int dump_depth;
-       unsigned long stack_boundary;
-       unsigned long stack_base;
        size_t stack_size;
-       pthread_mutex_t mutex;
+       unsigned long stack_base;
        int debugger;
        int target_cnt;
        pthread_t main_tid;
        int initialized;
-       int m_check;
+       int hooked;
+       struct allocator *alloc_handle;
+       char stack_memory[1048576];
+       unsigned int bloom_filter;
+#if defined(_THREAD_SAFETY)
+       pthread_mutex_t mutex;
+#endif
 } s_info = {
        ._malloc = NULL,
        ._realloc = NULL,
@@ -154,43 +105,55 @@ static struct {
        .target_list = NULL,
        .hook = 0,
        .dump_depth = DUMP_DEPTH,
-       .stack_boundary = 0,
-       .mutex = PTHREAD_MUTEX_INITIALIZER,
+       .stack_size = 0,
        .debugger = 0,
        .target_cnt = 0,
        .initialized = 0,
-       .m_check = 0,
+       .hooked = 0,
+       .alloc_handle = NULL,
+       .stack_memory = { 0, },
+       .bloom_filter = 0,
+#if defined(_THREAD_SAFETY)
+       .mutex = PTHREAD_MUTEX_INITIALIZER,
+#endif
 };
 
-static void unhook(void);
-static void hook(void);
-
 static inline struct target *find_target_by_name(const char *name)
 {
        struct dlist *l;
-       struct target *target;
+       struct target *target = NULL;
 
        dlist_foreach(s_info.target_list, l, target) {
                if (!strcmp(target->name, name)) {
-                       return target;
+                       break;
                }
+               target = NULL;
        }
-
-       return NULL;
+       return target;
 }
 
 static inline struct target *find_target_by_addr(unsigned long addr)
 {
        struct dlist *l;
-       struct target *target;
+       struct target *target = NULL;
 
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
        dlist_foreach(s_info.target_list, l, target) {
                if (target->begin <= addr && addr < target->end) {
-                       return target;
+                       break;
                }
+               target = NULL;
        }
+       CRITICAL_SECTION_END(&s_info.mutex);
 
-       return NULL;
+       return target;
+}
+
+static inline int MPROBE(void *ptr)
+{
+       enum mcheck_status status;
+       status = mprobe(ptr);
+       return status == MCHECK_DISABLED || status == MCHECK_OK;
 }
 
 /*!
@@ -215,7 +178,7 @@ static struct target *find_target_info(void)
 
        stack = (unsigned long *)&ret;
 
-       if (s_info.stack_boundary) {
+       if (s_info.stack_size) {
                pthread_t tid;
                unsigned long base;
                unsigned long boundary;
@@ -234,15 +197,14 @@ static struct target *find_target_info(void)
                        }
                } else {
                        base = s_info.stack_base;
-                       boundary = s_info.stack_boundary;
+                       boundary = s_info.stack_base + s_info.stack_size;
                }
 
                i = 0;
                while ((unsigned long)stack >= base && (unsigned long)stack < boundary) {
                        i++;
                        if (s_info.debugger) {
-                               DbgPrint("FP: %p, boundary: %p, INDEX: %d, ret: 0x%X\n",
-                                                               stack, boundary, i, *stack);
+                               DbgPrint("FP: %p, boundary: %p, INDEX: %d, ret: 0x%X\n", stack, (void *)boundary, i, (unsigned int)*stack);
                        }
 
                        target = find_target_by_addr(*stack++);
@@ -266,7 +228,6 @@ static struct target *find_target_info(void)
                        if (s_info.debugger) {
                                DbgPrint("[%d] Target[%s]: %d\n", i, target->name, target->usage);
                        }
-
                        return target;
                }
        }
@@ -274,85 +235,97 @@ static struct target *find_target_info(void)
        return NULL;
 }
 
-static void mcheck_cb(enum mcheck_status status)
+void *malloc_wrapper(size_t size)
 {
-       struct target *target;
-       switch (status) {
-       case MCHECK_DISABLED:
-               ErrPrint("mcheck is disabled\n");
-               break;
-       case MCHECK_OK:
-               ErrPrint("Consitency is ok\n");
-               break;
-       case MCHECK_HEAD:
-               target = find_target_info();
-               if (target) {
-                       ErrPrint("[HEAD] Inconsistency: %s\n", target->name);
-               }
-               break;
-       case MCHECK_TAIL:
-               target = find_target_info();
-               if (target) {
-                       ErrPrint("[HEAD] Inconsistency: %s\n", target->name);
-               }
-               break;
-       case MCHECK_FREE:
-               target = find_target_info();
-               if (target) {
-                       ErrPrint("[FREE] Inconsistency: %s\n", target->name);
-               }
-               break;
-       default:
-               break;
-       }
+       return s_info._malloc ? s_info._malloc(size) : NULL;
 }
 
-static inline int MPROBE(void *ptr)
+void *realloc_wrapper(void *ptr, size_t size)
 {
-       enum mcheck_status status;
+       return s_info._realloc ? s_info._realloc(ptr, size) : NULL;
+}
 
-       status = mprobe(ptr);
-       if (status == MCHECK_DISABLED) {
-               return 1;
+void free_wrapper(void *ptr)
+{
+       if (!s_info._free) {
+               s_info._free = dlsym(RTLD_NEXT, "free");
+               if (!s_info._free) {
+                       ErrPrint("Failed to find \"free\"\n");
+                       return;
+               }
        }
 
-       if (status != MCHECK_OK) {
-               mcheck_cb(status);
-               return 0;
-       }
+       s_info._free(ptr);
+}
 
-       return 1;
+void *memalign_wrapper(size_t align, size_t size)
+{
+       return s_info._memalign ? s_info._memalign(align, size) : NULL;
 }
 
-static void *heap_monitor_malloc(size_t size, const void *caller)
+API void *malloc(size_t size)
 {
        struct chunk *chunk;
        void *ptr = NULL;
 
-       LOCK();
-       unhook();
        ESTIMATE_START();
-       chunk = malloc(size + sizeof(*chunk));
-       if (chunk) {
-               chunk->info = find_target_info();
-               chunk->size = size;
+       if (s_info.initialized) {
+               chunk = malloc_wrapper(size + sizeof(*chunk));
+               if (!chunk) {
+                       goto out;
+               }
 
-               ptr = chunk->data;
-               SET_PAD(ptr, 0);
-               SET_STATE(ptr, VALID);
+               chunk->state = VALID;
+       } else {
+               CRITICAL_SECTION_BEGIN(&s_info.mutex);
+               if (!s_info.alloc_handle) {
+                       s_info.alloc_handle = allocator_init((unsigned int)s_info.stack_memory, sizeof(s_info.stack_memory));
+               }
+               CRITICAL_SECTION_END(&s_info.mutex);
 
-               if (chunk->info) {
-                       chunk->info->usage += size;
+               chunk = allocator_alloc(s_info.alloc_handle, size + sizeof(*chunk));
+               if (!chunk) {
+                       DbgPrint("Failed stack alloc\n");
+                       goto out;
                }
+
+               chunk->state = STACK;
+       }
+
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
+       chunk->info = find_target_info();
+       if (chunk->info) {
+               chunk->info->usage += size;
        }
+       CRITICAL_SECTION_END(&s_info.mutex);
+       chunk->size = size;
+       chunk->pad = 0;
+       ptr = chunk->data;
+
+out:
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
+       s_info.bloom_filter |= (unsigned int)ptr;
+       CRITICAL_SECTION_END(&s_info.mutex);
 
        ESTIMATE_END();
-       hook();
-       UNLOCK();
        return ptr;
 }
 
-static void heap_monitor_free(void *ptr, const void *caller)
+API void *calloc(size_t nmemb, size_t size)
+{
+       void *ptr;
+
+       size *= nmemb;
+
+       ptr = malloc(size);
+       if (ptr) {
+               memset(ptr, 0, size);
+       }
+
+       return ptr;
+}
+
+API void free(void *ptr)
 {
        struct chunk *chunk;
 
@@ -360,169 +333,154 @@ static void heap_monitor_free(void *ptr, const void *caller)
                return;
        }
 
-       LOCK();
-       unhook();
        ESTIMATE_START();
-
-       if (STATE(ptr) != VALID) {
-               DbgPrint("Unrecognizable chunk, do default operation\n");
-               chunk = ptr;
-               goto out;
-       }
-
-       chunk = container_of((void *)(((char *)ptr) - PAD(ptr)), struct chunk, data);
-       if (chunk->info) {
-               chunk->info->usage -= chunk->size;
+       if (!s_info.initialized) {
+               if (!s_info._free) {
+                       /*!
+                        * \note
+                        * If the "free" is called before initiate the heap-monitor,
+                        * Bind the "free" from here
+                        */
+                       s_info._free = dlsym(RTLD_NEXT, "free");
+                       if (!s_info._free) {
+                               exit(-EINVAL);
+                       }
+               }
        }
 
-       if (MPROBE(chunk)) {
-               SET_STATE(ptr, INVALID);
+       if (!s_info.alloc_handle) {
+               /*!
+                * \note
+                * If the allocator is not initiated,
+                * We don't need to validate the address.
+                * Just "free" it.
+                */
+               DbgPrint("Allocator is not initiated\n");
+               free_wrapper(ptr);
+       } else if ((s_info.bloom_filter & (unsigned int)ptr) != (unsigned int)ptr) {
+               DbgPrint("Bloom filtered\n");
+               free_wrapper(ptr);
        } else {
-               chunk = ptr;
-               if (MPROBE(chunk)) {
-                       DbgPrint("Successfully recovered\n");
+               chunk = container_of(ptr, struct chunk, data);
+               if(chunk->state == VALID) {
+                       if (MPROBE(chunk)) {
+                               if (chunk->info) {
+                                       chunk->info->usage -= chunk->size;
+                               }
+
+                               chunk->state = INVALID;
+                               ptr = (char *)chunk - chunk->pad;
+                       } else {
+                               DbgPrint("native free\n");
+                               ptr = chunk;
+                       }
+
+                       free_wrapper(ptr);
+               } else if (chunk->state == STACK || allocator_in_scope(s_info.alloc_handle, ptr)) {
+                       chunk->state = INVALID;
+                       ptr = (char *)chunk - chunk->pad;
+                       allocator_free(s_info.alloc_handle, ptr);
+               } else if (chunk->state == INVALID) {
+                       struct target *target;
+
+                       CRITICAL_SECTION_BEGIN(&s_info.mutex);
+                       target = find_target_info();
+                       ErrPrint("====== %p, %s\n", ptr, target->name);
+                       CRITICAL_SECTION_END(&s_info.mutex);
                } else {
-                       ErrPrint("Failed to recover\n");
-                       chunk = NULL; /* Do nothing */
-                       goto out;
+                       DbgPrint("native free\n");
+                       free_wrapper(ptr);
                }
        }
 
-out:
-       free(chunk);
        ESTIMATE_END();
-       hook();
-       UNLOCK();
        return;
 }
 
-static void *heap_monitor_realloc(void *__ptr, size_t size, const void *caller)
+API void *realloc(void *__ptr, size_t size)
 {
        void *ptr = NULL;
        struct chunk *chunk;
 
-       LOCK();
-       unhook();
+       if (!size) {
+               free(__ptr);
+       } else if (!__ptr) {
+               return malloc(size);
+       }
+
        ESTIMATE_START();
-       if (!__ptr) {
-               if (!size) {
+       /* Re-allocation */
+       if ((s_info.bloom_filter & (unsigned int)__ptr) != (unsigned int)__ptr) {
+               /* Move this to our boundary */
+
+               ptr = malloc(size);
+               if (!ptr) {
                        goto out;
                }
 
-               /* Allocation */
-               chunk = realloc(__ptr, size + sizeof(*chunk));
-               if (chunk) {
-                       chunk->info = find_target_info();
-                       chunk->size = size;
-                       ptr = chunk->data;
+               memcpy(ptr, __ptr, size);
 
-                       SET_PAD(ptr, 0);
-                       SET_STATE(ptr, VALID);
+               free_wrapper(__ptr);
+               goto out;
+       }
 
-                       if (chunk->info) {
-                               chunk->info->usage += size;
-                       }
+       if (!s_info.initialized) {
+               CRITICAL_SECTION_BEGIN(&s_info.mutex);
+               /*!
+                * We can do this. because allocator_free function has "void" return type.
+                * This is a small trick. ;) just for fun. Don't be mad with this trick.
+                */
+               if (!s_info.alloc_handle) {
+                       s_info.alloc_handle = allocator_init((unsigned int)s_info.stack_memory, sizeof(s_info.stack_memory));
                }
-       } else if (size == 0) {
-               /* Free */
-               if (STATE(__ptr) != VALID) {
-                       DbgPrint("Unrecognizable chunk, do default operation\n");
-                       ptr = realloc(__ptr, size);
-               } else {
-                       chunk = container_of((void *)(((char *)__ptr) - PAD(__ptr)), struct chunk, data);
-                       if (chunk->info) {
-                               chunk->info->usage -= chunk->size;
-                       }
+               CRITICAL_SECTION_END(&s_info.mutex);
+       }
 
-                       if (MPROBE(chunk)) {
-                               SET_STATE(__ptr, INVALID);
-                       } else {
-                               chunk = __ptr;
-                               if (MPROBE(chunk)) {
-                                       DbgPrint("Successfully recovered\n");
-                               } else {
-                                       ErrPrint("Failed to recover\n");
-                                       ptr = NULL;
-                                       goto out;
-                               }
-                       }
+       chunk = container_of(__ptr, struct chunk, data);
+       if (chunk->state == VALID) {
+               if (MPROBE((unsigned char *)chunk - chunk->pad)) {
+                       ptr = (unsigned char *)chunk - chunk->pad;
 
-                       ptr = realloc(chunk, size);
-               }
-       } else {
-               if (STATE(__ptr) != VALID) {
-                       DbgPrint("Unrecognizable chunk, do default operation\n");
-                       ptr = realloc(__ptr, size);
-               } else {
-                       int pad = PAD(__ptr);
+                       ptr = realloc_wrapper(ptr, size + sizeof(*chunk));
+                       if (ptr) {
+                               chunk = ptr;
 
-                       chunk = container_of((void *)(((char *)__ptr) - pad), struct chunk, data);
-                       if (MPROBE(chunk)) {
-                               ptr = realloc(chunk, size + sizeof(*chunk) + pad);
-                               if (ptr) {
-                                       struct chunk *new_chunk = ptr;
-
-                                       if (new_chunk->info) {
-                                               new_chunk->info->usage -= new_chunk->size;
-                                               new_chunk->info->usage += size;
-                                       }
-                                       new_chunk->size = size;
-                                       ptr = new_chunk->data + pad;
-
-                                       SET_STATE(ptr, VALID);
-                                       SET_PAD(ptr, pad);
-                                       /* Consider this, do we need to keep the alignment for realloc? */
-                               }
-                       } else {
-                               chunk = __ptr;
-                               if (!MPROBE(chunk)) {
-                                       ErrPrint("Failed to recover\n");
-                                       ptr = NULL;
-                                       goto out;
+                               if (chunk->info) {
+                                       /* Update allocation info */
+                                       chunk->info->usage -= chunk->size;
+                                       chunk->info->usage += size;
                                }
+                               chunk->size = size;
+                               chunk->pad = 0;
+                               chunk->state = VALID;
 
-                               ptr = realloc(chunk, size + sizeof(*chunk));
-                               if (ptr) {
-                                       void *tmp;
-                                       struct chunk *new_chunk;
-
-                                       tmp = malloc(size);
-                                       if (!tmp) {
-                                               ErrPrint("Heap: %s\n", strerror(errno));
-                                               ptr = NULL;
-                                               goto out;
-                                       }
-
-                                       memcpy(tmp, ptr, size);
-                                       memcpy(((char *)ptr) + sizeof(*chunk), tmp, size);
-                                       free(tmp);
-
-                                       new_chunk = ptr;
-                                       new_chunk->info = find_target_info();
-                                       if (new_chunk->info) {
-                                               new_chunk->info->usage += size;
-                                       }
-                                       new_chunk->size = size;
-                                       ptr = new_chunk->data;
-                                       SET_STATE(ptr, VALID);
-                                       SET_PAD(ptr, 0);
-
-                                       DbgPrint("Successfully recovered\n");
-                               } else {
-                                       DbgPrint("Failed to recover\n");
-                               }
+                               ptr = chunk->data;
                        }
                }
+       } else if (chunk->state == STACK || allocator_in_scope(s_info.alloc_handle, __ptr)) {
+               /*!
+                * Try allocate heap first.
+                * At last, we will replace all stack based chunk with heap based chunk via "realloc".
+                */
+               ptr = malloc(size);
+               if (!ptr) {
+                       goto out;
+               }
+
+               memcpy(ptr, __ptr, size);
+               allocator_free(s_info.alloc_handle, (char *)chunk - chunk->pad);
        }
 
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
+       s_info.bloom_filter |= (unsigned int)ptr;
+       CRITICAL_SECTION_END(&s_info.mutex);
+
 out:
        ESTIMATE_END();
-       hook();
-       UNLOCK();
        return ptr;
 }
 
-static void *heap_monitor_memalign(size_t align, size_t __size, const void *caller)
+API void *memalign(size_t align, size_t __size)
 {
        void *ptr = NULL;
        struct chunk *chunk;
@@ -533,66 +491,77 @@ static void *heap_monitor_memalign(size_t align, size_t __size, const void *call
                return NULL;
        }
 
-       LOCK();
-       unhook();
-       ESTIMATE_START();
-
        pad = align - (sizeof(*chunk) % align);
        size = sizeof(*chunk) + pad;
-       chunk = memalign(align, size + __size);
-       if (!chunk) {
-               goto out;
+
+       ESTIMATE_START();
+
+       if (!s_info.initialized) {
+               unsigned int aligned_offset;
+
+               CRITICAL_SECTION_BEGIN(&s_info.mutex);
+               if (!s_info.alloc_handle) {
+                       s_info.alloc_handle = allocator_init((unsigned int)s_info.stack_memory, sizeof(s_info.stack_memory));
+               }
+               CRITICAL_SECTION_END(&s_info.mutex);
+
+               /* Make more space for alignment the address */
+               size += align;
+               ptr = allocator_alloc(s_info.alloc_handle, size + __size);
+
+               aligned_offset = align - (((unsigned int)ptr) % align);
+               chunk = (struct chunk *)((char *)ptr + aligned_offset + pad);
+
+               chunk->pad = pad + aligned_offset;
+               chunk->state = STACK;
+
+               DbgPrint("Aligned stack: %p size: %d, pad: %d, offset: %d\n", ptr, size + __size, pad, aligned_offset);
+       } else {
+               ptr = memalign_wrapper(align, size + __size);
+               if (!ptr) {
+                       goto out;
+               }
+
+               chunk = (struct chunk *)((char *)ptr + pad);
+
+               chunk->pad = pad;
+               chunk->state = VALID;
        }
 
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
        chunk->info = find_target_info();
        if (chunk->info) {
                chunk->info->usage += __size;
        }
+       CRITICAL_SECTION_END(&s_info.mutex);
 
        chunk->size = __size;
-
-       ptr = chunk->data + pad;
-       SET_PAD(ptr, pad);
-       SET_STATE(ptr, VALID);
+       ptr = chunk->data;
 
 out:
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
+       s_info.bloom_filter |= (unsigned int)ptr;
+       CRITICAL_SECTION_END(&s_info.mutex);
        ESTIMATE_END();
-       hook();
-       UNLOCK();
        return ptr;
 }
 
-static void hook(void)
+API int posix_memalign(void **memptr, size_t alignment, size_t size)
 {
-       s_info.hook++;
-       if (s_info.hook == 1) {
-               __malloc_hook = heap_monitor_malloc;
-               __realloc_hook = heap_monitor_realloc;
-               __memalign_hook = heap_monitor_memalign;
-               __free_hook = heap_monitor_free;
+       if (!memptr) {
+               return -EINVAL;
        }
+
+       *memptr = memalign(alignment, size);
+
+       return *memptr ? 0 : -ENOMEM;
 }
 
-static void unhook(void)
+API void *vmalloc(size_t size)
 {
-       s_info.hook--;
-       if (s_info.hook == 0) {
-               __malloc_hook = s_info._malloc;
-               __realloc_hook = s_info._realloc;
-               __memalign_hook = s_info._memalign;
-               __free_hook = s_info._free;
-       }
+       return memalign(sysconf(_SC_PAGESIZE), size);
 }
 
-/* From GNU libc 2.14 this macro is defined, to declare
-   hook variables as volatile. Define it as empty for
-   older glibc versions */
-#ifndef __MALLOC_HOOK_VOLATILE
-     #define __MALLOC_HOOK_VOLATILE
-#endif
-
-void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook)(void) = heap_monitor_init;
-
 static int iterator_cb(struct dl_phdr_info *info, size_t size, void *data)
 {
        struct target *target;
@@ -602,6 +571,7 @@ static int iterator_cb(struct dl_phdr_info *info, size_t size, void *data)
        target = data;
 
        if (strcmp(info->dlpi_name, target->name)) {
+               DbgPrint("\n");
                return 0;
        }
 
@@ -611,8 +581,7 @@ static int iterator_cb(struct dl_phdr_info *info, size_t size, void *data)
                        target->begin = info->dlpi_addr + (unsigned long)phdr->p_vaddr;
                        target->end = target->begin + phdr->p_memsz;
                        if (s_info.debugger) {
-                               DbgPrint("Target: %s - [%s] 0x%lX - 0x%lX\n",
-                                                       target->name, info->dlpi_name, target->begin, target->end);
+                               DbgPrint("Target: %s - [%s] 0x%lX - 0x%lX\n", target->name, info->dlpi_name, target->begin, target->end);
                        }
                        break;
                }
@@ -625,80 +594,88 @@ API int heap_monitor_del_target(const char *name)
 {
        struct dlist *l;
        struct dlist *n;
-       struct target *target;
-       int ret;
+       struct target *target = NULL;
 
-       LOCK();
-       unhook();
-       ret = -ENOENT;
+       if (!s_info.initialized) {
+               return -EINVAL;
+       }
+
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
        dlist_foreach_safe(s_info.target_list, l, n, target) {
                if (!strcmp(target->name, name)) {
                        s_info.target_list = dlist_remove(s_info.target_list, l);
-                       free(target->name);
-                       free(target);
                        s_info.target_cnt--;
-                       ret = 0;
                        break;
                }
+               target = NULL;
+       }
+       CRITICAL_SECTION_END(&s_info.mutex);
+
+       if (target) {
+               DbgPrint("%s <> %s\n", target->name, name);
+               free_wrapper(target->name);
+               free_wrapper(target);
        }
-       hook();
-       UNLOCK();
 
-       return ret;
+       return target ? 0 : -ENOENT;
 }
 
 API int heap_monitor_add_target(const char *name)
 {
        struct target *target;
-       int ret;
 
-       LOCK();
-       unhook();
+       if (!s_info.initialized) {
+               return -EINVAL;
+       }
 
-       ret = 0;
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
        target = find_target_by_name(name);
        if (target) {
-               goto out;
+               ErrPrint("Target[%s] is already exists\n", name);
+               CRITICAL_SECTION_END(&s_info.mutex);
+               return 0;
        }
+       CRITICAL_SECTION_END(&s_info.mutex);
 
-       target = malloc(sizeof(*target));
+       target = malloc_wrapper(sizeof(*target));
        if (!target) {
                DbgPrint("Heap: %s\n", strerror(errno));
-               ret = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
-       target->name = strdup(name);
+       target->name = malloc_wrapper(strlen(name));
        if (!target->name) {
                DbgPrint("Heap: %s\n", strerror(errno));
-               free(target);
-               ret = -ENOMEM;
-               goto out;
+               free_wrapper(target);
+               return -ENOMEM;
        }
 
+       strcpy(target->name, name);
        target->usage = 0;
        target->begin = 0;
        target->end = 0;
 
        dl_iterate_phdr(iterator_cb, target);
 
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
        s_info.target_cnt++;
        s_info.target_list = dlist_append(s_info.target_list, target);
-out:
-       hook();
-       UNLOCK();
-       return ret;
+       CRITICAL_SECTION_END(&s_info.mutex);
+
+       DbgPrint("Target[%s] is added\n", name);
+       return 0;
 }
 
 API size_t heap_monitor_target_usage(const char *name)
 {
        struct target *target;
-       LOCK();
-       unhook();
+       size_t usage = 0;
+
+       CRITICAL_SECTION_BEGIN(&s_info.mutex);
        target = find_target_by_name(name);
-       hook();
-       UNLOCK();
-       return target ? target->usage : 0;
+       usage = target ? target->usage: 0;
+       CRITICAL_SECTION_END(&s_info.mutex);
+       return usage;
 }
 
 API int heap_monitor_initialized(void)
@@ -706,33 +683,58 @@ API int heap_monitor_initialized(void)
        return s_info.initialized;
 }
 
-API void heap_monitor_set_stack_boundary(unsigned long stack_boundary)
-{
-       s_info.stack_boundary = stack_boundary;
-}
-
 API void heap_monitor_init(void)
 {
        const char *var;
        pthread_attr_t attr;
+       int ret;
 
        if (s_info.initialized) {
                return;
        }
-       
-#if defined(_ENABLE_MCHECK)
-       s_info.m_check = mcheck(mcheck_cb);
-       if (s_info.m_check < 0) {
-               ErrPrint("Failed to install mcheck[%d]\n", s_info.m_check);
-       } else {
-               DbgPrint("mcheck installed: %d\n", s_info.m_check);
+
+       __file_log_fp = fopen("/tmp/heap_log.tmp", "w+");
+
+       if (!s_info.alloc_handle) {
+               s_info.alloc_handle = allocator_init((unsigned int)s_info.stack_memory, sizeof(s_info.stack_memory));
+               if (!s_info.alloc_handle) {
+                       exit(-EFAULT);
+               }
        }
-#endif
 
-       s_info._malloc = __malloc_hook;
-       s_info._realloc = __realloc_hook;
-       s_info._free = __free_hook;
-       s_info._memalign = __memalign_hook;
+       if (!s_info._malloc) {
+               s_info._malloc = dlsym(RTLD_NEXT, "malloc");
+               if (!s_info._malloc) {
+                       ErrPrint("malloc: %s\n", dlerror());
+                       exit(-EINVAL);
+               }
+       }
+       DbgPrint("malloc: %p & %p\n", s_info._malloc, malloc);
+
+       if (!s_info._free) {
+               s_info._free = dlsym(RTLD_NEXT, "free");
+               if (!s_info._free) {
+                       ErrPrint("free: %s\n", dlerror());
+                       exit(-EINVAL);
+               }
+       }
+       DbgPrint("free: %p & %p\n", s_info._free, free);
+
+       s_info._realloc = dlsym(RTLD_NEXT, "realloc");
+       if (!s_info._realloc) {
+               ErrPrint("realloc: %s\n", dlerror());
+               exit(-EINVAL);
+       }
+       DbgPrint("realloc: %p & %p\n", s_info._realloc, realloc);
+
+       s_info._memalign = dlsym(RTLD_NEXT, "memalign");
+       if (!s_info._memalign) {
+               ErrPrint("memalign: %s\n", dlerror());
+               exit(-EINVAL);
+       }
+       DbgPrint("memalign: %p & %p\n", s_info._memalign, memalign);
+
+       s_info.initialized = 1;
 
        var = getenv("HEAP_MONITOR_DUMP_DEPTH");
        if (var) {
@@ -745,39 +747,53 @@ API void heap_monitor_init(void)
        }
 
        s_info.main_tid = pthread_self();
-       s_info.initialized = 1;
 
-       if (pthread_getattr_np(s_info.main_tid, &attr)) {
-               return;
+       ret = pthread_getattr_np(s_info.main_tid, &attr);
+       if (ret != 0) {
+               ErrPrint("destroy: %s\n", strerror(ret));
+               exit(-EINVAL);
        }
 
-       if (pthread_attr_getstack(&attr, (void *)&s_info.stack_base, &s_info.stack_size)) {
+       ret = pthread_attr_getstack(&attr, (void *)&s_info.stack_base, &s_info.stack_size);
+       if (ret) {
                s_info.stack_base = 0;
                s_info.stack_size = 0;
-       } else {
-               s_info.stack_boundary = s_info.stack_base + s_info.stack_size;
        }
 
-       pthread_attr_destroy(&attr);
-       DbgPrint("Initialized\n");
+       ret = pthread_attr_destroy(&attr);
+       if (ret != 0) {
+               ErrPrint("destroy: %s\n", strerror(ret));
+       }
+
+       heap_monitor_add_target("");
+
+       DbgPrint("program text (etext): %p, "
+               "initialized data (edata): %p, "
+               "uninitialized data (end): %p, "
+               "break: %p, stack: %lu, stack_size: %u\n",
+               &etext, &edata, &end, sbrk(0), s_info.stack_base, s_info.stack_size);
+
+       return;
 }
 
-API void heap_monitor_start(void)
+API void heap_monitor_fini(void)
 {
-       if (!s_info.initialized) {
-               return;
+       DbgPrint("Usage: %d\n", heap_monitor_target_usage(""));
+       if (__file_log_fp) {
+               fclose(__file_log_fp);
        }
-
-       hook();
 }
 
-API void heap_monitor_stop(void)
+API __attribute__((destructor)) int destructor(void)
 {
-       if (!s_info.initialized) {
-               return;
-       }
+       heap_monitor_fini();
+       return 0;
+}
 
-       unhook();
+API __attribute__((constructor)) int constructor(void)
+{
+       heap_monitor_init();
+       return 0;
 }
 
 /* End of a file */