Skip to content

Instantly share code, notes, and snippets.

@Toliak
Last active March 4, 2025 10:13
Show Gist options
  • Select an option

  • Save Toliak/b4d5422dd7d436ded4ae321ce1e73814 to your computer and use it in GitHub Desktop.

Select an option

Save Toliak/b4d5422dd7d436ded4ae321ce1e73814 to your computer and use it in GitHub Desktop.

Revisions

  1. Toliak revised this gist Mar 4, 2025. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    # Description

    Patch for Valgrind commit `2d09ef48e2`.
    Also works on tag `VALGRIND_3_24_0`

    Provides logs for callgrind in the format:
    - Function entering
    ```
  2. Toliak revised this gist Mar 4, 2025. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -153,4 +153,5 @@ The log output (cut):
    - 6 000000000010924e [app] f2 (/my-project-directory/main.c:34)
    - 5 0000000000109234 [app] f1 (/my-project-directory/main.c:93)
    + 6 00000000048d0e00 [libc.so.6] printf (/usr/src/debug/glibc/glibc/stdio-common/printf.c:28)
    ```
    ```
  3. Toliak revised this gist Mar 2, 2025. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ Provides logs for callgrind in the format:
    ```
    - Function exiting
    ```
    - <Stack position (before exit)> [<Module name>] <Function name> (<source line the exit will return to, if debug symbols provided>)
    - <Stack position (before exit)> [<Module name>] <Function name> (<source line the function will return to, if debug symbols provided>)
    ```

    Also provides two arguments: `--ct-verbose-suppress-module` and `--ct-verbose-suppress-function`.
    @@ -21,6 +21,7 @@ Consider C code:

    <details>
    <summary>main.c</summary>

    ```c
    #include <stdio.h>
    #include <stdlib.h>
    @@ -117,6 +118,7 @@ int main(int argc, char** argv) {
    printf("Result: %d\n", f1(a));
    }
    ```
    </details>
    Command to build the code above:
  4. Toliak revised this gist Mar 2, 2025. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -17,9 +17,11 @@ Multiple module or function names should be separated by a colon.

    # Example

    Consider C++ code:
    Consider C code:

    ```
    <details>
    <summary>main.c</summary>
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    @@ -115,6 +117,7 @@ int main(int argc, char** argv) {
    printf("Result: %d\n", f1(a));
    }
    ```
    </details>
    Command to build the code above:
    ```
  5. Toliak revised this gist Mar 2, 2025. 1 changed file with 151 additions and 0 deletions.
    151 changes: 151 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,151 @@
    # Description

    Patch for Valgrind commit `2d09ef48e2`.
    Provides logs for callgrind in the format:
    - Function entering
    ```
    + <Stack position> [<Module name>] <Function name> (<source line of the beginning of the called function, if debug symbols provided>)
    ```
    - Function exiting
    ```
    - <Stack position (before exit)> [<Module name>] <Function name> (<source line the exit will return to, if debug symbols provided>)
    ```

    Also provides two arguments: `--ct-verbose-suppress-module` and `--ct-verbose-suppress-function`.
    The can be used to specify modules and functions for supress, respectively.
    Multiple module or function names should be separated by a colon.

    # Example

    Consider C++ code:

    ```
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    // Function declarations
    int f1(int v);
    int f2(int v);
    int f3(int v);
    int f4(int v);
    int f5(int v);
    int f6(int v);
    int f7(int v);
    int f8(int v);
    int f9(int v);
    int f10(int v);
    void file_check(void) {
    int fd = open("/dev/null", O_RDONLY);
    if (fd == -1) {
    perror("open");
    exit(1);
    }
    char buffer[1024];
    read(fd, buffer, sizeof(buffer));
    close(fd);
    }
    // Function definitions
    int f1(int v) {
    return f2(v + 1);
    }
    int f2(int v) {
    file_check();
    if (v > 10) {
    return (v - 5);
    }
    return f3(v * 2);
    }
    int f3(int v) {
    return f8(v + 3);
    }
    int f4(int v) {
    if (v < 0) {
    return (v + 10);
    }
    return f6(v - 2);
    }
    int f5(int v) {
    return f9(v / 2);
    }
    int f6(int v) {
    if (v % 2 == 0) {
    return (v + 1);
    }
    return f4(v - 1);
    }
    int f7(int v) {
    return f10(v * 3);
    }
    int f8(int v) {
    if (v > 20) {
    return (v - 10);
    }
    return f6(v + 5);
    }
    int f9(int v) {
    return f3(v - 4);
    }
    int f10(int v) {
    if (v == 0) {
    return 0; // Base case to stop recursion
    }
    return f2(v - 1);
    }
    int main(int argc, char** argv) {
    int a = 3;
    printf("Result: %d\n", f1(a));
    }
    ```

    Command to build the code above:
    ```
    gcc main.c -O0 -g -o build/app
    ```

    Command to run callgrind:
    ```
    $MY_VALGRIND_DIR/dist/bin/valgrind --tool=callgrind --ct-verbose=1 --ct-verbose-suppress-module="ld-linux-x86-64.so.2" --ct-verbose-suppress-function="__syscall_cancel:__internal_syscall_cancel" --log-file=./log.txt ./build/app
    ```

    The log output (cut):
    ```
    + 4 000000000010938e [app] main (/my-project-directory/main.c:91)
    + 5 0000000000109234 [app] f1 (/my-project-directory/main.c:33)
    + 6 000000000010924e [app] f2 (/my-project-directory/main.c:37)
    + 7 0000000000109199 [app] file_check (/my-project-directory/main.c:19)
    + 9 00000000049832d0 [libc.so.6] open (/usr/src/debug/glibc/glibc/io/../sysdeps/unix/sysv/linux/open64.c:30)
    - 9 00000000049832d0 [libc.so.6] open (/my-project-directory/main.c:20)
    + 9 0000000004983a20 [libc.so.6] read (/usr/src/debug/glibc/glibc/io/../sysdeps/unix/sysv/linux/read.c:25)
    - 9 0000000004983a20 [libc.so.6] read (/my-project-directory/main.c:27)
    + 9 000000000497ee60 [libc.so.6] close (/usr/src/debug/glibc/glibc/io/../sysdeps/unix/sysv/linux/close.c:26)
    - 9 000000000497ee60 [libc.so.6] close (/my-project-directory/main.c:29)
    - 7 0000000000109199 [app] file_check (/my-project-directory/main.c:38)
    + 7 000000000010927a [app] f3 (/my-project-directory/main.c:46)
    + 8 0000000000109325 [app] f8 (/my-project-directory/main.c:73)
    + 9 00000000001092dc [app] f6 (/my-project-directory/main.c:62)
    - 9 00000000001092dc [app] f6 (/my-project-directory/main.c:77)
    - 8 0000000000109325 [app] f8 (/my-project-directory/main.c:47)
    - 7 000000000010927a [app] f3 (/my-project-directory/main.c:43)
    - 6 000000000010924e [app] f2 (/my-project-directory/main.c:34)
    - 5 0000000000109234 [app] f1 (/my-project-directory/main.c:93)
    + 6 00000000048d0e00 [libc.so.6] printf (/usr/src/debug/glibc/glibc/stdio-common/printf.c:28)
    ```
  6. Toliak created this gist Mar 2, 2025.
    277 changes: 277 additions & 0 deletions callgrind-better-logs.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,277 @@
    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
    };