tizen 2.3 release
[framework/system/swap-probe.git] / probe_memory / libdamemalloc.c
1 /*
2  *  DA probe
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Anastasia Lyupa <a.lyupa@samsung.com>
12  * Dmitry Bogatov <d.bogatov@samsung.com>
13  *
14  * This library is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License as published by the
16  * Free Software Foundation; either version 2.1 of the License, or (at your option)
17  * any later version.
18  *
19  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
20  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
22  * License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with this library; if not, write to the Free Software Foundation, Inc., 51
26  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  *
28  * Contributors:
29  * - S-Core Co., Ltd
30  * - Samsung RnD Institute Russia
31  *
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <dlfcn.h>
38 #include <stdbool.h>
39 #include <memory.h>
40 #include <errno.h>
41 #include <malloc.h>
42 #include "daprobe.h"
43 #include "probeinfo.h"
44 #include "dacollection.h"
45 #include "dautil.h"
46 #include "da_memory.h"
47 #include "binproto.h"
48
49 static enum DaOptions _sopt = OPT_ALLOC;
50
51 void *malloc(size_t size)
52 {
53         static void* (*mallocp)(size_t);
54         DECLARE_VARIABLE_STANDARD;
55         void *pret;
56
57         rtdl_next_current_set_once(mallocp);
58
59         PRE_PROBEBLOCK();
60
61         pret = (*mallocp)(size);
62
63         if(pret != NULL && gProbeBlockCount == 0)
64                 add_memory_hash(pret, size, MEMTYPE_ALLOC,
65                                 blockresult ? MEM_EXTERNAL : MEM_INTERNAL);
66
67
68         POST_PACK_PROBEBLOCK_BEGIN();
69
70         PREPARE_LOCAL_BUF();
71         PACK_COMMON_BEGIN(MSG_PROBE_MEMORY, API_ID_malloc,
72                           "x", (int64_t) size);
73         PACK_COMMON_END('p', pret, newerrno, blockresult);
74         PACK_MEMORY(size, MEMORY_API_ALLOC, pret);
75         FLUSH_LOCAL_BUF();
76
77         POST_PACK_PROBEBLOCK_END();
78
79         return pret;
80 }
81
82 void free(void *ptr)
83 {
84         static void (*freep)(void *);
85         DECLARE_VARIABLE_STANDARD;
86
87         rtdl_next_current_set_once(freep);
88
89         PRE_PROBEBLOCK();
90
91         if(ptr != NULL && gProbeBlockCount == 0)
92                 del_memory_hash(ptr, MEMTYPE_FREE, NULL);
93
94         (*freep)(ptr);
95
96         POST_PACK_PROBEBLOCK_BEGIN();
97
98         PREPARE_LOCAL_BUF();
99         PACK_COMMON_BEGIN(MSG_PROBE_MEMORY, API_ID_free, 
100                           "p", (int64_t)(int) ptr);
101         PACK_COMMON_END('v', 0, newerrno, blockresult);
102         PACK_MEMORY(0, MEMORY_API_FREE, ptr);
103         FLUSH_LOCAL_BUF();
104
105         POST_PACK_PROBEBLOCK_END();
106 }
107
108 void *realloc(void *memblock, size_t size)
109 {
110         static void* (*reallocp)(void*, size_t);
111         DECLARE_VARIABLE_STANDARD;
112         void *pret;
113
114         rtdl_next_current_set_once(reallocp);
115         PRE_PROBEBLOCK();
116
117         if(memblock != NULL && gProbeBlockCount == 0)
118                 del_memory_hash(memblock, MEMTYPE_FREE, NULL);
119
120         pret = (*reallocp)(memblock, size);
121
122         if(pret != NULL && gProbeBlockCount == 0)
123                 add_memory_hash(pret, size, MEMTYPE_ALLOC,
124                                 blockresult ? MEM_EXTERNAL : MEM_INTERNAL);
125
126         POST_PACK_PROBEBLOCK_BEGIN();
127
128         PREPARE_LOCAL_BUF();
129         PACK_COMMON_BEGIN(MSG_PROBE_MEMORY, API_ID_realloc,
130                           "px", voidp_to_uint64(memblock), (uint64_t) size);
131         PACK_COMMON_END('p', pret, newerrno, blockresult);
132         PACK_MEMORY(size, MEMORY_API_ALLOC, pret);
133         FLUSH_LOCAL_BUF();
134
135         POST_PACK_PROBEBLOCK_END();
136
137         return pret;
138 }
139
140
141 void *temp_calloc(size_t nelem, size_t elsize)
142 {
143         /* Magic number, but somewhy it is sufficent */
144         static char extra_mem[20] = {0};
145         return (nelem * elsize > sizeof(extra_mem))
146                 ? extra_mem
147                 : NULL;
148 }
149
150 void *calloc(size_t nelem, size_t elsize)
151 {
152         static void* (*callocp)(size_t, size_t);
153         DECLARE_VARIABLE_STANDARD;
154         void *pret;
155
156         if (!callocp) {
157                 /**
158                  * Calloc is called by `dlsym`, so we provide small amount
159                  * of static memory via `temp_calloc`.
160                  */
161                 callocp = temp_calloc;
162                 callocp = rtdl_next(__func__);
163         }
164
165         PRE_PROBEBLOCK();
166
167         pret = (*callocp)(nelem, elsize);
168
169         if(pret != NULL && gProbeBlockCount == 0)
170                 add_memory_hash(pret, nelem * elsize, MEMTYPE_ALLOC,
171                                 blockresult ? MEM_EXTERNAL : MEM_INTERNAL);
172
173         POST_PACK_PROBEBLOCK_BEGIN();
174
175         PREPARE_LOCAL_BUF();
176         PACK_COMMON_BEGIN(MSG_PROBE_MEMORY, API_ID_calloc,
177                           "xx", (uint64_t)nelem, (uint64_t)elsize);
178         PACK_COMMON_END('p', pret, newerrno, blockresult);
179         PACK_MEMORY(nelem * elsize, MEMORY_API_ALLOC, pret);
180         FLUSH_LOCAL_BUF();
181
182         POST_PACK_PROBEBLOCK_END();
183
184
185         return pret;
186 }