blob: 5cda69853e76819246ecc8aff0f74cd1d386c368 [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*
2 This file is part of Callgrind, a Valgrind skin for call graph
3 profiling programs.
4
sewardje4b0bf02006-06-05 23:21:15 +00005 Copyright (C) 2002-2006, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +00006
7 This skin is derived from and contains lot of code from Cachegrind
8 Copyright (C) 2002 Nicholas Nethercote (njn25@cam.ac.uk)
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 02111-1307, USA.
24
25 The GNU General Public License is contained in the file COPYING.
26*/
27
28#include "config.h" // for VG_PREFIX
29
30#include "global.h"
31
32
33
34/*------------------------------------------------------------*/
35/*--- Function specific configuration options ---*/
36/*------------------------------------------------------------*/
37
38/* Special value for separate_callers: automatic = adaptive */
39#define CONFIG_AUTO -1
40
41#define CONFIG_DEFAULT -1
42#define CONFIG_FALSE 0
43#define CONFIG_TRUE 1
44
45/* Logging configuration for a function */
46struct _fn_config {
47 Int dump_before;
48 Int dump_after;
49 Int zero_before;
50 Int toggle_collect;
51
52 Int skip; /* Handle CALL to this function as JMP (= Skip)? */
53 Int group; /* don't change caller dependency inside group !=0 */
54 Int pop_on_jump;
55
56 Int separate_callers; /* separate logging dependent on caller */
57 Int separate_recursions; /* separate logging of rec. levels */
58
59#if CLG_ENABLE_DEBUG
60 Int verbosity; /* Change debug verbosity level while in function */
61#endif
62};
63
64/* Configurations for function name prefix patterns.
65 * Currently, only very limit patterns are possible:
66 * Exact prefix patterns and "*::" are allowed.
67 * E.g.
68 * - "abc" matches all functions starting with "abc".
69 * - "abc*::def" matches all functions starting with "abc" and
70 * starting with "def" after the first "::" separator.
71 * - "*::print(" matches C++ methods "print" in all classes
72 * without namespace. I.e. "*" doesn't match a "::".
73 *
74 * We build a trie from patterns, and for a given function, we
75 * go down the tree and apply all non-default configurations.
76 */
77
78
79#define NODE_DEGREE 30
80
81/* node of compressed trie search structure */
82typedef struct _config_node config_node;
83struct _config_node {
84 Int length;
85
86 fn_config* config;
87 config_node* sub_node[NODE_DEGREE];
88 config_node* next;
89 config_node* wild_star;
90 config_node* wild_char;
91
92 Char name[1];
93};
94
95/* root of trie */
96static config_node* fn_configs = 0;
97
98static __inline__
99fn_config* new_fnc(void)
100{
101 fn_config* new = (fn_config*) CLG_MALLOC(sizeof(fn_config));
102
103 new->dump_before = CONFIG_DEFAULT;
104 new->dump_after = CONFIG_DEFAULT;
105 new->zero_before = CONFIG_DEFAULT;
106 new->toggle_collect = CONFIG_DEFAULT;
107 new->skip = CONFIG_DEFAULT;
108 new->pop_on_jump = CONFIG_DEFAULT;
109 new->group = CONFIG_DEFAULT;
110 new->separate_callers = CONFIG_DEFAULT;
111 new->separate_recursions = CONFIG_DEFAULT;
112
113#if CLG_ENABLE_DEBUG
114 new->verbosity = CONFIG_DEFAULT;
115#endif
116
117 return new;
118}
119
120
121static config_node* new_config(Char* name, int length)
122{
123 int i;
124 config_node* node = (config_node*) CLG_MALLOC(sizeof(config_node) + length);
125
126 for(i=0;i<length;i++) {
127 if (name[i] == 0) break;
128 node->name[i] = name[i];
129 }
130 node->name[i] = 0;
131
132 node->length = length;
133 node->config = 0;
134 for(i=0;i<NODE_DEGREE;i++)
135 node->sub_node[i] = 0;
136 node->next = 0;
137 node->wild_char = 0;
138 node->wild_star = 0;
139
140 CLG_DEBUG(3, " new_config('%s', len %d)\n", node->name, length);
141
142 return node;
143}
144
145static __inline__
146Bool is_wild(Char n)
147{
148 return (n == '*') || (n == '?');
149}
150
151/* Recursively build up function matching tree (prefix tree).
152 * Returns function config object for pattern <name>
153 * and starting at tree node <*pnode>.
154 *
155 * Tree nodes (config_node) are created as needed,
156 * tree root is stored into <*pnode>, and the created
157 * leaf (fn_config) for the given pattern is returned.
158 */
159static fn_config* get_fnc2(config_node* node, Char* name)
160{
161 config_node *new_sub, *n, *nprev;
162 int offset, len;
163
164 CLG_DEBUG(3, " get_fnc2(%p, '%s')\n", node, name);
165
166 if (name[0] == 0) {
167 if (!node->config) node->config = new_fnc();
168 return node->config;
169 }
170
171 if (is_wild(*name)) {
172 if (*name == '*') {
173 while(name[1] == '*') name++;
174 new_sub = node->wild_star;
175 }
176 else
177 new_sub = node->wild_char;
178
179 if (!new_sub) {
180 new_sub = new_config(name, 1);
181 if (*name == '*')
182 node->wild_star = new_sub;
183 else
184 node->wild_char = new_sub;
185 }
186
187 return get_fnc2( new_sub, name+1);
188 }
189
190 n = node->sub_node[ name[0]%NODE_DEGREE ];
191 nprev = 0;
192 len = 0;
193 while(n) {
194 for(len=0; name[len] == n->name[len]; len++);
195 if (len>0) break;
196 nprev = n;
197 n = n->next;
198 }
199
200 if (!n) {
201 len = 1;
202 while(name[len] && (!is_wild(name[len]))) len++;
203 new_sub = new_config(name, len);
204 new_sub->next = node->sub_node[ name[0]%NODE_DEGREE ];
205 node->sub_node[ name[0]%NODE_DEGREE ] = new_sub;
206
207 if (name[len] == 0) {
208 new_sub->config = new_fnc();
209 return new_sub->config;
210 }
211
212 /* recurse on wildcard */
213 return get_fnc2( new_sub, name+len);
214 }
215
216 if (len < n->length) {
217
218 /* split up the subnode <n> */
219 config_node *new_node;
220 int i;
221
222 new_node = new_config(n->name, len);
223 if (nprev)
224 nprev->next = new_node;
225 else
226 node->sub_node[ n->name[0]%NODE_DEGREE ] = new_node;
227 new_node->next = n->next;
228
229 new_node->sub_node[ n->name[len]%NODE_DEGREE ] = n;
230
231 for(i=0, offset=len; offset < n->length; i++, offset++)
232 n->name[i] = n->name[offset];
233 n->name[i] = 0;
234 n->length = i;
235
236 name += len;
237 offset = 0;
238 while(name[offset] && (!is_wild(name[offset]))) offset++;
239 new_sub = new_config(name, offset);
240 /* this sub_node of new_node could already be set: chain! */
241 new_sub->next = new_node->sub_node[ name[0]%NODE_DEGREE ];
242 new_node->sub_node[ name[0]%NODE_DEGREE ] = new_sub;
243
244 if (name[offset]==0) {
245 new_sub->config = new_fnc();
246 return new_sub->config;
247 }
248
249 /* recurse on wildcard */
250 return get_fnc2( new_sub, name+offset);
251 }
252
253 name += n->length;
254
255 if (name[0] == 0) {
256 /* name and node name are the same */
257 if (!n->config) n->config = new_fnc();
258 return n->config;
259 }
260
261 offset = 1;
262 while(name[offset] && (!is_wild(name[offset]))) offset++;
263
264 new_sub = new_config(name, offset);
265 new_sub->next = n->sub_node[ name[offset]%NODE_DEGREE ];
266 n->sub_node[ name[offset]%NODE_DEGREE ] = new_sub;
267
268 return get_fnc2(new_sub, name+offset);
269}
270
271static void print_config_node(int s, config_node* node)
272{
273 config_node* n;
274 int i;
275
276 if (node != fn_configs) {
277 char sp[] = " ";
278
279 if (s>40) s=40;
280 VG_(printf)(sp+40-s);
281 VG_(printf)("'%s'/%d\n", node->name, node->length);
282 }
283 for(i=0;i<NODE_DEGREE;i++) {
284 n = node->sub_node[i];
285 while(n) {
286 print_config_node(s+1, n);
287 n = n->next;
288 }
289 }
290 if (node->wild_char) print_config_node(s+1, node->wild_char);
291 if (node->wild_star) print_config_node(s+1, node->wild_star);
292}
293
294/* get a function config for a name pattern (from command line) */
295static fn_config* get_fnc(Char* name)
296{
297 fn_config* fnc;
298
299 CLG_DEBUG(3, " +get_fnc(%s)\n", name);
300 if (fn_configs == 0)
301 fn_configs = new_config(name, 0);
302 fnc = get_fnc2(fn_configs, name);
303
304 CLG_DEBUGIF(3) {
305 CLG_DEBUG(3, " -get_fnc(%s):\n", name);
306 print_config_node(3, fn_configs);
307 }
308 return fnc;
309}
310
311
312
313static void update_fn_config1(fn_node* fn, fn_config* fnc)
314{
315 if (fnc->dump_before != CONFIG_DEFAULT)
316 fn->dump_before = (fnc->dump_before == CONFIG_TRUE);
317
318 if (fnc->dump_after != CONFIG_DEFAULT)
319 fn->dump_after = (fnc->dump_after == CONFIG_TRUE);
320
321 if (fnc->zero_before != CONFIG_DEFAULT)
322 fn->zero_before = (fnc->zero_before == CONFIG_TRUE);
323
324 if (fnc->toggle_collect != CONFIG_DEFAULT)
325 fn->toggle_collect = (fnc->toggle_collect == CONFIG_TRUE);
326
327 if (fnc->skip != CONFIG_DEFAULT)
328 fn->skip = (fnc->skip == CONFIG_TRUE);
329
330 if (fnc->pop_on_jump != CONFIG_DEFAULT)
331 fn->pop_on_jump = (fnc->pop_on_jump == CONFIG_TRUE);
332
333 if (fnc->group != CONFIG_DEFAULT)
334 fn->group = fnc->group;
335
336 if (fnc->separate_callers != CONFIG_DEFAULT)
337 fn->separate_callers = fnc->separate_callers;
338
339 if (fnc->separate_recursions != CONFIG_DEFAULT)
340 fn->separate_recursions = fnc->separate_recursions;
341
342#if CLG_ENABLE_DEBUG
343 if (fnc->verbosity != CONFIG_DEFAULT)
344 fn->verbosity = fnc->verbosity;
345#endif
346}
347
348/* Recursively go down the function matching tree,
349 * looking for a match to <name>. For every matching leaf,
350 * <fn> is updated with the pattern config.
351 */
352static void update_fn_config2(fn_node* fn, Char* name, config_node* node)
353{
354 config_node* n;
355
356 CLG_DEBUG(3, " update_fn_config2('%s', node '%s'): \n",
357 name, node->name);
358 if ((*name == 0) && node->config) {
359 CLG_DEBUG(3, "Found!\n");
360 update_fn_config1(fn, node->config);
361 return;
362 }
363
364 n = node->sub_node[ name[0]%NODE_DEGREE ];
365 while(n) {
366 if (VG_(strncmp)(name, n->name, n->length)==0) break;
367 n = n->next;
368 }
369 if (n) update_fn_config2(fn, name+n->length, n);
370
371 if (node->wild_char)
372 update_fn_config2(fn, name+1, node->wild_char);
373
374 if (node->wild_star) {
375 while(*name) {
376 update_fn_config2(fn, name, node->wild_star);
377 name++;
378 }
379 update_fn_config2(fn, name, node->wild_star);
380 }
381}
382
383/* Update function config according to configs of name prefixes */
384void CLG_(update_fn_config)(fn_node* fn)
385{
386 CLG_DEBUG(3, " update_fn_config('%s')\n", fn->name);
387 if (fn_configs)
388 update_fn_config2(fn, fn->name, fn_configs);
389}
390
391
392/*--------------------------------------------------------------------*/
393/*--- Command line processing ---*/
394/*--------------------------------------------------------------------*/
395
396static Char* getUInt(Char* s, UInt* pn)
397{
398 UInt n = 0;
399 while((*s >='0') && (*s <='9')) {
400 n = 10*n + (*s-'0');
401 s++;
402 }
403 if (pn) *pn = n;
404 return s;
405}
406
407__attribute__((unused))
408static UWord getUWord(Char* s)
409{
410 UWord n = 0;
411 Bool isHex = False;
412
413 if ((s[0] == '0') && (s[1] == 'x')) {
414 isHex = True;
415 s += 2;
416 }
417
418 if (!isHex) {
419 while((*s >='0') && (*s <='9')) {
420 n = 10*n + (*s-'0');
421 s++;
422 }
423 }
424 else {
425 while(1) {
426 if ((*s >='0') && (*s <='9')) {
427 n = 16*n + (*s-'0');
428 s++;
429 continue;
430 }
431 if ((*s >='a') && (*s <='f')) {
432 n = 16*n + (*s-'a'+10);
433 s++;
434 continue;
435 }
436 if ((*s >='A') && (*s <='F')) {
437 n = 16*n + (*s-'A'+10);
438 s++;
439 continue;
440 }
441 break;
442 }
443 }
444
445 return n;
446}
447
448Bool CLG_(process_cmd_line_option)(Char* arg)
449{
450 if (0 == VG_(strcmp)(arg, "--skip-plt=yes"))
451 CLG_(clo).skip_plt = True;
452 else if (0 == VG_(strcmp)(arg, "--skip-plt=no"))
453 CLG_(clo).skip_plt = False;
454
455 else if (0 == VG_(strcmp)(arg, "--collect-jumps=yes"))
456 CLG_(clo).collect_jumps = True;
457 else if (0 == VG_(strcmp)(arg, "--collect-jumps=no"))
458 CLG_(clo).collect_jumps = False;
459 /* compatibility alias, deprecated option */
460 else if (0 == VG_(strcmp)(arg, "--trace-jump=yes"))
461 CLG_(clo).collect_jumps = True;
462 else if (0 == VG_(strcmp)(arg, "--trace-jump=no"))
463 CLG_(clo).collect_jumps = False;
464
465 else if (0 == VG_(strcmp)(arg, "--combine-dumps=yes"))
466 CLG_(clo).combine_dumps = True;
467 else if (0 == VG_(strcmp)(arg, "--combine-dumps=no"))
468 CLG_(clo).combine_dumps = False;
469
470 else if (0 == VG_(strcmp)(arg, "--collect-atstart=yes"))
471 CLG_(clo).collect_atstart = True;
472 else if (0 == VG_(strcmp)(arg, "--collect-atstart=no"))
473 CLG_(clo).collect_atstart = False;
474
475 else if (0 == VG_(strcmp)(arg, "--instr-atstart=yes"))
476 CLG_(clo).instrument_atstart = True;
477 else if (0 == VG_(strcmp)(arg, "--instr-atstart=no"))
478 CLG_(clo).instrument_atstart = False;
479
480 else if (0 == VG_(strcmp)(arg, "--separate-threads=yes"))
481 CLG_(clo).separate_threads = True;
482 else if (0 == VG_(strcmp)(arg, "--separate-threads=no"))
483 CLG_(clo).separate_threads = False;
484
485 else if (0 == VG_(strcmp)(arg, "--compress-strings=yes"))
486 CLG_(clo).compress_strings = True;
487 else if (0 == VG_(strcmp)(arg, "--compress-strings=no"))
488 CLG_(clo).compress_strings = False;
489
490 else if (0 == VG_(strcmp)(arg, "--compress-mangled=yes"))
491 CLG_(clo).compress_mangled = True;
492 else if (0 == VG_(strcmp)(arg, "--compress-mangled=no"))
493 CLG_(clo).compress_mangled = False;
494
495 else if (0 == VG_(strcmp)(arg, "--compress-pos=yes"))
496 CLG_(clo).compress_pos = True;
497 else if (0 == VG_(strcmp)(arg, "--compress-pos=no"))
498 CLG_(clo).compress_pos = False;
499
500 else if (0 == VG_(strncmp)(arg, "--fn-skip=", 10)) {
501 fn_config* fnc = get_fnc(arg+10);
502 fnc->skip = CONFIG_TRUE;
503 }
504
505 else if (0 == VG_(strncmp)(arg, "--dump-before=", 14)) {
506 fn_config* fnc = get_fnc(arg+14);
507 fnc->dump_before = CONFIG_TRUE;
508 }
509
510 else if (0 == VG_(strncmp)(arg, "--zero-before=", 14)) {
511 fn_config* fnc = get_fnc(arg+14);
512 fnc->zero_before = CONFIG_TRUE;
513 }
514
515 else if (0 == VG_(strncmp)(arg, "--dump-after=", 13)) {
516 fn_config* fnc = get_fnc(arg+13);
517 fnc->dump_after = CONFIG_TRUE;
518 }
519
520 else if (0 == VG_(strncmp)(arg, "--toggle-collect=", 17)) {
521 fn_config* fnc = get_fnc(arg+17);
522 fnc->toggle_collect = CONFIG_TRUE;
523 /* defaults to initial collection off */
524 CLG_(clo).collect_atstart = False;
525 }
526
527 else if (0 == VG_(strncmp)(arg, "--separate-recs=", 16))
528 CLG_(clo).separate_recursions = (Int)VG_(atoll)(&arg[16]);
529
weidendoa762b0f2006-05-01 00:55:54 +0000530 /* change handling of a jump between functions to ret+call */
531 else if (0 == VG_(strcmp)(arg, "--pop-on-jump")) {
532 CLG_(clo).pop_on_jump = True;
533 }
weidendoa17f2a32006-03-20 10:27:30 +0000534 else if (0 == VG_(strncmp)(arg, "--pop-on-jump=", 14)) {
535 fn_config* fnc = get_fnc(arg+14);
536 fnc->pop_on_jump = CONFIG_TRUE;
537 }
538
539#if CLG_ENABLE_DEBUG
540 else if (0 == VG_(strncmp)(arg, "--ct-verbose=", 13))
541 CLG_(clo).verbose = (Int)VG_(atoll)(&arg[13]);
542
543 else if (0 == VG_(strncmp)(arg, "--ct-vstart=", 12))
544 CLG_(clo).verbose_start = (ULong)VG_(atoll)(&arg[12]);
545
546 else if (0 == VG_(strncmp)(arg, "--ct-verbose", 12)) {
547 UInt n;
548 fn_config* fnc;
549 Char* s = getUInt(arg+12, &n);
550 if ((n == 0) || *s != '=') return False;
551 fnc = get_fnc(s+1);
552 fnc->verbosity = n;
553 }
554#endif
555
556 else if (0 == VG_(strncmp)(arg, "--separate-callers=", 19)) {
557 if (0 == VG_(strcmp)(arg+19, "auto"))
558 CLG_(clo).separate_callers = CONFIG_AUTO;
559 else
560 CLG_(clo).separate_callers = (Int)VG_(atoll)(&arg[19]);
561 }
562
563 else if (0 == VG_(strncmp)(arg, "--fn-group", 10)) {
564 UInt n;
565 fn_config* fnc;
566 Char* s = getUInt(arg+10, &n);
567 if ((n == 0) || *s != '=') return False;
568 fnc = get_fnc(s+1);
569 fnc->group = n;
570 }
571
572 else if (0 == VG_(strncmp)(arg, "--separate-callers", 18)) {
573 UInt n;
574 fn_config* fnc;
575 Char* s = getUInt(arg+18, &n);
576 if ((n == 0) || *s != '=') return False;
577 fnc = get_fnc(s+1);
578 fnc->separate_callers = n;
579 }
580
581 else if (0 == VG_(strncmp)(arg, "--separate-recs", 15)) {
582 UInt n;
583 fn_config* fnc;
584 Char* s = getUInt(arg+15, &n);
585 if ((n == 0) || *s != '=') return False;
586 fnc = get_fnc(s+1);
587 fnc->separate_recursions = n;
588 }
589
590 else if (0 == VG_(strncmp)(arg, "--base=", 7))
591 CLG_(clo).filename_base = VG_(strdup)(arg+7);
592
593 else if (0 == VG_(strcmp)(arg, "--mangle-names=yes"))
594 CLG_(clo).mangle_names = True;
595 else if (0 == VG_(strcmp)(arg, "--mangle-names=no"))
596 CLG_(clo).mangle_names = False;
597
598 else if (0 == VG_(strcmp)(arg, "--skip-direct-rec=yes"))
599 CLG_(clo).skip_direct_recursion = True;
600 else if (0 == VG_(strcmp)(arg, "--skip-direct-rec=no"))
601 CLG_(clo).skip_direct_recursion = False;
602
603 else if (0 == VG_(strcmp)(arg, "--dump-bbs=yes"))
604 CLG_(clo).dump_bbs = True;
605 else if (0 == VG_(strcmp)(arg, "--dump-bbs=no"))
606 CLG_(clo).dump_bbs = False;
607
608 else if (0 == VG_(strcmp)(arg, "--dump-line=yes"))
609 CLG_(clo).dump_line = True;
610 else if (0 == VG_(strcmp)(arg, "--dump-line=no"))
611 CLG_(clo).dump_line = False;
612
613 else if (0 == VG_(strcmp)(arg, "--dump-instr=yes"))
614 CLG_(clo).dump_instr = True;
615 else if (0 == VG_(strcmp)(arg, "--dump-instr=no"))
616 CLG_(clo).dump_instr = False;
617
618 else if (0 == VG_(strcmp)(arg, "--dump-bb=yes"))
619 CLG_(clo).dump_bb = True;
620 else if (0 == VG_(strcmp)(arg, "--dump-bb=no"))
621 CLG_(clo).dump_bb = False;
622
623 else if (0 == VG_(strncmp)(arg, "--dump-every-bb=", 16))
weidendo9e326b72006-03-31 13:16:15 +0000624 CLG_(clo).dump_every_bb = (ULong)VG_(atoll)(&arg[16]);
weidendoa17f2a32006-03-20 10:27:30 +0000625
626
627 else if (0 == VG_(strcmp)(arg, "--collect-alloc=yes"))
628 CLG_(clo).collect_alloc = True;
629 else if (0 == VG_(strcmp)(arg, "--collect-alloc=no"))
630 CLG_(clo).collect_alloc = False;
631
632 else if (0 == VG_(strcmp)(arg, "--collect-systime=yes"))
633 CLG_(clo).collect_systime = True;
634 else if (0 == VG_(strcmp)(arg, "--collect-systime=no"))
635 CLG_(clo).collect_systime = False;
636
637 else if (0 == VG_(strcmp)(arg, "--simulate-cache=yes"))
638 CLG_(clo).simulate_cache = True;
639 else if (0 == VG_(strcmp)(arg, "--simulate-cache=no"))
640 CLG_(clo).simulate_cache = False;
641
642 else {
643 Bool isCachesimOption = (*CLG_(cachesim).parse_opt)(arg);
644
645 /* cache simulator is used if a simulator option is given */
646 if (isCachesimOption)
647 CLG_(clo).simulate_cache = True;
648
649 return isCachesimOption;
650 }
651
652 return True;
653}
654
655void CLG_(print_usage)(void)
656{
657 VG_(printf)(
658"\n dump creation options:\n"
659" --base=<prefix> Prefix for profile files [" DEFAULT_DUMPNAME "]\n"
660" --dump-line=no|yes Dump source lines of costs? [yes]\n"
661" --dump-instr=no|yes Dump instruction address of costs? [no]\n"
662" --compress-strings=no|yes Compress strings in profile dump? [yes]\n"
663" --compress-pos=no|yes Compress positions in profile dump? [yes]\n"
664" --combine-dumps=no|yes Concat all dumps into same file [no]\n"
665#if CLG_EXPERIMENTAL
666" --compress-events=no|yes Compress events in profile dump? [no]\n"
667" --dump-bb=no|yes Dump basic block address of costs? [no]\n"
668" --dump-bbs=no|yes Dump basic block info? [no]\n"
669" --dump-skipped=no|yes Dump info on skipped functions in calls? [no]\n"
670" --mangle-names=no|yes Mangle separation into names? [yes]\n"
671#endif
672
673"\n activity options (for interactivity use callgrind_control):\n"
674" --dump-every-bb=<count> Dump every <count> basic blocks [0=never]\n"
675" --dump-before=<func> Dump when entering function\n"
676" --zero-before=<func> Zero all costs when entering function\n"
677" --dump-after=<func> Dump when leaving function\n"
678#if CLG_EXPERIMENTAL
679" --dump-objs=no|yes Dump static object information [no]\n"
680#endif
681
682"\n data collection options:\n"
683" --instr-atstart=no|yes Do instrumentation at callgrind start [yes]\n"
684" --collect-atstart=no|yes Collect at process/thread start [yes]\n"
685" --toggle-collect=<func> Toggle collection on enter/leave function\n"
686" --collect-jumps=no|yes Collect jumps? [no]\n"
687#if CLG_EXPERIMENTAL
688" --collect-alloc=no|yes Collect memory allocation info? [no]\n"
689#endif
690" --collect-systime=no|yes Collect system call time info? [no]\n"
691
692"\n cost entity separation options:\n"
693" --separate-threads=no|yes Separate data per thread [no]\n"
694" --separate-callers=<n> Separate functions by call chain length [0]\n"
695" --separate-recs=<n> Separate function recursions upto level [2]\n"
696" --skip-plt=no|yes Ignore calls to/from PLT sections? [yes]\n"
697" --separate-recs<n>=<f> Separate <n> recursions for function <f>\n"
698" --separate-callers<n>=<f> Separate <n> callers for function <f>\n"
699" --skip-direct-rec=no|yes Ignore direct recursions? [yes]\n"
700" --fn-skip=<function> Ignore calls to/from function?\n"
701#if CLG_EXPERIMENTAL
702" --fn-group<no>=<func> Put function into separation group <no>\n"
703#endif
704 );
705
706 (*CLG_(cachesim).print_opts)();
707
708// VG_(printf)("\n"
709// " For full callgrind documentation, see\n"
710// " "VG_PREFIX"/share/doc/callgrind/html/callgrind.html\n\n");
711}
712
713void CLG_(print_debug_usage)(void)
714{
715 VG_(printf)(
716
717#if CLG_ENABLE_DEBUG
718" --ct-verbose=<level> Verbosity of standard debug output [0]\n"
719" --ct-vstart=<BB number> Only be verbose after basic block [0]\n"
720" --ct-verbose<level>=<func> Verbosity while in <func>\n"
721#else
722" (none)\n"
723#endif
724
725 );
726}
727
728
729void CLG_(set_clo_defaults)(void)
730{
731 /* Default values for command line arguments */
732
733 /* dump options */
734 CLG_(clo).filename_base = 0;
735 CLG_(clo).combine_dumps = False;
736 CLG_(clo).compress_strings = True;
737 CLG_(clo).compress_mangled = False;
738 CLG_(clo).compress_events = False;
739 CLG_(clo).compress_pos = True;
740 CLG_(clo).mangle_names = True;
741 CLG_(clo).dump_line = True;
742 CLG_(clo).dump_instr = False;
743 CLG_(clo).dump_bb = False;
744 CLG_(clo).dump_bbs = False;
745
746 CLG_(clo).dump_every_bb = 0;
747
748 /* Collection */
749 CLG_(clo).separate_threads = False;
750 CLG_(clo).collect_atstart = True;
751 CLG_(clo).collect_jumps = False;
752 CLG_(clo).collect_alloc = False;
753 CLG_(clo).collect_systime = False;
754
755 CLG_(clo).skip_plt = True;
756 CLG_(clo).separate_callers = 0;
757 CLG_(clo).separate_recursions = 2;
758 CLG_(clo).skip_direct_recursion = False;
759
760 /* Instrumentation */
761 CLG_(clo).instrument_atstart = True;
762 CLG_(clo).simulate_cache = False;
763
weidendoa762b0f2006-05-01 00:55:54 +0000764 /* Call graph */
765 CLG_(clo).pop_on_jump = False;
766
weidendoa17f2a32006-03-20 10:27:30 +0000767#if CLG_ENABLE_DEBUG
768 CLG_(clo).verbose = 0;
769 CLG_(clo).verbose_start = 0;
770#endif
771}