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