Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unwind functions (blacklist candidates) #9

Open
honggyukim opened this issue Apr 30, 2019 · 1 comment
Open

unwind functions (blacklist candidates) #9

honggyukim opened this issue Apr 30, 2019 · 1 comment

Comments

@honggyukim
Copy link
Owner

honggyukim commented Apr 30, 2019

gcc/libgcc/config/arm/libunwind.S

$ gcc/libgcc/config/arm/libunwind.S
    ...
UNWIND_WRAPPER _Unwind_RaiseException 1
UNWIND_WRAPPER _Unwind_Resume 1
UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
UNWIND_WRAPPER _Unwind_ForcedUnwind 3
UNWIND_WRAPPER _Unwind_Backtrace 2
    ...

gcc/libgcc/config/ia64/unwind-ia64.c

$ gcc/libgcc/config/ia64/unwind-ia64.c
    ...
#include "unwind.inc"

#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
alias (_Unwind_Backtrace);
alias (_Unwind_DeleteException);
alias (_Unwind_FindEnclosingFunction);
alias (_Unwind_ForcedUnwind);
alias (_Unwind_GetBSP);
alias (_Unwind_GetCFA);
alias (_Unwind_GetGR);
alias (_Unwind_GetIP);
alias (_Unwind_GetLanguageSpecificData);
alias (_Unwind_GetRegionStart);
alias (_Unwind_RaiseException);
alias (_Unwind_Resume);
alias (_Unwind_Resume_or_Rethrow);
alias (_Unwind_SetGR);
alias (_Unwind_SetIP);
#endif
    ...

gcc/libgcc/unwind.inc

$ gcc/libgcc/unwind.inc
    ...
/* Resume propagation of an existing exception.  This is used after
   e.g. executing cleanup code, and not to implement rethrowing.  */

void LIBGCC2_UNWIND_ATTRIBUTE
_Unwind_Resume (struct _Unwind_Exception *exc)
{
  struct _Unwind_Context this_context, cur_context;
  _Unwind_Reason_Code code;
  unsigned long frames;

  uw_init_context (&this_context);
  cur_context = this_context;

  /* Choose between continuing to process _Unwind_RaiseException
     or _Unwind_ForcedUnwind.  */
  if (exc->private_1 == 0)
    code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
  else
    code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);

  gcc_assert (code == _URC_INSTALL_CONTEXT);

  uw_install_context (&this_context, &cur_context, frames);
}
    ...
/* Perform stack backtrace through unwind data.  */

_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
{
  struct _Unwind_Context context;
  _Unwind_Reason_Code code;

  uw_init_context (&context);

  while (1)
    {
      _Unwind_FrameState fs;

      /* Set up fs to describe the FDE for the caller of context.  */
      code = uw_frame_state_for (&context, &fs);
      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
        return _URC_FATAL_PHASE1_ERROR;

      /* Call trace function.  */
      if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
        return _URC_FATAL_PHASE1_ERROR;

      /* We're done at end of stack.  */
      if (code == _URC_END_OF_STACK)
        break;

      /* Update context to describe the same frame as fs.  */
      uw_update_context (&context, &fs);
    }

  return code;
}
    ...
@honggyukim
Copy link
Owner Author

honggyukim commented Apr 30, 2019

glibc-2.26/sysdeps/arm/backtrace.c

$ cat glibc-2.26/sysdeps/arm/backtrace.c
    ...
static void
init (void)
{
  libgcc_handle = __libc_dlopen ("libgcc_s.so.1");

  if (libgcc_handle == NULL)
    return;

  unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace");
  unwind_vrs_get = __libc_dlsym (libgcc_handle, "_Unwind_VRS_Get");
  if (unwind_vrs_get == NULL)
    unwind_backtrace = NULL;
}
    ...
int
__backtrace (void **array, int size)
{
  struct trace_arg arg = { .array = array, .size = size, .cnt = -1 };

  if (size <= 0)
    return 0;

#ifdef SHARED
  __libc_once_define (static, once);

  __libc_once (once, init);
  if (unwind_backtrace == NULL)
    return 0;
#endif

  unwind_backtrace (backtrace_helper, &arg);

  if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
    --arg.cnt;
  return arg.cnt != -1 ? arg.cnt : 0;
}
weak_alias (__backtrace, backtrace)
libc_hidden_def (__backtrace)
    ...

honggyukim added a commit that referenced this issue Jul 11, 2021
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

This patch implements stacktrace() function for this.  It's implemented
in two different versions.  In debug mode, it uses an external libunwind
library and it's output looks as follows.

  Stack trace:
    #1  0x00000045390a fstack_update_stack_count + 0x2c
    #2  0x000000454081 __fstack_consume + 0x48f
    #3  0x000000454b62 __read_rstack + 0x74e
    #4  0x000000454bbb read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7f6d119f9840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

In release mode, it's better not to rely on an external library, so it
just uses builtin backtrace() function, but it can't print static
functions.  The example output looks as follows.

  Stack trace:
    #1  uftrace() [0x442277]
    #2  uftrace() [0x443ced]
    #3  uftrace(command_replay+0xe8) [0x415f28]
    #4  uftrace(main+0x544) [0x40ae14]
    #5  /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f52982e0840]
    #6  uftrace(_start+0x29) [0x40af49]

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
ASSERT is same as assert, but dumps stacktrace before stopped.

However, DASSERT is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with ASSERT
and DASSERT.

When one of the assertion is failed, it prints the stack trace and
raises SIGTRAP signal so that it can be handled by a debugger, otherwise
it will just stop execution anyway.

Here is the example output.

  /data_sdb/honggyu/work/uftrace/git/uftrace/utils/fstack.c:2025: fstack_update_stack_count: ASSERT `!task' failed.
  Stack trace:
    #1  0x0000004559f2 fstack_update_stack_count + 0x66
    #2  0x000000456187 __fstack_consume + 0x48f
    #3  0x000000456c68 __read_rstack + 0x74e
    #4  0x000000456cc1 read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7fd2a7bee840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

  Please report this bug to https://github.com/namhyung/uftrace/issues.

  Trace/breakpoint trap

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

This patch implements stacktrace() function for this.  It's implemented
in two different versions.  In debug mode, it uses an external libunwind
library and it's output looks as follows.

  Stack trace:
    #1  0x000000449ef9 parse_argspec + 0x5d6
    #2  0x00000044b76c parse_argument_spec + 0x70
    #3  0x00000044bf58 setup_trigger_action + 0x146
    #4  0x0000004329e5 find_dwarf_argspec + 0x153
    #5  0x000000432b18 find_auto_argspec + 0x4c
    #6  0x00000044b102 add_filter + 0x87
    #7  0x00000044c1bf add_trigger_entry + 0x15c
    #8  0x00000044c61f setup_trigger + 0x413
    #9  0x00000044c85b uftrace_setup_argument + 0x59
    #10 0x00000044e053 build_arg_spec + 0x4f
    #11 0x00000042a6fe walk_sessions + 0x4a
    #12 0x00000044e12d setup_fstack_args + 0x7d
    #13 0x00000043a353 open_data_file + 0x3ff
    #14 0x0000004171a5 command_replay + 0x7a
    #15 0x000000407ba9 main + 0x4c3
    #16 0x7f4e1df33840 __libc_start_main + 0xf0
    #17 0x000000405499 _start + 0x29

In release mode, it's better not to rely on an external library, so it
just uses builtin backtrace() function, but it can't print static
functions.  The example output looks as follows.

  Stack trace:
    #1  uftrace(parse_argspec+0x4d1) [0x43dd01]
    #2  uftrace() [0x43e44c]
    #3  uftrace(setup_trigger_action+0xb0) [0x43f4e0]
    #4  uftrace() [0x42a933]
    #5  uftrace(find_auto_argspec+0x29) [0x42aff9]
    #6  uftrace() [0x43f2f7]
    #7  uftrace() [0x43fa20]
    #8  uftrace() [0x440140]
    #9  uftrace(walk_sessions+0x39) [0x4248a9]
    #10 uftrace(setup_fstack_args+0xa6) [0x440bb6]
    #11 uftrace(open_data_file+0x16f) [0x43012f]
    #12 uftrace(command_replay+0x59) [0x415ee9]
    #13 uftrace(main+0x544) [0x40adc4]
    #14 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f8e3d944840]
    #15 uftrace(_start+0x29) [0x40aef9]

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
ASSERT is same as assert, but dumps stacktrace before stopped.

However, DASSERT is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with ASSERT
and DASSERT.

When one of the assertion is failed, it prints the stack trace and
raises SIGTRAP signal so that it can be handled by a debugger, otherwise
it will just stop execution anyway.

Here is the example output.

  /data_sdb/honggyu/work/uftrace/git/uftrace/utils/fstack.c:2025: fstack_update_stack_count: ASSERT `!task' failed.
  Stack trace:
    #1  0x0000004559f2 fstack_update_stack_count + 0x66
    #2  0x000000456187 __fstack_consume + 0x48f
    #3  0x000000456c68 __read_rstack + 0x74e
    #4  0x000000456cc1 read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7fd2a7bee840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

  Please report this bug to https://github.com/namhyung/uftrace/issues.

  Trace/breakpoint trap

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
Sometimes it's useful to print backtrace or stacktrace by explicitly
write a request inside source code.

This patch implements stacktrace() function for this.  It's implemented
in two different versions.  In debug mode, it uses an external libunwind
library and it's output looks as follows.

  Stack trace:
    #1  0x000000449ef9 parse_argspec + 0x5d6
    #2  0x00000044b76c parse_argument_spec + 0x70
    #3  0x00000044bf58 setup_trigger_action + 0x146
    #4  0x0000004329e5 find_dwarf_argspec + 0x153
    #5  0x000000432b18 find_auto_argspec + 0x4c
    #6  0x00000044b102 add_filter + 0x87
    #7  0x00000044c1bf add_trigger_entry + 0x15c
    #8  0x00000044c61f setup_trigger + 0x413
    #9  0x00000044c85b uftrace_setup_argument + 0x59
    #10 0x00000044e053 build_arg_spec + 0x4f
    #11 0x00000042a6fe walk_sessions + 0x4a
    #12 0x00000044e12d setup_fstack_args + 0x7d
    #13 0x00000043a353 open_data_file + 0x3ff
    #14 0x0000004171a5 command_replay + 0x7a
    #15 0x000000407ba9 main + 0x4c3
    #16 0x7f4e1df33840 __libc_start_main + 0xf0
    #17 0x000000405499 _start + 0x29

In release mode, it's better not to rely on an external library, so it
just uses builtin backtrace() function, but it can't print static
functions.  The example output looks as follows.

  Stack trace:
    #1  uftrace(parse_argspec+0x4d1) [0x43dd01]
    #2  uftrace() [0x43e44c]
    #3  uftrace(setup_trigger_action+0xb0) [0x43f4e0]
    #4  uftrace() [0x42a933]
    #5  uftrace(find_auto_argspec+0x29) [0x42aff9]
    #6  uftrace() [0x43f2f7]
    #7  uftrace() [0x43fa20]
    #8  uftrace() [0x440140]
    #9  uftrace(walk_sessions+0x39) [0x4248a9]
    #10 uftrace(setup_fstack_args+0xa6) [0x440bb6]
    #11 uftrace(open_data_file+0x16f) [0x43012f]
    #12 uftrace(command_replay+0x59) [0x415ee9]
    #13 uftrace(main+0x544) [0x40adc4]
    #14 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f8e3d944840]
    #15 uftrace(_start+0x29) [0x40aef9]

Signed-off-by: Honggyu Kim <[email protected]>
honggyukim added a commit that referenced this issue Jul 11, 2021
ASSERT is same as assert, but dumps stacktrace before stopped.

However, DASSERT is only compiled when DEBUG=1 is on in debug mode build.
Otherwise, it's simply ignored and doesn't make any overhead.

It would be better if we add more assertion like statements with ASSERT
and DASSERT.

When one of the assertion is failed, it prints the stack trace and
raises SIGTRAP signal so that it can be handled by a debugger, otherwise
it will just stop execution anyway.

Here is the example output.

  /data_sdb/honggyu/work/uftrace/git/uftrace/utils/fstack.c:2025: fstack_update_stack_count: ASSERT `!task' failed.
  Stack trace:
    #1  0x0000004559f2 fstack_update_stack_count + 0x66
    #2  0x000000456187 __fstack_consume + 0x48f
    #3  0x000000456c68 __read_rstack + 0x74e
    #4  0x000000456cc1 read_rstack + 0x28
    #5  0x000000417386 command_replay + 0x28e
    #6  0x000000407bf9 main + 0x4c3
    #7  0x7fd2a7bee840 __libc_start_main + 0xf0
    #8  0x0000004054e9 _start + 0x29
    #9  0x000000000000  + 0x29

  Please report this bug to https://github.com/namhyung/uftrace/issues.

  Trace/breakpoint trap

Signed-off-by: Honggyu Kim <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant