diff --git a/test/libmm/Makefile b/test/libmm/Makefile index 484a3787a..9d1307c0b 100644 --- a/test/libmm/Makefile +++ b/test/libmm/Makefile @@ -19,11 +19,9 @@ CFLAGS = -c -g -W \ ########################################################### #Check system: -SYSLIB = CHECKSYSRES = @echo "Unknow system type!";exit 1 UNIXNAME = $(shell uname -sm) -UNIXTYPE = LINUX -polarssl = +shared_ldflags = ifeq ($(CC),) CC = g++ @@ -42,6 +40,17 @@ ifeq ($(findstring clang++, $(CC)), clang++) -Wno-invalid-offsetof endif +# For Linux +ifeq ($(findstring Linux, $(UNIXNAME)), Linux) + shared_ldflags += -lunwind -lunwind-x86_64 -lz -lpthread +endif + +# For Darwin +ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin) + CFLAGS += -D_XOPEN_SOURCE -Wno-deprecated-declarations + shared_ldflags += -lz -lpthread +endif + #Find system type. ifneq ($(SYSPATH),) CHECKSYSRES = @echo "System is $(shell uname -sm)" @@ -53,7 +62,6 @@ LIB_PATH_DST = . DEF_PATH_DST = ./debug CFLAGS += -I. -shared_ldflags = -lunwind -lunwind-x86_64 -lz -lpthread #Project's objs OBJS_DST = $(patsubst %.cpp, $(OBJ_PATH_DST)/%.o, $(notdir $(wildcard ./*.cpp))) diff --git a/test/libmm/libmm.cpp b/test/libmm/libmm.cpp index 461fecea3..65fc56cec 100644 --- a/test/libmm/libmm.cpp +++ b/test/libmm/libmm.cpp @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include "libmm.h" static void stacktrace(void) { @@ -35,8 +37,6 @@ static void stacktrace(void) } } -typedef void *(*malloc_fn)(size_t); -static malloc_fn __malloc_fn = NULL; static size_t total_size = 0; static bool __check = false; static pthread_mutex_t __lock; @@ -45,7 +45,6 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT; static void once_init(void) { - __malloc_fn = (malloc_fn) dlsym(RTLD_NEXT, "malloc"); pthread_mutex_init(&__lock, NULL); } @@ -69,7 +68,7 @@ void *malloc(size_t size) return NULL; } - ptr = __malloc_fn(size); + ptr = mymalloc(size); if (ptr && __check) { if (size == 8208) { //abort(); diff --git a/test/libmm/libmm.h b/test/libmm/libmm.h index da8b0de82..4ea8bcd39 100644 --- a/test/libmm/libmm.h +++ b/test/libmm/libmm.h @@ -5,6 +5,9 @@ extern "C" { #endif +void *mymalloc(size_t size); +void print_mem_list(); + //void start_check(void); //void stop_check(void); diff --git a/test/libmm/memalloc.cpp b/test/libmm/memalloc.cpp new file mode 100644 index 000000000..a4031ebb2 --- /dev/null +++ b/test/libmm/memalloc.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +// Copy from https://github.com/arjun024/memalloc +/* Only for the debug printf */ +#include +#include "libmm.h" + +typedef char ALIGN[16]; + +union header { + struct { + size_t size; + unsigned is_free; + union header *next; + } s; + /* force the header to be aligned to 16 bytes */ + ALIGN stub; +}; +typedef union header header_t; + +header_t *head = NULL, *tail = NULL; +pthread_mutex_t global_malloc_lock; + +static header_t *get_free_block(size_t size) +{ + header_t *curr = head; + while(curr) { + /* see if there's a free block that can accomodate requested size */ + if (curr->s.is_free && curr->s.size >= size) + return curr; + curr = curr->s.next; + } + return NULL; +} + +void free(void *block) +{ + header_t *header, *tmp; + /* program break is the end of the process's data segment */ + void *programbreak; + + if (!block) + return; + pthread_mutex_lock(&global_malloc_lock); + header = (header_t*)block - 1; + /* sbrk(0) gives the current program break address */ + programbreak = sbrk(0); + + /* + Check if the block to be freed is the last one in the + linked list. If it is, then we could shrink the size of the + heap and release memory to OS. Else, we will keep the block + but mark it as free. + */ + if ((char*)block + header->s.size == programbreak) { + if (head == tail) { + head = tail = NULL; + } else { + tmp = head; + while (tmp) { + if(tmp->s.next == tail) { + tmp->s.next = NULL; + tail = tmp; + } + tmp = tmp->s.next; + } + } + /* + sbrk() with a negative argument decrements the program break. + So memory is released by the program to OS. + */ + sbrk(0 - header->s.size - sizeof(header_t)); + /* Note: This lock does not really assure thread + safety, because sbrk() itself is not really + thread safe. Suppose there occurs a foregin sbrk(N) + after we find the program break and before we decrement + it, then we end up realeasing the memory obtained by + the foreign sbrk(). + */ + pthread_mutex_unlock(&global_malloc_lock); + return; + } + header->s.is_free = 1; + pthread_mutex_unlock(&global_malloc_lock); +} + +void *mymalloc(size_t size) +{ + size_t total_size; + void *block; + header_t *header; + if (!size) + return NULL; + pthread_mutex_lock(&global_malloc_lock); + header = get_free_block(size); + if (header) { + /* Woah, found a free block to accomodate requested memory. */ + header->s.is_free = 0; + pthread_mutex_unlock(&global_malloc_lock); + return (void*)(header + 1); + } + /* We need to get memory to fit in the requested block and header from OS. */ + total_size = sizeof(header_t) + size; + block = sbrk(total_size); + if (block == (void*) -1) { + pthread_mutex_unlock(&global_malloc_lock); + return NULL; + } + header = (header_t*) block; + header->s.size = size; + header->s.is_free = 0; + header->s.next = NULL; + if (!head) + head = header; + if (tail) + tail->s.next = header; + tail = header; + pthread_mutex_unlock(&global_malloc_lock); + return (void*)(header + 1); +} + +void *calloc(size_t num, size_t nsize) +{ + size_t size; + void *block; + if (!num || !nsize) + return NULL; + size = num * nsize; + /* check mul overflow */ + if (nsize != size / num) + return NULL; + block = mymalloc(size); + if (!block) + return NULL; + memset(block, 0, size); + return block; +} + +void *realloc(void *block, size_t size) +{ + header_t *header; + void *ret; + if (!block || !size) + return mymalloc(size); + header = (header_t*)block - 1; + if (header->s.size >= size) + return block; + ret = mymalloc(size); + if (ret) { + /* Relocate contents to the new bigger block */ + memcpy(ret, block, header->s.size); + /* Free the old memory block */ + free(block); + } + return ret; +} + +/* A debug function to print the entire link list */ +void print_mem_list() +{ + header_t *curr = head; + printf("head = %p, tail = %p \n", (void*)head, (void*)tail); + while(curr) { + printf("addr = %p, size = %zu, is_free=%u, next=%p\n", + (void*)curr, curr->s.size, curr->s.is_free, (void*)curr->s.next); + curr = curr->s.next; + } +}