1 #ifndef INCLUDE_HEAP_JEMALLOC_STD_C
2 #define INCLUDE_HEAP_JEMALLOC_STD_C
3 #define HEAP32 1
4 #include "linux_heap_jemalloc.c"
5 #undef HEAP32
6 #endif
7
8 #undef GH
9 #undef GHT
10 #undef GHT_MAX
11 #undef PFMTx
12
13 // FIXME: It should be detected at runtime, not during the compilation stage
14 #if HEAP32
15 #define GH(x) x##_32
16 #define GHT ut32
17 #define GHT_MAX UT32_MAX
18 #define PFMTx PFMT32x
19 #else
20 #define GH(x) x##_64
21 #define GHT ut64
22 #define GHT_MAX UT64_MAX
23 #define PFMTx PFMT64x
24 #endif
25
26 #if __linux__
27 // TODO: provide proper api in cbin to resolve symbols and load libraries from debug maps and such
28 // this is, provide a programmatic api for the slow dmi command
GH(je_get_va_symbol)29 static GHT GH(je_get_va_symbol)(const char *path, const char *symname) {
30 RListIter *iter;
31 RBinSymbol *s;
32 RCore *core = r_core_new ();
33 GHT vaddr = 0LL;
34
35 if (!core) {
36 return GHT_MAX;
37 }
38
39 RBinOptions opt;
40 r_bin_options_init (&opt, -1, 0, 0, false);
41 if (r_bin_open (core->bin, path, &opt)) {
42 RList *syms = r_bin_get_symbols (core->bin);
43 if (!syms) {
44 r_core_free (core);
45 return GHT_MAX;
46 }
47 r_list_foreach (syms, iter, s) {
48 if (!strcmp(s->name, symname)) {
49 vaddr = s->vaddr;
50 break;
51 }
52 }
53 }
54 r_core_free (core);
55 return vaddr;
56 }
57
GH(je_matched)58 static int GH(je_matched)(const char *ptr, const char *str) {
59 int ret = strncmp (ptr, str, strlen (str) - 1);
60 return !ret;
61 }
62 #endif
63
GH(r_resolve_jemalloc)64 static bool GH(r_resolve_jemalloc)(RCore *core, char *symname, ut64 *symbol) {
65 RListIter *iter;
66 RDebugMap *map;
67 const char *jemalloc_ver_end = NULL;
68 ut64 jemalloc_addr = UT64_MAX;
69
70 if (!core || !core->dbg || !core->dbg->maps){
71 return false;
72 }
73 r_debug_map_sync (core->dbg);
74 r_list_foreach (core->dbg->maps, iter, map) {
75 if (strstr (map->name, "libjemalloc.")) {
76 jemalloc_addr = map->addr;
77 jemalloc_ver_end = map->name;
78 break;
79 }
80 }
81 if (!jemalloc_ver_end) {
82 eprintf ("Warning: Is jemalloc mapped in memory? (see dm command)\n");
83 return false;
84 }
85 #if __linux__
86 bool is_debug_file = GH(je_matched)(jemalloc_ver_end, "/usr/local/lib");
87
88 if (!is_debug_file) {
89 eprintf ("Warning: Is libjemalloc.so.2 in /usr/local/lib path?\n");
90 return false;
91 }
92 char *path = r_str_newf ("%s", jemalloc_ver_end);
93 if (r_file_exists (path)) {
94 ut64 vaddr = GH(je_get_va_symbol)(path, symname);
95 if (jemalloc_addr != GHT_MAX && vaddr != 0) {
96 *symbol = jemalloc_addr + vaddr;
97 free (path);
98 return true;
99 }
100 }
101 free (path);
102 return false;
103 #else
104 eprintf ("[*] Resolving %s from libjemalloc.2... ", symname);
105 // this is quite sloooow, we must optimize dmi
106 char *va = r_core_cmd_strf (core, "dmi libjemalloc.2 %s$~[1]", symname);
107 ut64 n = r_num_get (NULL, va);
108 if (n && n != UT64_MAX) {
109 *symbol = n;
110 eprintf ("0x%08"PFMT64x"\n", n);
111 } else {
112 eprintf ("NOT FOUND\n");
113 }
114 free (va);
115 return true;
116 #endif
117 }
118
GH(jemalloc_get_chunks)119 static void GH(jemalloc_get_chunks)(RCore *core, const char *input) {
120 ut64 cnksz;
121 RConsPrintablePalette *pal = &r_cons_singleton ()->context->pal;
122
123 if (!GH(r_resolve_jemalloc)(core, "je_chunksize", &cnksz)) {
124 eprintf ("Fail at read symbol je_chunksize\n");
125 return;
126 }
127 r_io_read_at (core->io, cnksz, (ut8 *)&cnksz, sizeof (GHT));
128
129 switch (input[0]) {
130 case '\0':
131 eprintf ("need an arena_t to associate chunks");
132 break;
133 case ' ':
134 {
135 GHT arena = GHT_MAX;
136 arena_t *ar = R_NEW0 (arena_t);
137 extent_node_t *node = R_NEW0 (extent_node_t), *head = R_NEW0 (extent_node_t);
138 input += 1;
139 arena = r_num_math (core->num, input);
140
141 if (arena) {
142 r_io_read_at (core->io, arena, (ut8 *)ar, sizeof (arena_t));
143 r_io_read_at (core->io, (GHT)(size_t)ar->achunks.qlh_first, (ut8 *)head, sizeof (extent_node_t));
144 if (head->en_addr) {
145 PRINT_YA (" Chunk - start: ");
146 PRINTF_BA ("0x%08"PFMT64x, (ut64)(size_t)head->en_addr);
147 PRINT_YA (", end: ");
148 PRINTF_BA ("0x%08"PFMT64x, (ut64)(size_t)((char *)head->en_addr + cnksz));
149 PRINT_YA (", size: ");
150 PRINTF_BA ("0x%08"PFMT64x"\n", (ut64)cnksz);
151 r_io_read_at (core->io, (ut64)(size_t)head->ql_link.qre_next, (ut8 *)node, sizeof (extent_node_t));
152 while (node && node->en_addr != head->en_addr) {
153 PRINT_YA (" Chunk - start: ");
154 PRINTF_BA ("0x%08"PFMT64x, (ut64)(size_t)node->en_addr);
155 PRINT_YA (", end: ");
156 PRINTF_BA ("0x%"PFMT64x, (ut64)(size_t)((char *)node->en_addr + cnksz));
157 PRINT_YA (", size: ");
158 PRINTF_BA ("0x%08"PFMT64x"\n", cnksz);
159 r_io_read_at (core->io, (ut64)(size_t)node->ql_link.qre_next, (ut8 *)node, sizeof (extent_node_t));
160 }
161 }
162 }
163 free (ar);
164 free (head);
165 free (node);
166 break;
167 }
168 case '*':
169 {
170 int i = 0;
171 ut64 sym;
172 GHT arenas = GHT_MAX, arena = GHT_MAX;
173 arena_t *ar = R_NEW0 (arena_t);
174 extent_node_t *node = R_NEW0 (extent_node_t);
175 extent_node_t *head = R_NEW0 (extent_node_t);
176
177 if (!node || !head) {
178 eprintf ("Error calling calloc\n");
179 free (ar);
180 free (node);
181 free (head);
182 return;
183 }
184
185 if (GH(r_resolve_jemalloc) (core, "je_arenas", &sym)) {
186 r_io_read_at (core->io, sym, (ut8 *)&arenas, sizeof (GHT));
187 for (;;) {
188 r_io_read_at (core->io, arenas + i * sizeof (GHT), (ut8 *)&arena, sizeof (GHT));
189 if (!arena) {
190 break;
191 }
192 PRINTF_GA ("arenas[%d]: @ 0x%"PFMTx" { \n", i++, (GHT)arena);
193 r_io_read_at (core->io, arena, (ut8 *)ar, sizeof (arena_t));
194 r_io_read_at (core->io, (GHT)(size_t)ar->achunks.qlh_first, (ut8 *)head, sizeof (extent_node_t));
195 if (head->en_addr != 0) {
196 PRINT_YA (" Chunk - start: ");
197 PRINTF_BA ("0x%08"PFMT64x, (ut64)(size_t)head->en_addr);
198 PRINT_YA (", end: ");
199 PRINTF_BA ("0x%"PFMT64x, (ut64)(size_t)((char *)head->en_addr + cnksz));
200 PRINT_YA (", size: ");
201 PRINTF_BA ("0x%08"PFMT64x"\n", (ut64)cnksz);
202 ut64 addr = (ut64) (size_t)head->ql_link.qre_next;
203 r_io_read_at (core->io, addr, (ut8 *)node, sizeof (extent_node_t));
204 while (node && head && node->en_addr != head->en_addr) {
205 PRINT_YA (" Chunk - start: ");
206 PRINTF_BA ("0x%08"PFMT64x, (ut64)(size_t)node->en_addr);
207 PRINT_YA (", end: ");
208 PRINTF_BA ("0x%"PFMT64x, (ut64)(size_t)((char *)node->en_addr + cnksz));
209 PRINT_YA (", size: ");
210 PRINTF_BA ("0x%"PFMT64x"\n", cnksz);
211 r_io_read_at (core->io, (GHT)(size_t)node->ql_link.qre_next, (ut8 *)node, sizeof (extent_node_t));
212 }
213 }
214 PRINT_GA ("}\n");
215 }
216 }
217 free (ar);
218 free (head);
219 free (node);
220 }
221 break;
222 }
223 }
224
GH(jemalloc_print_narenas)225 static void GH(jemalloc_print_narenas)(RCore *core, const char *input) {
226 ut64 symaddr;
227 ut64 arenas;
228 GHT arena = GHT_MAX;
229 arena_t *ar = R_NEW0 (arena_t);
230 if (!ar) {
231 return;
232 }
233 arena_stats_t *stats = R_NEW0 (arena_stats_t);
234 if (!stats) {
235 free (ar);
236 return;
237 }
238 int i = 0;
239 GHT narenas = 0;
240 RConsPrintablePalette *pal = &r_cons_singleton ()->context->pal;
241
242 switch (input[0]) {
243 case '\0':
244 if (GH(r_resolve_jemalloc)(core, "narenas_total", &symaddr)) {
245 r_io_read_at (core->io, symaddr, (ut8 *)&narenas, sizeof (GHT));
246 PRINTF_GA ("narenas : %"PFMT64d"\n", (ut64)narenas);
247 }
248 if (narenas == 0) {
249 eprintf ("No arenas allocated.\n");
250 free (stats);
251 free (ar);
252 return;
253 }
254 if (narenas == GHT_MAX) {
255 eprintf ("Cannot find narenas_total\n");
256 free (stats);
257 free (ar);
258 return;
259 }
260
261 if (GH(r_resolve_jemalloc)(core, "je_arenas", &arenas)) {
262 r_io_read_at (core->io, arenas, (ut8 *)&arenas, sizeof (GHT));
263 PRINTF_GA ("arenas[%"PFMT64d"] @ 0x%"PFMT64x" {\n", (ut64)narenas, (ut64)arenas);
264 for (i = 0; i < narenas; i++) {
265 ut64 at = arenas + (i * sizeof (GHT));
266 r_io_read_at (core->io, at, (ut8 *)&arena, sizeof (GHT));
267 if (!arena) {
268 PRINTF_YA (" arenas[%d]: (empty)\n", i);
269 continue;
270 }
271 PRINTF_YA (" arenas[%d]: ", i);
272 PRINTF_BA ("@ 0x%"PFMT64x"\n", at);
273 }
274 }
275 PRINT_GA ("}\n");
276 break;
277 case ' ':
278 arena = r_num_math (core->num, input + 1);
279 r_io_read_at (core->io, (GHT)arena, (ut8 *)ar, sizeof (arena_t));
280
281 PRINT_GA ("struct arena_s {\n");
282 #define OO(x) (ut64)(arena + r_offsetof (arena_t, x))
283 PRINTF_BA (" ind = 0x%x\n", ar->ind);
284 PRINTF_BA (" nthreads: application allocation = 0x%"PFMT64x"\n", (ut64)ar->nthreads[0]);
285 PRINTF_BA (" nthreads: internal metadata allocation = 0x%"PFMT64x"\n", (ut64)ar->nthreads[1]);
286 PRINTF_BA (" lock = 0x%"PFMT64x"\n", OO(lock));
287 PRINTF_BA (" stats = 0x%"PFMT64x"\n", OO(stats));
288 PRINTF_BA (" tcache_ql = 0x%"PFMT64x"\n", OO(tcache_ql));
289 PRINTF_BA (" prof_accumbytes = 0x%"PFMT64x"x\n", (ut64)ar->prof_accumbytes);
290 PRINTF_BA (" offset_state = 0x%"PFMT64x"\n", (ut64)ar->offset_state);
291 PRINTF_BA (" dss_prec_t = 0x%"PFMT64x"\n",OO(dss_prec));
292 PRINTF_BA (" achunks = 0x%"PFMT64x"\n", OO(achunks));
293 PRINTF_BA (" extent_sn_next = 0x%"PFMT64x"\n", (ut64)(size_t)ar->extent_sn_next);
294 PRINTF_BA (" spare = 0x%"PFMT64x"\n", (ut64)(size_t)ar->spare);
295 PRINTF_BA (" lg_dirty_mult = 0x%"PFMT64x"\n", (ut64)(ssize_t)ar->lg_dirty_mult);
296 PRINTF_BA (" purging = %s\n", r_str_bool (ar->purging));
297 PRINTF_BA (" nactive = 0x%"PFMT64x"\n", (ut64)(size_t)ar->nactive);
298 PRINTF_BA (" ndirty = 0x%"PFMT64x"\n", (ut64)(size_t)ar->ndirty);
299
300 PRINTF_BA (" runs_dirty = 0x%"PFMT64x"\n", OO(runs_dirty));
301 PRINTF_BA (" chunks_cache = 0x%"PFMT64x"\n", OO(chunks_cache));
302 PRINTF_BA (" huge = 0x%"PFMT64x"\n", OO(huge));
303 PRINTF_BA (" huge_mtx = 0x%"PFMT64x"\n", OO(huge_mtx));
304
305 PRINTF_BA (" chunks_szsnad_cached = 0x%"PFMT64x"\n", OO(chunks_szsnad_cached));
306 PRINTF_BA (" chunks_ad_cached = 0x%"PFMT64x"\n", OO(chunks_ad_cached));
307 PRINTF_BA (" chunks_szsnad_retained = 0x%"PFMT64x"\n", OO(chunks_szsnad_retained));
308 PRINTF_BA (" chunks_ad_cached = 0x%"PFMT64x"\n", OO(chunks_ad_retained));
309
310 PRINTF_BA (" chunks_mtx = 0x%"PFMT64x"\n", OO(chunks_mtx));
311 PRINTF_BA (" node_cache = 0x%"PFMT64x"\n", OO(node_cache));
312 PRINTF_BA (" node_cache_mtx = 0x%"PFMT64x"\n", OO(node_cache_mtx));
313 PRINTF_BA (" chunks_hooks = 0x%"PFMT64x"\n", OO(chunk_hooks));
314 PRINTF_BA (" bins = %d 0x%"PFMT64x"\n", JM_NBINS, OO(bins));
315 PRINTF_BA (" runs_avail = %d 0x%"PFMT64x"\n", NPSIZES, OO(runs_avail));
316 PRINT_GA ("}\n");
317 break;
318 }
319 free (ar);
320 free (stats);
321 }
322
GH(jemalloc_get_bins)323 static void GH(jemalloc_get_bins)(RCore *core, const char *input) {
324 int i = 0, j;
325 ut64 bin_info;
326 ut64 arenas;
327 GHT arena = GHT_MAX; //, bin = GHT_MAX;
328 arena_t *ar = NULL;
329 arena_bin_info_t *b = NULL;
330 RConsPrintablePalette *pal = &r_cons_singleton ()->context->pal;
331
332 switch (input[0]) {
333 case ' ':
334 ar = R_NEW0 (arena_t);
335 if (!ar) {
336 break;
337 }
338 b = R_NEW0 (arena_bin_info_t);
339 if (!b) {
340 break;
341 }
342 if (!GH(r_resolve_jemalloc)(core, "je_arena_bin_info", &bin_info)) {
343 eprintf ("Error resolving je_arena_bin_info\n");
344 R_FREE (b);
345 break;
346 }
347 if (GH(r_resolve_jemalloc)(core, "je_arenas", &arenas)) {
348 r_io_read_at (core->io, arenas, (ut8 *)&arenas, sizeof (GHT));
349 PRINTF_GA ("arenas @ 0x%"PFMTx" {\n", (GHT)arenas);
350 for (;;) {
351 r_io_read_at (core->io, arenas + i * sizeof (GHT), (ut8 *)&arena, sizeof (GHT));
352 if (!arena) {
353 R_FREE (b);
354 break;
355 }
356 PRINTF_YA (" arenas[%d]: ", i++);
357 PRINTF_BA ("@ 0x%"PFMTx, (GHT)arena);
358 PRINT_YA (" {\n");
359 r_io_read_at (core->io, arena, (ut8 *)ar, sizeof (arena_t));
360 for (j = 0; j < JM_NBINS; j++) {
361 r_io_read_at (core->io, (GHT)(bin_info + j * sizeof (arena_bin_info_t)),
362 (ut8*)b, sizeof (arena_bin_info_t));
363 PRINT_YA (" {\n");
364 PRINT_YA (" regsize : ");
365 PRINTF_BA ("0x%zx\n", b->reg_size);
366 PRINT_YA (" redzone size ");
367 PRINTF_BA ("0x%zx\n", b->redzone_size);
368 PRINT_YA (" reg_interval : ");
369 PRINTF_BA ("0x%zx\n", b->reg_interval);
370 PRINT_YA (" run_size : ");
371 PRINTF_BA ("0x%zx\n", b->run_size);
372 PRINT_YA (" nregs : ");
373 PRINTF_BA ("0x%x\n", b->nregs);
374 // FIXME: It's a structure of bitmap_info_t
375 //PRINT_YA (" bitmap_info : ");
376 //PRINTF_BA ("0x%"PFMT64x"\n", b->bitmap_info);
377 PRINT_YA (" reg0_offset : ");
378 PRINTF_BA ("0x%"PFMT64x"\n\n", (ut64)b->reg0_offset);
379 // FIXME: It's a structure of malloc_mutex_t
380 //PRINTF_YA (" bins[%d]->lock ", j);
381 //PRINTF_BA ("= 0x%"PFMT64x"\n", ar->bins[j].lock);
382 // FIXME: It's a structure of arena_run_t*
383 //PRINTF_YA (" bins[%d]->runcur ", j);
384 //PRINTF_BA ("@ 0x%"PFMT64x"\n", ar->bins[j].runcur);
385 // FIXME: It's a structure of arena_run_heap_t*
386 //PRINTF_YA (" bins[%d]->runs ", j);
387 //PRINTF_BA ("@ 0x%"PFMTx"\n", ar->bins[j].runs);
388 // FIXME: It's a structure of malloc_bin_stats_t
389 //PRINTF_YA (" bins[%d]->stats ", j);
390 //PRINTF_BA ("= 0x%"PFMTx"\n", ar->bins[j].stats);
391 PRINT_YA (" }\n");
392 }
393 PRINT_YA (" }\n");
394 }
395 }
396 PRINT_GA ("}\n");
397 break;
398 }
399 free (ar);
400 free (b);
401 }
402
403 #if 0
404 static void GH(jemalloc_get_runs)(RCore *core, const char *input) {
405 switch (input[0]) {
406 case ' ':
407 {
408 int pageind;
409 ut64 npages, chunksize_mask, map_bias, map_misc_offset, chunk, mapbits;;
410 arena_chunk_t *c = R_NEW0 (arena_chunk_t);
411
412 if (!c) {
413 eprintf ("Error calling calloc\n");
414 return;
415 }
416
417 input += 1;
418 chunk = r_num_math (core->num, input);
419
420 if (!GH(r_resolve_jemalloc)(core, "je_chunk_npages", &npages)) {
421 eprintf ("Error resolving je_chunk_npages\n");
422 return;
423 }
424 if (!GH(r_resolve_jemalloc)(core, "je_chunksize_mask", &chunksize_mask)) {
425 eprintf ("Error resolving je_chunksize_mask\n");
426 return;
427 }
428 if (!GH(r_resolve_jemalloc)(core, "je_map_bias", &map_bias)) {
429 eprintf ("Error resolving je_map_bias");
430 return;
431 }
432 if (!GH(r_resolve_jemalloc)(core, "je_map_misc_offset", &map_misc_offset)) {
433 eprintf ("Error resolving je_map_misc_offset");
434 return;
435 }
436
437 r_io_read_at (core->io, npages, (ut8*)&npages, sizeof (GHT));
438 r_io_read_at (core->io, chunksize_mask, (ut8*)&chunksize_mask, sizeof (GHT));
439 r_io_read_at (core->io, map_bias, (ut8*)&map_bias, sizeof (GHT));
440 r_io_read_at (core->io, map_misc_offset, (ut8*)&map_misc_offset, sizeof (GHT));
441
442 eprintf ("map_misc_offset 0x%08"PFMT64x"\n", (ut64)map_misc_offset);
443
444 r_io_read_at (core->io, chunk, (ut8 *)c, sizeof (arena_chunk_t));
445 mapbits = *(GHT *)&c->map_bits;
446 eprintf ("map_bits: 0x%08"PFMT64x"\n", (ut64)mapbits);
447
448 uint32_t offset = r_offsetof (arena_chunk_t, map_bits);
449
450 arena_chunk_map_bits_t *dwords = (void *)calloc (sizeof (arena_chunk_map_bits_t), npages);
451 r_io_read_at (core->io, chunk + offset, (ut8*)dwords, sizeof (arena_chunk_map_bits_t) * npages);
452 eprintf ("map_bits @ 0x%08"PFMT64x"\n", (ut64)(chunk + offset));
453
454 arena_run_t *r = R_NEW0 (arena_run_t);
455 if (!r) {
456 eprintf ("Error calling calloc\n");
457 return;
458 }
459 for (pageind = map_bias; pageind < npages; pageind++) {
460 arena_chunk_map_bits_t mapelm = dwords[pageind-map_bias];
461 if (mapelm.bits & CHUNK_MAP_ALLOCATED) {
462 // ut64 elm = ((arena_chunk_map_misc_t *)((uintptr_t)chunk + (uintptr_t)map_misc_offset) + pageind-map_bias);
463 ut64 elm = chunk + map_misc_offset + pageind-map_bias;
464 eprintf ("\nelm: 0x%"PFMT64x"\n", elm);
465 arena_chunk_map_misc_t *m = R_NEW0 (arena_chunk_map_misc_t);
466 if (m) {
467 ut64 run = elm + r_offsetof (arena_chunk_map_misc_t, run);
468 r_io_read_at (core->io, elm, (ut8*)m, sizeof (arena_chunk_map_misc_t));
469 eprintf ("Small run @ 0x%08"PFMT64x"\n", (ut64)elm);
470 r_io_read_at (core->io, run, (ut8*)r, sizeof (arena_run_t));
471 eprintf ("binind: 0x%08"PFMT64x"\n", (ut64)r->binind);
472 eprintf ("nfree: 0x%08"PFMT64x"\n", (ut64)r->nfree);
473 eprintf ("bitmap: 0x%08"PFMT64x"\n\n", (ut64)*(GHT*)r->bitmap);
474 free (m);
475 }
476 } else if (mapelm.bits & CHUNK_MAP_LARGE) {
477 ut64 run = (ut64) (size_t) chunk + (pageind << LG_PAGE);
478 eprintf ("Large run @ 0x%08"PFMT64x"\n", run);
479 r_io_read_at (core->io, run, (ut8*)r, sizeof (arena_run_t));
480 eprintf ("binind: 0x%08"PFMT64x"\n", (ut64)r->binind);
481 eprintf ("nfree: 0x%08"PFMT64x"\n", (ut64)r->nfree);
482 eprintf ("bitmap: 0x%08"PFMT64x"\n\n", (ut64)*(GHT*)r->bitmap);
483 }
484 }
485 free (c);
486 free (r);
487 }
488 break;
489 }
490 }
491 #endif
492
GH(cmd_dbg_map_jemalloc)493 static int GH(cmd_dbg_map_jemalloc)(RCore *core, const char *input) {
494 const char *help_msg[] = {
495 "Usage:", "dmh", " # Memory map heap",
496 "dmha", "[arena_t]", "show all arenas created, or print arena_t structure for given arena",
497 "dmhb", "[arena_t]", "show all bins created for given arena",
498 "dmhc", "*|[arena_t]", "show all chunks created in all arenas, or show all chunks created for a given arena_t instance",
499 // "dmhr", "[arena_chunk_t]", "print all runs created for a given arena_chunk_t instance",
500 "dmh?", "", "Show map heap help", NULL
501 };
502
503 switch (input[0]) {
504 case '?':
505 r_core_cmd_help (core, help_msg);
506 break;
507 case 'a': //dmha
508 GH(jemalloc_print_narenas) (core, input + 1);
509 break;
510 case 'b': //dmhb
511 GH(jemalloc_get_bins) (core, input + 1);
512 break;
513 case 'c': //dmhc
514 GH(jemalloc_get_chunks) (core, input + 1);
515 break;
516 /*
517 case 'r': //dmhr
518 GH(jemalloc_get_runs) (core, input + 1);
519 break;
520 */
521 }
522 return 0;
523 }
524
525