|
diff --git a/callgrind/callstack.c b/callgrind/callstack.c |
|
index fc1d6eeab..acc7c5542 100644 |
|
--- a/callgrind/callstack.c |
|
+++ b/callgrind/callstack.c |
|
@@ -174,6 +174,135 @@ static void function_left(fn_node* fn) |
|
} |
|
|
|
|
|
+/* Returns uhhhh the same pointer to the fn_buf. If no fn_buf (or it is "???") -- `fallback_fn_name` |
|
+ See debug.c, `CLG_(print_addr)` for the reference |
|
+*/ |
|
+static HChar* CLG_(get_fn_buf_name)(HChar* fn_buf) { |
|
+ const HChar* fallback_fn_name = "???"; |
|
+ if (!fn_buf || VG_(strcmp)(fn_buf,"???") == 0) { |
|
+ return fallback_fn_name; |
|
+ } |
|
+ return fn_buf; |
|
+} |
|
+ |
|
+ |
|
+/* Returns shifted pointer to the same allocated string. If no module name -- `fallback_obj_name` |
|
+ See debug.c, `CLG_(print_addr)` for the reference |
|
+*/ |
|
+static HChar* CLG_(get_di_obj_name)(DebugInfo *di) { |
|
+ const HChar* fallback_obj_name = "???"; |
|
+ UInt i=0, opos=0; |
|
+ |
|
+ if (UNLIKELY(!di)) { |
|
+ return fallback_obj_name; |
|
+ } |
|
+ |
|
+ const HChar* obj_name = VG_(DebugInfo_get_filename)(di); |
|
+ if (obj_name) { |
|
+ while(obj_name[i]) { |
|
+ if (obj_name[i]=='/') { |
|
+ opos = i+1; |
|
+ } |
|
+ i++; |
|
+ } |
|
+ |
|
+ obj_name += opos; |
|
+ return (obj_name[0]) ? obj_name : fallback_obj_name; |
|
+ } |
|
+ |
|
+ return fallback_obj_name; |
|
+} |
|
+ |
|
+ |
|
+/* Prints source mapped code line |
|
+ See debug.c, `CLG_(print_addr)` for the reference |
|
+*/ |
|
+static void CLG_(print_fl_buf_source_line)(UInt di_ln, const HChar* dir_buf, const HChar* fl_buf) { |
|
+ if (di_ln>0) { |
|
+ if (dir_buf[0]) { |
|
+ VG_(printf)("(%s/%s:%u)", dir_buf, fl_buf, di_ln);} |
|
+ else { |
|
+ VG_(printf)("(%s:%u)", fl_buf, di_ln); |
|
+ } |
|
+ } else { |
|
+ VG_(printf)("(???)"); |
|
+ } |
|
+} |
|
+ |
|
+ |
|
+static void CLG_(print_verbose_1_patch)(jCC* jcc, Bool with_jmpaddr) { |
|
+ const HChar *fn_buf, *fl_buf, *dir_buf; |
|
+ const HChar *fn_name, *obj_name; |
|
+ DebugInfo* di; |
|
+ UInt di_ln; |
|
+ Addr addr, jmpaddr; |
|
+ Bool is_blacklisted = False; |
|
+ |
|
+ if (jcc && jcc->to && jcc->to->bb) { |
|
+ // Do not print or even process if there is no jcc |
|
+ |
|
+ addr = bb_addr(jcc->to->bb); |
|
+ jmpaddr = bb_jmpaddr(jcc->from->bb); // TODO: may be bb_addr(jcc->from-bb) useful? |
|
+ |
|
+ if (addr != 0) { |
|
+ CLG_(get_debug_info)(addr, &dir_buf, &fl_buf, &fn_buf, &di_ln, &di); |
|
+ |
|
+ fn_name = CLG_(get_fn_buf_name)(fn_buf); |
|
+ obj_name = CLG_(get_di_obj_name)(di); |
|
+ |
|
+ for (SizeT i = 0; i < VG_(sizeXA)(CLG_(clo).suppress_module) && !is_blacklisted; i++) { |
|
+ const HChar *module = *(HChar**)VG_(indexXA)(CLG_(clo).suppress_module, i); |
|
+ if (VG_(strncmp)(module, obj_name, 1024) == 0) { |
|
+ // VG_(printf)("[B] %s blacklisted by %s\n", obj_name, module); |
|
+ is_blacklisted = True; |
|
+ break; |
|
+ } |
|
+ } |
|
+ for (SizeT i = 0; i < VG_(sizeXA)(CLG_(clo).suppress_function) && !is_blacklisted; i++) { |
|
+ const HChar *function = *(HChar**)VG_(indexXA)(CLG_(clo).suppress_function, i); |
|
+ if (VG_(strncmp)(function, fn_name, 1024) == 0) { |
|
+ // VG_(printf)("[B] %s blacklisted by %s\n", obj_name, function); |
|
+ is_blacklisted = True; |
|
+ break; |
|
+ } |
|
+ } |
|
+ } |
|
+ |
|
+ if (!is_blacklisted) { |
|
+ if (with_jmpaddr) { |
|
+ VG_(printf)("- %2d ", CLG_(current_call_stack).sp + 1); |
|
+ } |
|
+ else { |
|
+ VG_(printf)("+ %2d ", CLG_(current_call_stack).sp); |
|
+ } |
|
+ |
|
+ VG_(printf)("%016llx ", addr); |
|
+ |
|
+ if (addr != 0) { |
|
+ VG_(printf)("[%s] %s ", obj_name, fn_name); |
|
+ |
|
+ if (with_jmpaddr) { |
|
+ if (jmpaddr != 0) { |
|
+ CLG_(get_debug_info)(jmpaddr, &dir_buf, &fl_buf, &fn_buf, &di_ln, &di); |
|
+ CLG_(print_fl_buf_source_line)(di_ln, dir_buf, fl_buf); |
|
+ } else { |
|
+ VG_(printf)("(???)"); |
|
+ } |
|
+ } |
|
+ else { |
|
+ CLG_(print_fl_buf_source_line)(di_ln, dir_buf, fl_buf); |
|
+ } |
|
+ } |
|
+ else { |
|
+ VG_(printf)("NO_DI"); |
|
+ } |
|
+ |
|
+ VG_(printf)("\n"); |
|
+ } |
|
+ } |
|
+} |
|
+ |
|
+ |
|
/* Push call on call stack. |
|
* |
|
* Increment the usage count for the function called. |
|
@@ -270,24 +399,7 @@ void CLG_(push_call_stack)(BBCC* from, UInt jmp, BBCC* to, Addr sp, Bool skip) |
|
#if CLG_ENABLE_DEBUG |
|
CLG_DEBUGIF(0) { |
|
if (CLG_(clo).verbose<2) { |
|
- if (jcc && jcc->to && jcc->to->bb) { |
|
- const HChar spaces[][41] = { |
|
- " . . . . . . . . . .", |
|
- " . . . . . . . . . . ", |
|
- " . . . . . . . . . . ", |
|
- ". . . . . . . . . . " }; |
|
- |
|
- int s = CLG_(current_call_stack).sp; |
|
- UInt* pars = (UInt*) sp; |
|
- |
|
- BB* bb = jcc->to->bb; |
|
- if (s>40) s=40; |
|
- VG_(printf)("%s> %s(0x%x, 0x%x, ...) [%s / %#lx]\n", spaces[s%4]+40-s, bb->fn->name, |
|
- pars ? pars[1]:0, |
|
- pars ? pars[2]:0, |
|
- bb->obj->name + bb->obj->last_slash_pos, |
|
- (UWord)bb->offset); |
|
- } |
|
+ CLG_(print_verbose_1_patch)(jcc, False); |
|
} |
|
else if (CLG_(clo).verbose<4) { |
|
VG_(printf)("+ %2d ", CLG_(current_call_stack).sp); |
|
@@ -368,8 +480,11 @@ void CLG_(pop_call_stack)(void) |
|
CLG_(current_call_stack).sp--; |
|
|
|
#if CLG_ENABLE_DEBUG |
|
- CLG_DEBUGIF(1) { |
|
- if (CLG_(clo).verbose<4) { |
|
+ CLG_DEBUGIF(0) { |
|
+ if (CLG_(clo).verbose<2) { |
|
+ CLG_(print_verbose_1_patch)(jcc, True); |
|
+ } |
|
+ else if (CLG_(clo).verbose<4) { |
|
if (jcc) { |
|
/* popped JCC target first */ |
|
VG_(printf)("- %2d %#lx => ", |
|
diff --git a/callgrind/clo.c b/callgrind/clo.c |
|
index ce15fc832..7781bf2fd 100644 |
|
--- a/callgrind/clo.c |
|
+++ b/callgrind/clo.c |
|
@@ -399,6 +399,38 @@ void CLG_(update_fn_config)(fn_node* fn) |
|
update_fn_config2(fn, fn->name, fn_configs); |
|
} |
|
|
|
+/* String split into XArray */ |
|
+static void CLG_(string_split_to_xarray)(const HChar *orig_str, HChar delim, XArray *out_array) { |
|
+ SizeT j = 0; |
|
+ SizeT i = 0; |
|
+ for (i = 0; i < 16 * 1024 * 1024 && orig_str[i] != '\0'; ++i) { |
|
+ HChar c = orig_str[i]; |
|
+ if (c == delim) { |
|
+ if (i > j) { |
|
+ HChar* new_str = VG_(malloc)("ct_verbose_suppress_module", i - j + 1); |
|
+ VG_(strncpy)(new_str, orig_str + j, i - j); |
|
+ new_str[i-j] = 0; |
|
+ VG_(addToXA)(out_array, (void*)&new_str); |
|
+ } |
|
+ // Do not capture empty string |
|
+ |
|
+ j = i+1; |
|
+ } |
|
+ } |
|
+ if (i > j) { |
|
+ HChar* new_str = VG_(malloc)("ct_verbose_suppress_module", i - j + 1); |
|
+ VG_(strncpy)(new_str, orig_str + j, i - j); |
|
+ new_str[i-j] = 0; |
|
+ VG_(printf)("before addToXA2: (%d) %s\n", i-j, new_str); |
|
+ |
|
+ VG_(addToXA)(out_array, (void*)&new_str); |
|
+ } |
|
+ |
|
+ // for (SizeT i = 0; i < VG_(sizeXA)(out_array); i++) { |
|
+ // VG_(printf)("Suppressed modules: %s\n", VG_(indexXA)(out_array, i)); |
|
+ // } |
|
+} |
|
+ |
|
|
|
/*--------------------------------------------------------------------*/ |
|
/*--- Command line processing ---*/ |
|
@@ -466,6 +498,21 @@ Bool CLG_(process_cmd_line_option)(const HChar* arg) |
|
else if VG_INT_CLO(arg, "--ct-verbose", CLG_(clo).verbose) {} |
|
else if VG_INT_CLO(arg, "--ct-vstart", CLG_(clo).verbose_start) {} |
|
|
|
+ else if VG_STR_CLO(arg, "--ct-verbose-suppress-module", tmp_str) { |
|
+ CLG_(string_split_to_xarray)(tmp_str, ':', CLG_(clo).suppress_module); |
|
+ |
|
+ for (SizeT i = 0; i < VG_(sizeXA)(CLG_(clo).suppress_module); i++) { |
|
+ VG_(printf)("Suppressed modules: %s\n", *(HChar**)VG_(indexXA)(CLG_(clo).suppress_module, i)); |
|
+ } |
|
+ } |
|
+ else if VG_STR_CLO(arg, "--ct-verbose-suppress-function", tmp_str) { |
|
+ CLG_(string_split_to_xarray)(tmp_str, ':', CLG_(clo).suppress_function); |
|
+ |
|
+ for (SizeT i = 0; i < VG_(sizeXA)(CLG_(clo).suppress_function); i++) { |
|
+ VG_(printf)("Suppressed functions: %s\n", *(HChar**)VG_(indexXA)(CLG_(clo).suppress_function, i)); |
|
+ } |
|
+ } |
|
+ |
|
else if VG_STREQN(12, arg, "--ct-verbose") { |
|
fn_config* fnc; |
|
HChar* s; |
|
@@ -634,6 +681,8 @@ void CLG_(print_debug_usage)(void) |
|
" --ct-verbose=<level> Verbosity of standard debug output [0]\n" |
|
" --ct-vstart=<BB number> Only be verbose after basic block [0]\n" |
|
" --ct-verbose<level>=<func> Verbosity while in <func>\n" |
|
+" --ct-verbose-suppress-module=<modules> Suppress output for modules (separated by colon string)\n" |
|
+" --ct-verbose-suppress-function=<functions> Suppress output for functions (separated by colon string)\n" |
|
#else |
|
" (none)\n" |
|
#endif |
|
@@ -685,5 +734,9 @@ void CLG_(set_clo_defaults)(void) |
|
#if CLG_ENABLE_DEBUG |
|
CLG_(clo).verbose = 0; |
|
CLG_(clo).verbose_start = 0; |
|
+ CLG_(clo).suppress_function = VG_(newXA)(VG_(malloc), "CLG(set_clo_defaults).sf", |
|
+ VG_(free), sizeof(HChar *)); |
|
+ CLG_(clo).suppress_module= VG_(newXA)(VG_(malloc), "CLG(set_clo_defaults).sm", |
|
+ VG_(free), sizeof(HChar *)); |
|
#endif |
|
} |
|
diff --git a/callgrind/global.h b/callgrind/global.h |
|
index 4a988a481..4207e865c 100644 |
|
--- a/callgrind/global.h |
|
+++ b/callgrind/global.h |
|
@@ -123,6 +123,8 @@ struct _CommandLineOptions { |
|
#if CLG_ENABLE_DEBUG |
|
Int verbose; |
|
ULong verbose_start; |
|
+ XArray *suppress_module; // array of string |
|
+ XArray *suppress_function; // array of string |
|
#endif |
|
}; |
|
|