1af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/* 286562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 3af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 4d4bab99f83dbc53665c5769c3f6b50ffcd2a9a7dbart Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>. 5af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 6af44c8236f7a73e71b16b707bba56f33af4d01cesewardj This program is free software; you can redistribute it and/or 7af44c8236f7a73e71b16b707bba56f33af4d01cesewardj modify it under the terms of the GNU General Public License as 8af44c8236f7a73e71b16b707bba56f33af4d01cesewardj published by the Free Software Foundation; either version 2 of the 9af44c8236f7a73e71b16b707bba56f33af4d01cesewardj License, or (at your option) any later version. 10af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 11af44c8236f7a73e71b16b707bba56f33af4d01cesewardj This program is distributed in the hope that it will be useful, but 12af44c8236f7a73e71b16b707bba56f33af4d01cesewardj WITHOUT ANY WARRANTY; without even the implied warranty of 13af44c8236f7a73e71b16b707bba56f33af4d01cesewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14af44c8236f7a73e71b16b707bba56f33af4d01cesewardj General Public License for more details. 15af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 16af44c8236f7a73e71b16b707bba56f33af4d01cesewardj You should have received a copy of the GNU General Public License 17af44c8236f7a73e71b16b707bba56f33af4d01cesewardj along with this program; if not, write to the Free Software 18af44c8236f7a73e71b16b707bba56f33af4d01cesewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 02111-1307, USA. 20af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 21af44c8236f7a73e71b16b707bba56f33af4d01cesewardj The GNU General Public License is contained in the file COPYING. 22af44c8236f7a73e71b16b707bba56f33af4d01cesewardj*/ 23af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 24af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 25af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_malloc_wrappers.h" 26af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_thread.h" 27af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_basics.h" 28af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_execontext.h" 29af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_hashtable.h" 30af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_libcassert.h" 31af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_libcbase.h" 32af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_libcprint.h" 33af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_mallocfree.h" 34af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_options.h" 35af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_replacemalloc.h" 36af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_threadstate.h" 37af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "pub_tool_tooliface.h" 38af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 39af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 40246fbf2655328fc150e528b701223b7a1eafe471bart/* Local type definitions. */ 41af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 425fd2814722565a7a5042ba9a691024d7095e31dbbart/** 435fd2814722565a7a5042ba9a691024d7095e31dbbart * Node with per-allocation information that will be stored in a hash map. 445fd2814722565a7a5042ba9a691024d7095e31dbbart * As specified in <pub_tool_hashtable.h>, the first member must be a pointer 455fd2814722565a7a5042ba9a691024d7095e31dbbart * and the second member must be an UWord. 465fd2814722565a7a5042ba9a691024d7095e31dbbart */ 47af44c8236f7a73e71b16b707bba56f33af4d01cesewardjtypedef struct _DRD_Chunk { 48bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct _DRD_Chunk* next; 495fd2814722565a7a5042ba9a691024d7095e31dbbart UWord data; // pointer to actual block 505fd2814722565a7a5042ba9a691024d7095e31dbbart SizeT size; // size requested 515fd2814722565a7a5042ba9a691024d7095e31dbbart ExeContext* where; // where it was allocated 52af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} DRD_Chunk; 53af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 54246fbf2655328fc150e528b701223b7a1eafe471bart 55246fbf2655328fc150e528b701223b7a1eafe471bart/* Local variables. */ 56246fbf2655328fc150e528b701223b7a1eafe471bart 57ba0818d7de52833bf2a801d766e565b5f8d4df1bbartstatic StartUsingMem s_start_using_mem_callback; 58ba0818d7de52833bf2a801d766e565b5f8d4df1bbartstatic StopUsingMem s_stop_using_mem_callback; 595fd2814722565a7a5042ba9a691024d7095e31dbbart/* Statistics. */ 60ba0818d7de52833bf2a801d766e565b5f8d4df1bbartstatic SizeT s_cmalloc_n_mallocs = 0; 61ba0818d7de52833bf2a801d766e565b5f8d4df1bbartstatic SizeT s_cmalloc_n_frees = 0; 62ba0818d7de52833bf2a801d766e565b5f8d4df1bbartstatic SizeT s_cmalloc_bs_mallocd = 0; 63246fbf2655328fc150e528b701223b7a1eafe471bart/* Record malloc'd blocks. */ 6409a4c794458cdb9dea743fa40e450150a2725257florianstatic VgHashTable *s_malloc_list = NULL; 65af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 66af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 675fd2814722565a7a5042ba9a691024d7095e31dbbart/* Function definitions. */ 68af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 695fd2814722565a7a5042ba9a691024d7095e31dbbart/** Allocate client memory memory and update the hash map. */ 70ba0818d7de52833bf2a801d766e565b5f8d4df1bbartstatic void* new_block(ThreadId tid, SizeT size, SizeT align, Bool is_zeroed) 71af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 725fd2814722565a7a5042ba9a691024d7095e31dbbart void* p; 73af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 745fd2814722565a7a5042ba9a691024d7095e31dbbart p = VG_(cli_malloc)(align, size); 755fd2814722565a7a5042ba9a691024d7095e31dbbart if (!p) 76bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return NULL; 775fd2814722565a7a5042ba9a691024d7095e31dbbart if (is_zeroed) 785fd2814722565a7a5042ba9a691024d7095e31dbbart VG_(memset)(p, 0, size); 79af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 805fd2814722565a7a5042ba9a691024d7095e31dbbart DRD_(malloclike_block)(tid, (Addr)p, size); 81af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 825fd2814722565a7a5042ba9a691024d7095e31dbbart return p; 83af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 84af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 85ba0818d7de52833bf2a801d766e565b5f8d4df1bbart/** 86ba0818d7de52833bf2a801d766e565b5f8d4df1bbart * Store information about a memory block that has been allocated by 875fd2814722565a7a5042ba9a691024d7095e31dbbart * malloc() or a malloc() replacement in the hash map. 88ba0818d7de52833bf2a801d766e565b5f8d4df1bbart */ 89ba0818d7de52833bf2a801d766e565b5f8d4df1bbartvoid DRD_(malloclike_block)(const ThreadId tid, const Addr p, const SizeT size) 90ba0818d7de52833bf2a801d766e565b5f8d4df1bbart{ 915fd2814722565a7a5042ba9a691024d7095e31dbbart DRD_Chunk* mc; 925fd2814722565a7a5042ba9a691024d7095e31dbbart 93ba0818d7de52833bf2a801d766e565b5f8d4df1bbart tl_assert(p); 94ba0818d7de52833bf2a801d766e565b5f8d4df1bbart 955fd2814722565a7a5042ba9a691024d7095e31dbbart if (size > 0) 965fd2814722565a7a5042ba9a691024d7095e31dbbart s_start_using_mem_callback(p, size, 0/*ec_uniq*/); 97ba0818d7de52833bf2a801d766e565b5f8d4df1bbart 985fd2814722565a7a5042ba9a691024d7095e31dbbart s_cmalloc_n_mallocs++; 99ba0818d7de52833bf2a801d766e565b5f8d4df1bbart // Only update this stat if allocation succeeded. 100ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_cmalloc_bs_mallocd += size; 101ba0818d7de52833bf2a801d766e565b5f8d4df1bbart 1025fd2814722565a7a5042ba9a691024d7095e31dbbart mc = VG_(malloc)("drd.malloc_wrappers.cDC.1", sizeof(DRD_Chunk)); 1035fd2814722565a7a5042ba9a691024d7095e31dbbart mc->data = p; 1045fd2814722565a7a5042ba9a691024d7095e31dbbart mc->size = size; 1055fd2814722565a7a5042ba9a691024d7095e31dbbart mc->where = VG_(record_ExeContext)(tid, 0); 1065fd2814722565a7a5042ba9a691024d7095e31dbbart VG_(HT_add_node)(s_malloc_list, mc); 107af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 108af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 1095fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void handle_free(ThreadId tid, void* p) 110af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 111fc08a534fa0590012aae11715eda8ecbb60d599cbart Bool success; 112af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 113fc08a534fa0590012aae11715eda8ecbb60d599cbart tl_assert(p); 114fc08a534fa0590012aae11715eda8ecbb60d599cbart success = DRD_(freelike_block)(tid, (Addr)p, True); 115fc08a534fa0590012aae11715eda8ecbb60d599cbart tl_assert(success); 116af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 117af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 118ba0818d7de52833bf2a801d766e565b5f8d4df1bbart/** 119ba0818d7de52833bf2a801d766e565b5f8d4df1bbart * Remove the information that was stored by DRD_(malloclike_block)() about 120ba0818d7de52833bf2a801d766e565b5f8d4df1bbart * a memory block. 121ba0818d7de52833bf2a801d766e565b5f8d4df1bbart */ 122fc08a534fa0590012aae11715eda8ecbb60d599cbartBool DRD_(freelike_block)(const ThreadId tid, const Addr p, const Bool dealloc) 123af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 124bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_Chunk* mc; 125bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 126ba0818d7de52833bf2a801d766e565b5f8d4df1bbart tl_assert(p); 127bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 128ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_cmalloc_n_frees++; 129ba0818d7de52833bf2a801d766e565b5f8d4df1bbart 130639d0ada466e6f4f6bb9032800ff9042941edfd8bart mc = VG_(HT_lookup)(s_malloc_list, (UWord)p); 131ba0818d7de52833bf2a801d766e565b5f8d4df1bbart if (mc) 132bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 133bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p == mc->data); 134bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (mc->size > 0) 135ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_stop_using_mem_callback(mc->data, mc->size); 136697bb6b9de0158d7621fc72b486fe8e553512aedbart if (dealloc) 137697bb6b9de0158d7621fc72b486fe8e553512aedbart VG_(cli_free)((void*)p); 138639d0ada466e6f4f6bb9032800ff9042941edfd8bart VG_(HT_remove)(s_malloc_list, (UWord)p); 139bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(free)(mc); 140ba0818d7de52833bf2a801d766e565b5f8d4df1bbart return True; 141bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 142ba0818d7de52833bf2a801d766e565b5f8d4df1bbart return False; 143ba0818d7de52833bf2a801d766e565b5f8d4df1bbart} 144ba0818d7de52833bf2a801d766e565b5f8d4df1bbart 1455fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for malloc(). */ 1465fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void* drd_malloc(ThreadId tid, SizeT n) 147ba0818d7de52833bf2a801d766e565b5f8d4df1bbart{ 1485fd2814722565a7a5042ba9a691024d7095e31dbbart return new_block(tid, n, VG_(clo_alignment), /*is_zeroed*/False); 1495fd2814722565a7a5042ba9a691024d7095e31dbbart} 1505fd2814722565a7a5042ba9a691024d7095e31dbbart 1515fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for memalign(). */ 1525fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void* drd_memalign(ThreadId tid, SizeT align, SizeT n) 1535fd2814722565a7a5042ba9a691024d7095e31dbbart{ 1545fd2814722565a7a5042ba9a691024d7095e31dbbart return new_block(tid, n, align, /*is_zeroed*/False); 155af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 156af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 1575fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for calloc(). */ 1585fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void* drd_calloc(ThreadId tid, SizeT nmemb, SizeT size1) 159af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 1605fd2814722565a7a5042ba9a691024d7095e31dbbart return new_block(tid, nmemb*size1, VG_(clo_alignment), 1615fd2814722565a7a5042ba9a691024d7095e31dbbart /*is_zeroed*/True); 162af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 163af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 1645fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for free(). */ 1655fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void drd_free(ThreadId tid, void* p) 1665fd2814722565a7a5042ba9a691024d7095e31dbbart{ 1675fd2814722565a7a5042ba9a691024d7095e31dbbart handle_free(tid, p); 1685fd2814722565a7a5042ba9a691024d7095e31dbbart} 1695fd2814722565a7a5042ba9a691024d7095e31dbbart 1705fd2814722565a7a5042ba9a691024d7095e31dbbart/** 1715fd2814722565a7a5042ba9a691024d7095e31dbbart * Wrapper for realloc(). Returns a pointer to the new block of memory, or 1725fd2814722565a7a5042ba9a691024d7095e31dbbart * NULL if no new block could not be allocated. Notes: 1735fd2814722565a7a5042ba9a691024d7095e31dbbart * - realloc(NULL, size) has the same effect as malloc(size). 1745fd2814722565a7a5042ba9a691024d7095e31dbbart * - realloc(p, 0) has the same effect as free(p). 1755fd2814722565a7a5042ba9a691024d7095e31dbbart * - success is not guaranteed even if the requested size is smaller than the 1765fd2814722565a7a5042ba9a691024d7095e31dbbart * allocated size. 1775fd2814722565a7a5042ba9a691024d7095e31dbbart*/ 1785fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void* drd_realloc(ThreadId tid, void* p_old, SizeT new_size) 179af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 180bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_Chunk* mc; 1815fd2814722565a7a5042ba9a691024d7095e31dbbart void* p_new; 1825fd2814722565a7a5042ba9a691024d7095e31dbbart SizeT old_size; 1835fd2814722565a7a5042ba9a691024d7095e31dbbart 1845fd2814722565a7a5042ba9a691024d7095e31dbbart if (! p_old) 1855fd2814722565a7a5042ba9a691024d7095e31dbbart return drd_malloc(tid, new_size); 1865fd2814722565a7a5042ba9a691024d7095e31dbbart 1875fd2814722565a7a5042ba9a691024d7095e31dbbart if (new_size == 0) 1885fd2814722565a7a5042ba9a691024d7095e31dbbart { 1895fd2814722565a7a5042ba9a691024d7095e31dbbart drd_free(tid, p_old); 1905fd2814722565a7a5042ba9a691024d7095e31dbbart return NULL; 1915fd2814722565a7a5042ba9a691024d7095e31dbbart } 192bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 1935fd2814722565a7a5042ba9a691024d7095e31dbbart s_cmalloc_n_mallocs++; 1945fd2814722565a7a5042ba9a691024d7095e31dbbart s_cmalloc_n_frees++; 195ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_cmalloc_bs_mallocd += new_size; 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 1975fd2814722565a7a5042ba9a691024d7095e31dbbart mc = VG_(HT_lookup)(s_malloc_list, (UWord)p_old); 1985fd2814722565a7a5042ba9a691024d7095e31dbbart if (mc == NULL) 1995fd2814722565a7a5042ba9a691024d7095e31dbbart { 200bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(0); 201bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return NULL; 202bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 203bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 204bedfd237fbdc80d0c917cfcb85a94b5561c92633bart old_size = mc->size; 205bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 206bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (old_size == new_size) 207bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 208bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* size unchanged */ 209bedfd237fbdc80d0c917cfcb85a94b5561c92633bart mc->where = VG_(record_ExeContext)(tid, 0); 210bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p_new = p_old; 211bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 2125fd2814722565a7a5042ba9a691024d7095e31dbbart else if (new_size < old_size) 213bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 2145fd2814722565a7a5042ba9a691024d7095e31dbbart /* new size is smaller but nonzero */ 2155b61bdafc1dd18079783b5db29d89b3925c797edbart s_stop_using_mem_callback(mc->data + new_size, old_size - new_size); 216bedfd237fbdc80d0c917cfcb85a94b5561c92633bart mc->size = new_size; 217bedfd237fbdc80d0c917cfcb85a94b5561c92633bart mc->where = VG_(record_ExeContext)(tid, 0); 218bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p_new = p_old; 219bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 220bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 221bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 222bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* new size is bigger */ 2235fd2814722565a7a5042ba9a691024d7095e31dbbart p_new = VG_(cli_malloc)(VG_(clo_alignment), new_size); 224bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 2255fd2814722565a7a5042ba9a691024d7095e31dbbart if (p_new) 226bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 2275fd2814722565a7a5042ba9a691024d7095e31dbbart /* Copy from old to new. */ 2285fd2814722565a7a5042ba9a691024d7095e31dbbart VG_(memcpy)(p_new, p_old, mc->size); 22931b983d29affe6c30a2283be8824c6d75c74d848bart 2305fd2814722565a7a5042ba9a691024d7095e31dbbart /* Free old memory. */ 23183e7eb6cd7c93cd9f43d07bcc9cd80a722d8fb85bart if (mc->size > 0) 23283e7eb6cd7c93cd9f43d07bcc9cd80a722d8fb85bart s_stop_using_mem_callback(mc->data, mc->size); 233e49a5881613565fe8c53b90013cd50d8b4e9821fbart VG_(cli_free)(p_old); 2345fd2814722565a7a5042ba9a691024d7095e31dbbart VG_(HT_remove)(s_malloc_list, (UWord)p_old); 2355fd2814722565a7a5042ba9a691024d7095e31dbbart 2365fd2814722565a7a5042ba9a691024d7095e31dbbart /* Update state information. */ 2375fd2814722565a7a5042ba9a691024d7095e31dbbart mc->data = (Addr)p_new; 2385fd2814722565a7a5042ba9a691024d7095e31dbbart mc->size = new_size; 2395fd2814722565a7a5042ba9a691024d7095e31dbbart mc->where = VG_(record_ExeContext)(tid, 0); 2405fd2814722565a7a5042ba9a691024d7095e31dbbart VG_(HT_add_node)(s_malloc_list, mc); 2415fd2814722565a7a5042ba9a691024d7095e31dbbart s_start_using_mem_callback((Addr)p_new, new_size, 0/*ec_uniq*/); 242bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 245bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Allocation failed -- leave original block untouched. */ 246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 24731b983d29affe6c30a2283be8824c6d75c74d848bart } 248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p_new; 250af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 251af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2525fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for __builtin_new(). */ 2535fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void* drd___builtin_new(ThreadId tid, SizeT n) 254af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 2555fd2814722565a7a5042ba9a691024d7095e31dbbart return new_block(tid, n, VG_(clo_alignment), /*is_zeroed*/False); 256af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 257af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2585fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for __builtin_delete(). */ 2595fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void drd___builtin_delete(ThreadId tid, void* p) 260af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 2615fd2814722565a7a5042ba9a691024d7095e31dbbart handle_free(tid, p); 262af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 263af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2645fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for __builtin_vec_new(). */ 2655fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void* drd___builtin_vec_new(ThreadId tid, SizeT n) 266af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 267ba0818d7de52833bf2a801d766e565b5f8d4df1bbart return new_block(tid, n, VG_(clo_alignment), /*is_zeroed*/False); 268af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 269af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2705fd2814722565a7a5042ba9a691024d7095e31dbbart/** Wrapper for __builtin_vec_delete(). */ 2715fd2814722565a7a5042ba9a691024d7095e31dbbartstatic void drd___builtin_vec_delete(ThreadId tid, void* p) 272af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 2735fd2814722565a7a5042ba9a691024d7095e31dbbart handle_free(tid, p); 274af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 275af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2765fd2814722565a7a5042ba9a691024d7095e31dbbart/** 2775fd2814722565a7a5042ba9a691024d7095e31dbbart * Wrapper for malloc_usable_size() / malloc_size(). This function takes 2785fd2814722565a7a5042ba9a691024d7095e31dbbart * a pointer to a block allocated by `malloc' and returns the amount of space 2795fd2814722565a7a5042ba9a691024d7095e31dbbart * that is available in the block. This may or may not be more than the size 2805fd2814722565a7a5042ba9a691024d7095e31dbbart * requested from `malloc', due to alignment or minimum size constraints. 2815fd2814722565a7a5042ba9a691024d7095e31dbbart */ 2825fd2814722565a7a5042ba9a691024d7095e31dbbartstatic SizeT drd_malloc_usable_size(ThreadId tid, void* p) 2838b140dee891a850c09d27f316df913acc7d7bae7njn{ 2845fd2814722565a7a5042ba9a691024d7095e31dbbart DRD_Chunk* mc; 2855fd2814722565a7a5042ba9a691024d7095e31dbbart 2865fd2814722565a7a5042ba9a691024d7095e31dbbart mc = VG_(HT_lookup)(s_malloc_list, (UWord)p); 2878b140dee891a850c09d27f316df913acc7d7bae7njn 2885fd2814722565a7a5042ba9a691024d7095e31dbbart return mc ? mc->size : 0; 2898b140dee891a850c09d27f316df913acc7d7bae7njn} 2908b140dee891a850c09d27f316df913acc7d7bae7njn 291246fbf2655328fc150e528b701223b7a1eafe471bartvoid DRD_(register_malloc_wrappers)(const StartUsingMem start_callback, 292246fbf2655328fc150e528b701223b7a1eafe471bart const StopUsingMem stop_callback) 293af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 294ba0818d7de52833bf2a801d766e565b5f8d4df1bbart tl_assert(s_malloc_list == 0); 2955fd2814722565a7a5042ba9a691024d7095e31dbbart s_malloc_list = VG_(HT_construct)("drd_malloc_list"); 296bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(start_callback); 297bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(stop_callback); 298bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 299ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_start_using_mem_callback = start_callback; 300ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_stop_using_mem_callback = stop_callback; 301bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 3025fd2814722565a7a5042ba9a691024d7095e31dbbart VG_(needs_malloc_replacement)(drd_malloc, 3035fd2814722565a7a5042ba9a691024d7095e31dbbart drd___builtin_new, 3045fd2814722565a7a5042ba9a691024d7095e31dbbart drd___builtin_vec_new, 3055fd2814722565a7a5042ba9a691024d7095e31dbbart drd_memalign, 3065fd2814722565a7a5042ba9a691024d7095e31dbbart drd_calloc, 3075fd2814722565a7a5042ba9a691024d7095e31dbbart drd_free, 3085fd2814722565a7a5042ba9a691024d7095e31dbbart drd___builtin_delete, 3095fd2814722565a7a5042ba9a691024d7095e31dbbart drd___builtin_vec_delete, 3105fd2814722565a7a5042ba9a691024d7095e31dbbart drd_realloc, 3115fd2814722565a7a5042ba9a691024d7095e31dbbart drd_malloc_usable_size, 312bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 0); 313af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 314af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 315246fbf2655328fc150e528b701223b7a1eafe471bartBool DRD_(heap_addrinfo)(Addr const a, 316246fbf2655328fc150e528b701223b7a1eafe471bart Addr* const data, 317246fbf2655328fc150e528b701223b7a1eafe471bart SizeT* const size, 318246fbf2655328fc150e528b701223b7a1eafe471bart ExeContext** const where) 319af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 320bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_Chunk* mc; 321bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 322bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(data); 323bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(size); 324bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(where); 325bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 326ba0818d7de52833bf2a801d766e565b5f8d4df1bbart VG_(HT_ResetIter)(s_malloc_list); 327ba0818d7de52833bf2a801d766e565b5f8d4df1bbart while ((mc = VG_(HT_Next)(s_malloc_list))) 328bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (mc->data <= a && a < mc->data + mc->size) 330bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 331bedfd237fbdc80d0c917cfcb85a94b5561c92633bart *data = mc->data; 332bedfd237fbdc80d0c917cfcb85a94b5561c92633bart *size = mc->size; 333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart *where = mc->where; 334bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return True; 335bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 336bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 337bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return False; 338af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 339af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 340af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*------------------------------------------------------------*/ 341af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*--- Statistics printing ---*/ 342af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*------------------------------------------------------------*/ 343af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 344246fbf2655328fc150e528b701223b7a1eafe471bartvoid DRD_(print_malloc_stats)(void) 345af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 346bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_Chunk* mc; 347bedfd237fbdc80d0c917cfcb85a94b5561c92633bart SizeT nblocks = 0; 348bedfd237fbdc80d0c917cfcb85a94b5561c92633bart SizeT nbytes = 0; 34931b983d29affe6c30a2283be8824c6d75c74d848bart 350bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (VG_(clo_verbosity) == 0) 351bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (VG_(clo_xml)) 353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 355bedfd237fbdc80d0c917cfcb85a94b5561c92633bart /* Count memory still in use. */ 356ba0818d7de52833bf2a801d766e565b5f8d4df1bbart VG_(HT_ResetIter)(s_malloc_list); 357ba0818d7de52833bf2a801d766e565b5f8d4df1bbart while ((mc = VG_(HT_Next)(s_malloc_list))) 358bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 359bedfd237fbdc80d0c917cfcb85a94b5561c92633bart nblocks++; 360bedfd237fbdc80d0c917cfcb85a94b5561c92633bart nbytes += mc->size; 361bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 362bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 36331b983d29affe6c30a2283be8824c6d75c74d848bart VG_(message)(Vg_DebugMsg, 3641e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj "malloc/free: in use at exit: %lu bytes in %lu blocks.\n", 365bedfd237fbdc80d0c917cfcb85a94b5561c92633bart nbytes, nblocks); 36631b983d29affe6c30a2283be8824c6d75c74d848bart VG_(message)(Vg_DebugMsg, 3671e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj "malloc/free: %lu allocs, %lu frees, %lu bytes allocated.\n", 368ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_cmalloc_n_mallocs, 369ba0818d7de52833bf2a801d766e565b5f8d4df1bbart s_cmalloc_n_frees, s_cmalloc_bs_mallocd); 370bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (VG_(clo_verbosity) > 1) 3711e29ebcf5a0d5d29434d112bda3a584b4a3f8066sewardj VG_(message)(Vg_DebugMsg, " \n"); 372af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 373af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 374af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*--------------------------------------------------------------------*/ 375af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*--- end ---*/ 376af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/*--------------------------------------------------------------------*/ 377