libroot_debug: Merge guarded heap into libroot_debug.
[haiku.git] / src / system / libroot / posix / malloc_debug / malloc_debug_api.cpp
blob45d3c1c6c3e7e726882310a47b1a7bd54b137ff5
1 /*
2 * Copyright 2015, Michael Lotz <mmlr@mlotz.ch>.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "malloc_debug_api.h"
9 #include <malloc.h>
10 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
16 static heap_implementation* sCurrentHeap = NULL;
19 // #pragma mark - Heap Debug API
22 extern "C" status_t
23 heap_debug_start_wall_checking(int msInterval)
25 if (sCurrentHeap->start_wall_checking != NULL)
26 return sCurrentHeap->start_wall_checking(msInterval);
28 return B_NOT_SUPPORTED;
32 extern "C" status_t
33 heap_debug_stop_wall_checking()
35 if (sCurrentHeap->stop_wall_checking != NULL)
36 return sCurrentHeap->stop_wall_checking();
38 return B_NOT_SUPPORTED;
42 extern "C" void
43 heap_debug_set_paranoid_validation(bool enabled)
45 if (sCurrentHeap->set_paranoid_validation != NULL)
46 sCurrentHeap->set_paranoid_validation(enabled);
50 extern "C" void
51 heap_debug_set_memory_reuse(bool enabled)
53 if (sCurrentHeap->set_memory_reuse != NULL)
54 sCurrentHeap->set_memory_reuse(enabled);
58 extern "C" void
59 heap_debug_set_debugger_calls(bool enabled)
61 if (sCurrentHeap->set_debugger_calls != NULL)
62 sCurrentHeap->set_debugger_calls(enabled);
66 extern "C" void
67 heap_debug_set_default_alignment(size_t defaultAlignment)
69 if (sCurrentHeap->set_default_alignment != NULL)
70 sCurrentHeap->set_default_alignment(defaultAlignment);
74 extern "C" void
75 heap_debug_validate_heaps()
77 if (sCurrentHeap->validate_heaps != NULL)
78 sCurrentHeap->validate_heaps();
82 extern "C" void
83 heap_debug_validate_walls()
85 if (sCurrentHeap->validate_walls != NULL)
86 sCurrentHeap->validate_walls();
90 extern "C" void
91 heap_debug_dump_allocations(bool statsOnly, thread_id thread)
93 if (sCurrentHeap->dump_allocations != NULL)
94 sCurrentHeap->dump_allocations(statsOnly, thread);
98 extern "C" void
99 heap_debug_dump_heaps(bool dumpAreas, bool dumpBins)
101 if (sCurrentHeap->dump_heaps != NULL)
102 sCurrentHeap->dump_heaps(dumpAreas, dumpBins);
106 extern "C" void *
107 heap_debug_malloc_with_guard_page(size_t size)
109 if (sCurrentHeap->malloc_with_guard_page != NULL)
110 return sCurrentHeap->malloc_with_guard_page(size);
112 return NULL;
116 extern "C" status_t
117 heap_debug_get_allocation_info(void *address, size_t *size,
118 thread_id *thread)
120 if (sCurrentHeap->get_allocation_info != NULL)
121 return sCurrentHeap->get_allocation_info(address, size, thread);
123 return B_NOT_SUPPORTED;
127 extern "C" status_t
128 heap_debug_set_dump_allocations_on_exit(bool enabled)
130 if (sCurrentHeap->set_dump_allocations_on_exit != NULL)
131 return sCurrentHeap->set_dump_allocations_on_exit(enabled);
133 return B_NOT_SUPPORTED;
137 extern "C" status_t
138 heap_debug_set_stack_trace_depth(size_t stackTraceDepth)
140 if (sCurrentHeap->set_stack_trace_depth != NULL)
141 return sCurrentHeap->set_stack_trace_depth(stackTraceDepth);
143 return B_NOT_SUPPORTED;
147 // #pragma mark - Init
150 extern "C" status_t
151 __init_heap(void)
153 const char *mode = getenv("MALLOC_DEBUG");
154 if (mode == NULL || strchr(mode, 'g') == NULL)
155 sCurrentHeap = &__mallocDebugHeap;
156 else
157 sCurrentHeap = &__mallocGuardedHeap;
159 status_t result = sCurrentHeap->init();
160 if (result != B_OK)
161 return result;
163 if (mode != NULL) {
164 if (strchr(mode, 'p') != NULL)
165 heap_debug_set_paranoid_validation(true);
166 if (strchr(mode, 'r') != NULL)
167 heap_debug_set_memory_reuse(false);
168 if (strchr(mode, 'e') != NULL)
169 heap_debug_set_dump_allocations_on_exit(true);
171 size_t defaultAlignment = 0;
172 const char *argument = strchr(mode, 'a');
173 if (argument != NULL
174 && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) {
175 heap_debug_set_default_alignment(defaultAlignment);
178 size_t stackTraceDepth = 0;
179 argument = strchr(mode, 's');
180 if (argument != NULL
181 && sscanf(argument, "s%" B_SCNuSIZE, &stackTraceDepth) == 1) {
182 heap_debug_set_stack_trace_depth(stackTraceDepth);
185 int wallCheckInterval = 0;
186 argument = strchr(mode, 'w');
187 if (argument != NULL
188 && sscanf(argument, "w%d", &wallCheckInterval) == 1) {
189 heap_debug_start_wall_checking(wallCheckInterval);
193 return B_OK;
197 extern "C" void
198 __heap_terminate_after()
200 if (sCurrentHeap->terminate_after != NULL)
201 sCurrentHeap->terminate_after();
205 // #pragma mark - Public API
208 extern "C" void*
209 sbrk_hook(long)
211 debug_printf("sbrk not supported on malloc debug\n");
212 debugger("sbrk not supported on malloc debug");
213 return NULL;
217 extern "C" void*
218 memalign(size_t alignment, size_t size)
220 return sCurrentHeap->memalign(alignment, size);
224 extern "C" void*
225 malloc(size_t size)
227 return sCurrentHeap->malloc(size);
231 extern "C" void
232 free(void* address)
234 sCurrentHeap->free(address);
238 extern "C" void*
239 realloc(void* address, size_t newSize)
241 return sCurrentHeap->realloc(address, newSize);
245 extern "C" void*
246 calloc(size_t numElements, size_t size)
248 if (sCurrentHeap->calloc != NULL)
249 return sCurrentHeap->calloc(numElements, size);
251 void* address = malloc(numElements * size);
252 if (address != NULL)
253 memset(address, 0, numElements * size);
255 return address;
259 extern "C" void*
260 valloc(size_t size)
262 if (sCurrentHeap->valloc != NULL)
263 return sCurrentHeap->valloc(size);
265 return memalign(B_PAGE_SIZE, size);
269 extern "C" int
270 posix_memalign(void **pointer, size_t alignment, size_t size)
272 if (sCurrentHeap->posix_memalign != NULL)
273 return sCurrentHeap->posix_memalign(pointer, alignment, size);
275 if (!is_valid_alignment(alignment))
276 return EINVAL;
278 *pointer = memalign(alignment, size);
279 if (*pointer == NULL)
280 return ENOMEM;
282 return 0;