Skip to content

Instantly share code, notes, and snippets.

@zhuizhuhaomeng
Created June 28, 2023 08:16
Show Gist options
  • Save zhuizhuhaomeng/2a5c604eedb22b0cf07061aee0aadede to your computer and use it in GitHub Desktop.
Save zhuizhuhaomeng/2a5c604eedb22b0cf07061aee0aadede to your computer and use it in GitHub Desktop.

Revisions

  1. zhuizhuhaomeng created this gist Jun 28, 2023.
    173 changes: 173 additions & 0 deletions d.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,173 @@
    commit ffbb604ca72b709d8f77eebab7da97ec366c4f5b
    Author: lijunlong <[email protected]>
    Date: Wed Jun 28 16:10:40 2023 +0800

    bugfix: _stp_stack_user_sprint flush the buffer to the terminal when the log->buf is full.

    diff --git a/runtime/linux/print.c b/runtime/linux/print.c
    index 594b155be..8dbb3a800 100644
    --- a/runtime/linux/print.c
    +++ b/runtime/linux/print.c
    @@ -36,9 +36,13 @@
    */

    struct _stp_log {
    + unsigned int dst_size;
    + unsigned int dst_len;
    unsigned int len; /* Bytes used in the buffer */
    char *buf; /* NB we don't use arrays here to avoid allocating memory
    on offline CPUs (but still possible ones) */
    + char *dst; /* copy the buf into the dst when flushing buf for
    + _stp_snprintf */
    atomic_t reentrancy_lock;
    };
    #include "print_flush.c"
    diff --git a/runtime/print_flush.c b/runtime/print_flush.c
    index 98963b3eb..f12431e0a 100644
    --- a/runtime/print_flush.c
    +++ b/runtime/print_flush.c
    @@ -30,6 +30,17 @@ static void __stp_print_flush(struct _stp_log *log)
    log->len = 0; /* clear it for later reuse */
    dbug_trans(1, "len = %zu\n", len);

    + if (log->dst != NULL) {
    + if (log->dst_len < log->dst_size) {
    + size_t bytes;
    +
    + bytes = min_t(int, log->dst_size - log->dst_len, len);
    + memcpy(log->dst + log->dst_len, bufp, bytes);
    + log->dst_len += bytes;
    + }
    + return;
    + }
    +
    /* try to reserve header + len */
    bytes_reserved = _stp_data_write_reserve(hlen+len,
    &entry);
    diff --git a/runtime/stack.c b/runtime/stack.c
    index cdcee4bdd..011ec536d 100644
    --- a/runtime/stack.c
    +++ b/runtime/stack.c
    @@ -709,12 +709,25 @@ static void _stp_stack_kernel_sprint(char *str, int size, struct context* c,
    }

    log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
    + log->dst = str;
    + log->dst_size = size - 1;
    + log->dst_len = 0;
    +
    __stp_print_flush(log);
    _stp_stack_kernel_print(c, sym_flags);
    - bytes = min_t(int, size - 1, log->len);
    - memcpy(str, log->buf, bytes);
    +
    + bytes = min_t(int, size - 1 - log->dst_len, log->len);
    + if (bytes > 0)
    + memcpy(str + log->dst_len, log->buf, bytes);
    + bytes += log->dst_len;
    + if ((sym_flags & _STP_SYM_POST_SPACE) && bytes > 0 && str[bytes] == ' ')
    + bytes--;
    str[bytes] = '\0';
    log->len = 0;
    + log->dst = NULL;
    + log->dst_size = 0;
    + log->dst_len = 0;
    +
    _stp_print_unlock_irqrestore(&flags);
    }

    @@ -737,11 +750,23 @@ static void _stp_stack_user_sprint(char *str, int size, struct context* c,

    log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id());
    __stp_print_flush(log);
    + log->dst = str;
    + log->dst_size = size - 1;
    + log->dst_len = 0;
    +
    _stp_stack_user_print(c, sym_flags);
    - bytes = min_t(int, size - 1, log->len);
    - memcpy(str, log->buf, bytes);
    + bytes = min_t(int, size - 1 - log->dst_len, log->len);
    + if (bytes > 0)
    + memcpy(str + log->dst_len, log->buf, bytes);
    + bytes += log->dst_len;
    + if ((sym_flags & _STP_SYM_POST_SPACE) && bytes > 0 && str[bytes] == ' ')
    + bytes--;
    str[bytes] = '\0';
    log->len = 0;
    + log->dst = NULL;
    + log->dst_size = 0;
    + log->dst_len = 0;
    +
    _stp_print_unlock_irqrestore(&flags);
    }

    diff --git a/testsuite/systemtap.base/ustack.exp b/testsuite/systemtap.base/ustack.exp
    index 30671326a..9604d138f 100644
    --- a/testsuite/systemtap.base/ustack.exp
    +++ b/testsuite/systemtap.base/ustack.exp
    @@ -47,3 +47,25 @@ if {$res ne ""} {
    send_log "stderr:\n$stderr"
    }
    }
    +
    +# --- TEST 3 ---
    +
    +set subtest3 "TEST 3: sprint_ubacktrace()"
    +
    +set res [target_compile ${testpath}/${test}_3.c ./a.out executable \
    + "additional_flags=-O additional_flags=-g additional_flags=-O0"]
    +if {$res ne ""} {
    + verbose "target_compile failed: $res" 2
    + fail "$test: $subtest2: unable to compile ${test}_3.c"
    +} else {
    + set test_name "$test: $subtest3"
    +
    + set cmd "stap -DMAXBACKTRACE=256 --ldd -c ./a.out '$srcdir/$subdir/${test}_3.stp'"
    + set exit_code [run_cmd_2way $cmd out stderr]
    + set out_pat "bt: mark.*"
    + like "${test_name}: stdout" $out $out_pat ""
    + is "${test_name}: exit code" $exit_code 0
    + if {$stderr ne ""} {
    + send_log "stderr:\n$stderr"
    + }
    +}
    diff --git a/testsuite/systemtap.base/ustack_3.c b/testsuite/systemtap.base/ustack_3.c
    new file mode 100644
    index 000000000..d159562de
    --- /dev/null
    +++ b/testsuite/systemtap.base/ustack_3.c
    @@ -0,0 +1,22 @@
    +void mark()
    +{
    +}
    +
    +int my_func_name_is_very_longlonglonglonglonglonglonglonglonglonglong(int depth)
    +{
    + int sum;
    +
    + if (depth <= 0) {
    + mark();
    + return 0;
    + }
    +
    + sum = my_func_name_is_very_longlonglonglonglonglonglonglonglonglonglong(depth - 1);
    + sum += depth;
    + return sum;
    +}
    +
    +int main(void) {
    + my_func_name_is_very_longlonglonglonglonglonglonglonglonglonglong(200);
    + return 0;
    +}
    diff --git a/testsuite/systemtap.base/ustack_3.stp b/testsuite/systemtap.base/ustack_3.stp
    new file mode 100644
    index 000000000..01f462ab3
    --- /dev/null
    +++ b/testsuite/systemtap.base/ustack_3.stp
    @@ -0,0 +1,5 @@
    +probe process.function("mark") {
    + s = sprint_ubacktrace();
    + s = sprintf("bt: %s", s)
    + printf("%s", s);
    +}