1c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* 2c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** 3c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** Copyright (C) 2008-2011, The Android Open Source Project 4c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** 5c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** Licensed under the Apache License, Version 2.0 (the "License"); 6c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** you may not use this file except in compliance with the License. 7c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** You may obtain a copy of the License at 8c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** 9c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** http://www.apache.org/licenses/LICENSE-2.0 10c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** 11c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** Unless required by applicable law or agreed to in writing, software 12c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** distributed under the License is distributed on an "AS IS" BASIS, 13c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** See the License for the specific language governing permissions and 15c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev** limitations under the License. 16c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev*/ 17c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 18c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <android/log.h> 19c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <pthread.h> 20c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <time.h> 21c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include <stdarg.h> 22c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 23c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "mapinfo.h" 24c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 25c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevextern int heaptracker_stacktrace(intptr_t*, size_t); 26c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevextern void *__real_malloc(size_t size); 27c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevextern void *__real_realloc(void *ptr, size_t size); 28c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevextern void *__real_calloc(int nmemb, int size); 29c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevextern void __real_free(void *ptr); 30c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 31c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic mapinfo *milist; 32c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 33c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define MAX_BACKTRACE_DEPTH 15 34c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define ALLOCATION_TAG 0x1ee7d00d 35c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define BACKLOG_TAG 0xbabecafe 36c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define FREE_POISON 0xa5 37c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define BACKLOG_MAX 50 38c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define FRONT_GUARD 0xaa 39c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define FRONT_GUARD_LEN (1<<4) 40c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define REAR_GUARD 0xbb 41c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define REAR_GUARD_LEN (1<<4) 42c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define SCANNER_SLEEP_S 3 43c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 44c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstruct hdr { 45c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev uint32_t tag; 46c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *prev; 47c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *next; 48c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev intptr_t bt[MAX_BACKTRACE_DEPTH]; 49c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int bt_depth; 50c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev intptr_t freed_bt[MAX_BACKTRACE_DEPTH]; 51c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int freed_bt_depth; 52c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t size; 53c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev char front_guard[FRONT_GUARD_LEN]; 54c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} __attribute__((packed)); 55c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 56c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstruct ftr { 57c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev char rear_guard[REAR_GUARD_LEN]; 58c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} __attribute__((packed)); 59c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 60c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline struct ftr * to_ftr(struct hdr *hdr) 61c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 62c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return (struct ftr *)(((char *)(hdr + 1)) + hdr->size); 63c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 64c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 65c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void *user(struct hdr *hdr) 66c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 67c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return hdr + 1; 68c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 69c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 70c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline struct hdr *meta(void *user) 71c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 72c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return ((struct hdr *)user) - 1; 73c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 74c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 75c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevextern int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap); 76c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void default_log(const char *fmt, ...) 77c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 78c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev va_list lst; 79c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev va_start(lst, fmt); 80c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __android_log_vprint(ANDROID_LOG_ERROR, "DEBUG", fmt, lst); 81c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev va_end(lst); 82c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 83c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 84c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* Override this for non-printf reporting */ 85c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid (*malloc_log)(const char *fmt, ...) = default_log; 86c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* Call this ad dlclose() to get leaked memory */ 87c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid free_leaked_memory(void); 88c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 89c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic unsigned num; 90c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic struct hdr *first; 91c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic struct hdr *last; 92c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER; 93c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 94c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic unsigned backlog_num; 95c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic struct hdr *backlog_first; 96c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic struct hdr *backlog_last; 97c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic pthread_rwlock_t backlog_lock = PTHREAD_RWLOCK_INITIALIZER; 98c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 99c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchevvoid print_backtrace(const intptr_t *bt, int depth) 100c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 101c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mapinfo *mi; 102c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int cnt, rel_pc; 103c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev intptr_t self_bt[MAX_BACKTRACE_DEPTH]; 104c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev 105c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev if (!bt) { 106c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev depth = heaptracker_stacktrace(self_bt, MAX_BACKTRACE_DEPTH); 107c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev bt = self_bt; 108c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev } 109c169ecd6aea1ed7b8a786f130aee7d980a4b9701Iliyan Malchev 110c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); 111c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev for (cnt = 0; cnt < depth && cnt < MAX_BACKTRACE_DEPTH; cnt++) { 112c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mi = pc_to_mapinfo(milist, bt[cnt], &rel_pc); 113c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("\t#%02d pc %08x %s\n", cnt, 114c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mi ? rel_pc : bt[cnt], 115c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev mi ? mi->name : "(unknown)"); 116c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 117c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 118c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 119c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void init_front_guard(struct hdr *hdr) 120c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 121c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN); 122c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 123c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 124c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int is_front_guard_valid(struct hdr *hdr) 125c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 126c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev unsigned i; 127c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev for (i = 0; i < FRONT_GUARD_LEN; i++) 128c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->front_guard[i] != FRONT_GUARD) 129c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 130c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 1; 131c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 132c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 133c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void init_rear_guard(struct hdr *hdr) 134c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 135c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct ftr *ftr = to_ftr(hdr); 136c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev memset(ftr->rear_guard, REAR_GUARD, REAR_GUARD_LEN); 137c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 138c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 139c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int is_rear_guard_valid(struct hdr *hdr) 140c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 141c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev unsigned i; 142c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int valid = 1; 143c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int first_mismatch = -1; 144c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct ftr *ftr = to_ftr(hdr); 145c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev for (i = 0; i < REAR_GUARD_LEN; i++) { 146c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (ftr->rear_guard[i] != REAR_GUARD) { 147c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (first_mismatch < 0) 148c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev first_mismatch = i; 149c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev valid = 0; 150c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 151c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else if (first_mismatch >= 0) { 152c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ REAR GUARD MISMATCH [%d, %d)\n", first_mismatch, i); 153c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev first_mismatch = -1; 154c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 155c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 156c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 157c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (first_mismatch >= 0) 158c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ REAR GUARD MISMATCH [%d, %d)\n", first_mismatch, i); 159c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return valid; 160c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 161c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 162c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void __add(struct hdr *hdr, struct hdr **first, struct hdr **last) 163c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 164c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->prev = 0; 165c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->next = *last; 166c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (*last) 167c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev (*last)->prev = hdr; 168c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 169c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *first = hdr; 170c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *last = hdr; 171c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 172c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 173c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int __del(struct hdr *hdr, struct hdr **first, struct hdr **last) 174c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 175c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->prev) 176c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->prev->next = hdr->next; 177c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 178c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *last = hdr->next; 179c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->next) 180c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->next->prev = hdr->prev; 181c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 182c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *first = hdr->prev; 183c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 184c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 185c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 186c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void add(struct hdr *hdr, size_t size) 187c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 188c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_wrlock(&lock); 189c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->tag = ALLOCATION_TAG; 190c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->size = size; 191c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev init_front_guard(hdr); 192c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev init_rear_guard(hdr); 193c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev num++; 194c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __add(hdr, &first, &last); 195c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_unlock(&lock); 196c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 197c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 198c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int del(struct hdr *hdr) 199c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 200c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->tag != ALLOCATION_TAG) 201c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return -1; 202c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 203c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_wrlock(&lock); 204c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __del(hdr, &first, &last); 205c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev num--; 206c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_unlock(&lock); 207c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 208c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 209c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void poison(struct hdr *hdr) 211c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 212c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev memset(user(hdr), FREE_POISON, hdr->size); 213c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 214c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 215c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int was_used_after_free(struct hdr *hdr) 216c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 217c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev unsigned i; 218c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev const char *data = (const char *)user(hdr); 219c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev for (i = 0; i < hdr->size; i++) 220c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (data[i] != FREE_POISON) 221c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 1; 222c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 223c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 224c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 225c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* returns 1 if valid, *safe == 1 if safe to dump stack */ 226c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int check_guards(struct hdr *hdr, int *safe) 227c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 228c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *safe = 1; 229c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!is_front_guard_valid(hdr)) { 230c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->front_guard[0] == FRONT_GUARD) { 231c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d HAS A CORRUPTED FRONT GUARD\n", 232c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 233c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } else { 234c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p HAS A CORRUPTED FRONT GUARD "\ 235c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev "(NOT DUMPING STACKTRACE)\n", user(hdr)); 236c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* Allocation header is probably corrupt, do not print stack trace */ 237c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *safe = 0; 238c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 239c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 240c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 241c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 242c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!is_rear_guard_valid(hdr)) { 243c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d HAS A CORRUPTED REAR GUARD\n", 244c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 245c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 246c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 247c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 248c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 1; 249c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 250c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 251c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* returns 1 if valid, *safe == 1 if safe to dump stack */ 252c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int __check_allocation(struct hdr *hdr, int *safe) 253c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 254c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int valid = 1; 255c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *safe = 1; 256c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 257c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->tag != ALLOCATION_TAG && hdr->tag != BACKLOG_TAG) { 258c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p HAS INVALID TAG %08x (NOT DUMPING STACKTRACE)\n", 259c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->tag); 260c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* Allocation header is probably corrupt, do not dequeue or dump stack 261c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * trace. 262c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev */ 263c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *safe = 0; 264c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return 0; 265c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 266c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 267c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->tag == BACKLOG_TAG && was_used_after_free(hdr)) { 268c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d WAS USED AFTER BEING FREED\n", 269c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 270c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev valid = 0; 271c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* check the guards to see if it's safe to dump a stack trace */ 272c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev (void)check_guards(hdr, safe); 273c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 274c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else 275c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev valid = check_guards(hdr, safe); 276c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 277c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!valid && *safe) { 278c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n", 279c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 280c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(hdr->bt, hdr->bt_depth); 281c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->tag == BACKLOG_TAG) { 282c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d FREED HERE:\n", 283c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 284c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(hdr->freed_bt, hdr->freed_bt_depth); 285c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 286c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 287c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 288c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return valid; 289c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 290c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 291c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int __del_and_check(struct hdr *hdr, 292c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr **first, struct hdr **last, unsigned *cnt, 293c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int *safe) 294c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 295c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int valid; 296c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev valid = __check_allocation(hdr, safe); 297c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (safe) { 298c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev (*cnt)--; 299c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __del(hdr, first, last); 300c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 301c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return valid; 302c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 303c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 304c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void __del_from_backlog(struct hdr *hdr) 305c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 306c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int safe; 307c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev (void)__del_and_check(hdr, 308c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &backlog_first, &backlog_last, &backlog_num, 309c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &safe); 310c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->tag = 0; /* clear the tag */ 311c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 312c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 313c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void del_from_backlog(struct hdr *hdr) 314c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 315c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_wrlock(&backlog_lock); 316c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __del_from_backlog(hdr); 317c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_unlock(&backlog_lock); 318c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 319c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 320c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline int del_leak(struct hdr *hdr, int *safe) 321c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 322c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int valid; 323c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_wrlock(&lock); 324c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev valid = __del_and_check(hdr, 325c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev &first, &last, &num, 326c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev safe); 327c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_unlock(&lock); 328c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return valid; 329c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 330c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 331c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic inline void add_to_backlog(struct hdr *hdr) 332c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 333c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_wrlock(&backlog_lock); 334c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->tag = BACKLOG_TAG; 335c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev backlog_num++; 336c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __add(hdr, &backlog_first, &backlog_last); 337c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev poison(hdr); 338c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* If we've exceeded the maximum backlog, clear it up */ 339c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev while (backlog_num > BACKLOG_MAX) { 340c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *gone = backlog_first; 341c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __del_from_backlog(gone); 342c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __real_free(gone); 343c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 344c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_unlock(&backlog_lock); 345c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 346c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 347c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid* __wrap_malloc(size_t size) 348c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 349c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_tracker_log("%s: %s\n", __FILE__, __FUNCTION__); 350c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *hdr = __real_malloc(sizeof(struct hdr) + size + 351c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev sizeof(struct ftr)); 352c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr) { 353c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->bt_depth = heaptracker_stacktrace( 354c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->bt, MAX_BACKTRACE_DEPTH); 355c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev add(hdr, size); 35648fbdeb14d1a916f7e769b4d7f76e714e6df8c5dIliyan Malchev return user(hdr); 357c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 358c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NULL; 359c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 360c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 361c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid __wrap_free(void *ptr) 362c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 363c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *hdr; 364c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!ptr) /* ignore free(NULL) */ 365c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return; 366c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 367c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr = meta(ptr); 368c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 369c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (del(hdr) < 0) { 370c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev intptr_t bt[MAX_BACKTRACE_DEPTH]; 371c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int depth; 372c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev depth = heaptracker_stacktrace(bt, MAX_BACKTRACE_DEPTH); 373c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->tag == BACKLOG_TAG) { 374c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d BYTES MULTIPLY FREED!\n", 375c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 376c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n", 377c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 378c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(hdr->bt, hdr->bt_depth); 379c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* hdr->freed_bt_depth should be nonzero here */ 380c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n", 381c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 382c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(hdr->freed_bt, hdr->freed_bt_depth); 383c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d NOW BEING FREED HERE:\n", 384c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 385c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(bt, depth); 386c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 387c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else { 388c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n", 389c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr)); 390c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(bt, depth); 391c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* Leak here so that we do not crash */ 392c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev //__real_free(user(hdr)); 393c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 394c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 395c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else { 396c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->freed_bt_depth = heaptracker_stacktrace(hdr->freed_bt, 397c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev MAX_BACKTRACE_DEPTH); 398c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev add_to_backlog(hdr); 399c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 400c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 401c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 402c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid *__wrap_realloc(void *ptr, size_t size) 403c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 404c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *hdr; 405c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 406c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!size) { 407c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __wrap_free(ptr); 408c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NULL; 409c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 410c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 411c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!ptr) 412c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return __wrap_malloc(size); 413c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 414c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr = meta(ptr); 415c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 416c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("%s: %s\n", __FILE__, __FUNCTION__); 417c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (del(hdr) < 0) { 418c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev intptr_t bt[MAX_BACKTRACE_DEPTH]; 419c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int depth; 420c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev depth = heaptracker_stacktrace(bt, MAX_BACKTRACE_DEPTH); 421c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr->tag == BACKLOG_TAG) { 422c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ REALLOCATION %p SIZE %d OF FREED MEMORY!\n", 423c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), size, hdr->size); 424c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n", 425c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 426c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(hdr->bt, hdr->bt_depth); 427c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* hdr->freed_bt_depth should be nonzero here */ 428c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n", 429c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 430c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(hdr->freed_bt, hdr->freed_bt_depth); 431c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d NOW BEING REALLOCATED HERE:\n", 432c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), hdr->size); 433c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(bt, depth); 434c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 435c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* We take the memory out of the backlog and fall through so the 436c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * reallocation below succeeds. Since we didn't really free it, we 437c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * can default to this behavior. 438c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev */ 439c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev del_from_backlog(hdr); 440c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 441c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev else { 442c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ REALLOCATION %p SIZE %d IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n", 443c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(hdr), size); 444c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(bt, depth); 445c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev // just get a whole new allocation and leak the old one 446c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return __real_realloc(0, size); 447c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev // return __real_realloc(user(hdr), size); // assuming it was allocated externally 448c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 449c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 450c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 45148fbdeb14d1a916f7e769b4d7f76e714e6df8c5dIliyan Malchev hdr = __real_realloc(hdr, sizeof(struct hdr) + size + sizeof(struct ftr)); 452c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr) { 453c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->bt_depth = heaptracker_stacktrace(hdr->bt, MAX_BACKTRACE_DEPTH); 454c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev add(hdr, size); 455c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return user(hdr); 456c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 457c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 458c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NULL; 459c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 460c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 461c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid *__wrap_calloc(int nmemb, size_t size) 462c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 463c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_tracker_log("%s: %s\n", __FILE__, __FUNCTION__); 464c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *hdr; 465c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev size_t __size = nmemb * size; 46648fbdeb14d1a916f7e769b4d7f76e714e6df8c5dIliyan Malchev hdr = __real_calloc(1, sizeof(struct hdr) + __size + sizeof(struct ftr)); 467c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (hdr) { 468c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->bt_depth = heaptracker_stacktrace( 469c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr->bt, MAX_BACKTRACE_DEPTH); 470c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev add(hdr, __size); 471c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return user(hdr); 472c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 473c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NULL; 474c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 475c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 476c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevvoid heaptracker_free_leaked_memory(void) 477c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 478c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *del; int cnt; 479c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 480c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (num) 481c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ THERE ARE %d LEAKED ALLOCATIONS\n", num); 482c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 483c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev while (last) { 484c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int safe; 485c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev del = last; 486c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ DELETING %d BYTES OF LEAKED MEMORY AT %p (%d REMAINING)\n", 487c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev del->size, user(del), num); 488c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (del_leak(del, &safe)) { 489c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev /* safe == 1, because the allocation is valid */ 490c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n", 491c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev user(del), del->size); 492c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev print_backtrace(del->bt, del->bt_depth); 493c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 494c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __real_free(del); 495c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 496c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 497c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("+++ DELETING %d BACKLOGGED ALLOCATIONS\n", backlog_num); 498c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev while (backlog_last) { 499c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev del = backlog_first; 500c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev del_from_backlog(del); 501c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev __real_free(del); 502c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 503c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 504c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 505c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int check_list(struct hdr *list, pthread_rwlock_t *rwlock) 506c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 507c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct hdr *hdr; 508c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int safe, num_checked; 509c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 510c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_rdlock(rwlock); 511c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev num_checked = 0; 512c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr = list; 513c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev while (hdr) { 514c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev (void)__check_allocation(hdr, &safe); 515c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev hdr = hdr->next; 516c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev num_checked++; 517c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 518c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_rwlock_unlock(rwlock); 519c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 520c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return num_checked; 521c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 522c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 523c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic pthread_t scanner_thread; 524c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic pthread_cond_t scanner_cond = PTHREAD_COND_INITIALIZER; 525c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic int scanner_stop; 526c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic pthread_mutex_t scanner_lock = PTHREAD_MUTEX_INITIALIZER; 527c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 528c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void* scanner(void *data __attribute__((unused))) 529c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 530c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev struct timespec ts; 531c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev int num_checked, num_checked_backlog; 532c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 533c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev while (1) { 534c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev num_checked = check_list(last, &lock); 535c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev num_checked_backlog = check_list(backlog_last, &backlog_lock); 536c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 537c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("@@@ scanned %d/%d allocs and %d/%d freed\n", 538c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// num_checked, num, 539c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// num_checked_backlog, backlog_num); 540c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 541c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_mutex_lock(&scanner_lock); 542c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (!scanner_stop) { 543c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev clock_gettime(CLOCK_REALTIME, &ts); 544c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev ts.tv_sec += SCANNER_SLEEP_S; 545c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_cond_timedwait(&scanner_cond, &scanner_lock, &ts); 546c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 547c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev if (scanner_stop) { 548c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_mutex_unlock(&scanner_lock); 549c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev break; 550c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 551c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_mutex_unlock(&scanner_lock); 552c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev } 553c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 554c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("@@@ scanner thread exiting"); 555c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev return NULL; 556c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 557c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 558c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void init(void) __attribute__((constructor)); 559c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void init(void) 560c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 561c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("@@@ start scanner thread"); 562c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev milist = init_mapinfo(getpid()); 563c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_create(&scanner_thread, 564c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev NULL, 565c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev scanner, 566c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev NULL); 567c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 568c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 569c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void deinit(void) __attribute__((destructor)); 570c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatic void deinit(void) 571c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{ 572c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("@@@ signal stop to scanner thread"); 573c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_mutex_lock(&scanner_lock); 574c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev scanner_stop = 1; 575c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_cond_signal(&scanner_cond); 576c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_mutex_unlock(&scanner_lock); 577c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("@@@ wait for scanner thread to exit"); 578c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev pthread_join(scanner_thread, NULL); 579c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev// malloc_log("@@@ scanner thread stopped"); 580c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 581c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev heaptracker_free_leaked_memory(); 582c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev deinit_mapinfo(milist); 583c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev} 584