You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ar...@apache.org on 2021/12/29 04:10:04 UTC

[incubator-nuttx] 03/03: sched/backtrace: Dump the complete stack regardless the depth

This is an automated email from the ASF dual-hosted git repository.

archer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit dd942f0b0401f68df746ae067707a2460f3f7199
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Fri Dec 24 15:38:14 2021 +0800

    sched/backtrace: Dump the complete stack regardless the depth
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
 arch/arm/src/common/arm_backtrace_fp.c    | 27 ++++++++-----
 arch/arm/src/common/arm_backtrace_thumb.c | 54 +++++++++++++++++--------
 arch/risc-v/src/common/riscv_backtrace.c  | 31 +++++++++------
 arch/xtensa/src/common/xtensa_backtrace.c | 66 +++++++++++++++++++------------
 include/execinfo.h                        |  4 +-
 include/nuttx/arch.h                      |  4 +-
 include/sched.h                           |  2 +-
 include/sys/syscall_lookup.h              |  2 +-
 libs/libc/sched/sched_backtrace.c         | 10 ++---
 libs/libc/sched/sched_dumpstack.c         | 56 ++++++++++++++------------
 sched/sched/sched_backtrace.c             |  4 +-
 syscall/syscall.csv                       |  2 +-
 12 files changed, 160 insertions(+), 102 deletions(-)

diff --git a/arch/arm/src/common/arm_backtrace_fp.c b/arch/arm/src/common/arm_backtrace_fp.c
index 8d4d4f7..c9373ec 100644
--- a/arch/arm/src/common/arm_backtrace_fp.c
+++ b/arch/arm/src/common/arm_backtrace_fp.c
@@ -49,13 +49,17 @@ __attribute__((no_sanitize_address))
 #endif
 static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit,
                      FAR uintptr_t *fp, FAR uintptr_t *pc,
-                     FAR void **buffer, int size)
+                     FAR void **buffer, int size, FAR int *skip)
 {
   int i = 0;
 
   if (pc)
     {
-      buffer[i++] = pc;
+      i++;
+      if (*skip-- <= 0)
+        {
+          *buffer++ = pc;
+        }
     }
 
   for (; i < size; fp = (FAR uintptr_t *)*(fp - 1), i++)
@@ -65,7 +69,10 @@ static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit,
           break;
         }
 
-      buffer[i] = (FAR void *)*fp;
+      if (*skip-- <= 0)
+        {
+          *buffer++ = (FAR void *)*fp;
+        }
     }
 
   return i;
@@ -93,6 +100,7 @@ static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit,
  *   tcb    - Address of the task's TCB
  *   buffer - Return address from the corresponding stack frame
  *   size   - Maximum number of addresses that can be stored in buffer
+ *   skip   - number of addresses to be skipped
  *
  * Returned Value:
  *   up_backtrace() returns the number of addresses returned in buffer
@@ -102,7 +110,8 @@ static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit,
 #ifdef CONFIG_MM_KASAN
 __attribute__((no_sanitize_address))
 #endif
-int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
+int up_backtrace(FAR struct tcb_s *tcb,
+                 FAR void **buffer, int size, int skip)
 {
   FAR struct tcb_s *rtcb = running_task();
 #if CONFIG_ARCH_INTERRUPTSTACK > 7
@@ -129,12 +138,12 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
           ret = backtrace(istacklimit - (CONFIG_ARCH_INTERRUPTSTACK & ~7),
                           istacklimit,
                           (FAR void *)__builtin_frame_address(0),
-                          NULL, buffer, size);
+                          NULL, buffer, size, &skip);
 #else
           ret = backtrace(rtcb->stack_base_ptr,
                           rtcb->stack_base_ptr + rtcb->adj_stack_size,
                           (FAR void *)__builtin_frame_address(0),
-                          NULL, buffer, size);
+                          NULL, buffer, size, &skip);
 #endif /* CONFIG_ARCH_INTERRUPTSTACK > 7 */
           if (ret < size)
             {
@@ -142,7 +151,7 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
                                rtcb->stack_base_ptr + rtcb->adj_stack_size,
                                (FAR void *)CURRENT_REGS[REG_FP],
                                (FAR void *)CURRENT_REGS[REG_PC],
-                               &buffer[ret], size - ret);
+                               &buffer[ret], size - ret, &skip);
             }
         }
       else
@@ -150,7 +159,7 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
           ret = backtrace(rtcb->stack_base_ptr,
                           rtcb->stack_base_ptr + rtcb->adj_stack_size,
                           (FAR void *)__builtin_frame_address(0),
-                          NULL, buffer, size);
+                          NULL, buffer, size, &skip);
         }
     }
   else
@@ -161,7 +170,7 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
                       tcb->stack_base_ptr + tcb->adj_stack_size,
                       (FAR void *)tcb->xcp.regs[REG_FP],
                       (FAR void *)tcb->xcp.regs[REG_PC],
-                      buffer, size);
+                      buffer, size, &skip);
 
       leave_critical_section(flags);
     }
diff --git a/arch/arm/src/common/arm_backtrace_thumb.c b/arch/arm/src/common/arm_backtrace_thumb.c
index ea766b0..83265c5 100644
--- a/arch/arm/src/common/arm_backtrace_thumb.c
+++ b/arch/arm/src/common/arm_backtrace_thumb.c
@@ -316,10 +316,10 @@ static FAR void *backtrace_push_internal(FAR void **psp,
 #ifdef CONFIG_MM_KASAN
 __attribute__((no_sanitize_address))
 #endif
-static int backtrace_push(FAR void *limit, FAR void **sp,
-                          FAR void *pc, FAR void **buffer, int size)
+static int backtrace_push(FAR void *limit, FAR void **sp, FAR void *pc,
+                          FAR void **buffer, int size, FAR int *skip)
 {
-  int i = 0;
+  int i = 1;
 
   if (!in_code_region(pc))
     {
@@ -328,7 +328,10 @@ static int backtrace_push(FAR void *limit, FAR void **sp,
 
   pc = (uintptr_t)pc & 0xfffffffe;
 
-  buffer[i++] = pc;
+  if (*skip-- <= 0)
+    {
+      *buffer++ = pc;
+    }
 
   for (; i < size; i++)
     {
@@ -337,11 +340,21 @@ static int backtrace_push(FAR void *limit, FAR void **sp,
           break;
         }
 
-      buffer[i] = backtrace_push_internal(sp, &pc);
-      if (!buffer[i])
+      pc = backtrace_push_internal(sp, &pc);
+      if (!pc)
         {
           break;
         }
+
+      if (*skip-- <= 0)
+        {
+          *buffer++ = pc;
+        }
+
+      if (ip)
+        {
+          ip = NULL;
+        }
     }
 
   return i;
@@ -359,7 +372,7 @@ static int backtrace_push(FAR void *limit, FAR void **sp,
 __attribute__((no_sanitize_address))
 #endif
 static int backtrace_branch(FAR void *limit, FAR void *sp,
-                            FAR void **buffer, int size)
+                            FAR void **buffer, int size, FAR int *skip)
 {
   uint16_t ins16;
   uint32_t addr;
@@ -377,7 +390,11 @@ static int backtrace_branch(FAR void *limit, FAR void *sp,
       ins16 = *(FAR uint16_t *)addr;
       if (INSTR_IS(ins16, T_BLX))
         {
-          buffer[i++] = addr;
+          i++;
+          if (*skip-- <= 0)
+            {
+              *buffer++ = addr;
+            }
         }
 
       /* BL Instruction
@@ -393,7 +410,11 @@ static int backtrace_branch(FAR void *limit, FAR void *sp,
           ins16 = *(FAR uint16_t *)addr;
           if (INSTR_IS(ins16, T_BL))
             {
-              buffer[i++] = addr;
+              i++;
+              if (*skip-- <= 0)
+                {
+                  *buffer++ = addr;
+                }
             }
         }
     }
@@ -468,7 +489,8 @@ void up_backtrace_init_code_regions(FAR void **regions)
 #ifdef CONFIG_MM_KASAN
 __attribute__((no_sanitize_address))
 #endif
-int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
+int up_backtrace(FAR struct tcb_s *tcb,
+                 FAR void **buffer, int size, FAR int skip)
 {
   FAR struct tcb_s *rtcb = running_task();
   irqstate_t flags;
@@ -504,7 +526,7 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
           ret = backtrace_push(rtcb->stack_base_ptr +
                                rtcb->adj_stack_size,
                                &sp, (FAR void *)up_backtrace + 10,
-                               buffer, size);
+                               buffer, size, &skip);
 #endif
           if (ret < size)
             {
@@ -512,7 +534,7 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
               ret += backtrace_push(rtcb->stack_base_ptr +
                                     rtcb->adj_stack_size, &sp,
                                     (FAR void *)CURRENT_REGS[REG_PC],
-                                    &buffer[ret], size - ret);
+                                    &buffer[ret], size - ret, &skip);
             }
         }
       else
@@ -520,14 +542,14 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
           ret = backtrace_push(rtcb->stack_base_ptr +
                                rtcb->adj_stack_size, &sp,
                                (FAR void *)up_backtrace + 10,
-                               buffer, size);
+                               buffer, size, &skip);
         }
 
       if (ret < size)
         {
           ret += backtrace_branch(rtcb->stack_base_ptr +
                                   rtcb->adj_stack_size, sp,
-                                  &buffer[ret], size - ret);
+                                  &buffer[ret], size - ret, &skip);
         }
     }
   else
@@ -544,13 +566,13 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
           ret += backtrace_push(tcb->stack_base_ptr +
                                 tcb->adj_stack_size, &sp,
                                 (FAR void *)tcb->xcp.regs[REG_LR],
-                                &buffer[ret], size - ret);
+                                &buffer[ret], size - ret, &skip);
 
           if (ret < size)
             {
               ret += backtrace_branch(tcb->stack_base_ptr +
                                       tcb->adj_stack_size, sp,
-                                      &buffer[ret], size - ret);
+                                      &buffer[ret], size - ret, &skip);
             }
         }
 
diff --git a/arch/risc-v/src/common/riscv_backtrace.c b/arch/risc-v/src/common/riscv_backtrace.c
index f328325..007815b 100644
--- a/arch/risc-v/src/common/riscv_backtrace.c
+++ b/arch/risc-v/src/common/riscv_backtrace.c
@@ -63,13 +63,17 @@ static inline uintptr_t getfp(void)
 
 static int backtrace(uintptr_t *base, uintptr_t *limit,
                      uintptr_t *fp, uintptr_t *ra,
-                     void **buffer, int size)
+                     void **buffer, int size, int *skip)
 {
   int i = 0;
 
   if (ra)
     {
-      buffer[i++] = ra;
+      i++;
+      if (*skip-- <= 0)
+        {
+          *buffer++ = ra;
+        }
     }
 
   for (; i < size; fp = (uintptr_t *)*(fp - 2), i++)
@@ -85,7 +89,10 @@ static int backtrace(uintptr_t *base, uintptr_t *limit,
           break;
         }
 
-      buffer[i] = ra;
+      if (*skip-- <= 0)
+        {
+          *buffer++ = ra;
+        }
     }
 
   return i;
@@ -113,13 +120,14 @@ static int backtrace(uintptr_t *base, uintptr_t *limit,
  *   tcb    - Address of the task's TCB
  *   buffer - Return address from the corresponding stack frame
  *   size   - Maximum number of addresses that can be stored in buffer
+ *   skip   - number of addresses to be skipped
  *
  * Returned Value:
  *   up_backtrace() returns the number of addresses returned in buffer
  *
  ****************************************************************************/
 
-int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
+int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip)
 {
   struct tcb_s *rtcb = running_task();
   irqstate_t flags;
@@ -137,28 +145,27 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
 #if CONFIG_ARCH_INTERRUPTSTACK > 15
           ret = backtrace((void *)&g_intstackalloc,
                           (void *)((uint32_t)&g_intstackalloc +
-                                       CONFIG_ARCH_INTERRUPTSTACK),
-                          (void *)getfp(), NULL, buffer, size);
+                                   CONFIG_ARCH_INTERRUPTSTACK),
+                          (void *)getfp(), NULL, buffer, size, &skip);
 #else
           ret = backtrace(rtcb->stack_base_ptr,
                           rtcb->stack_base_ptr + rtcb->adj_stack_size,
-                          (void *)getfp(), NULL, buffer, size);
+                          (void *)getfp(), NULL, buffer, size, &skip);
 #endif
           if (ret < size)
             {
               ret += backtrace(rtcb->stack_base_ptr,
-                               rtcb->stack_base_ptr +
-                               rtcb->adj_stack_size,
+                               rtcb->stack_base_ptr + rtcb->adj_stack_size,
                                (void *)CURRENT_REGS[REG_FP],
                                (void *)CURRENT_REGS[REG_EPC],
-                               &buffer[ret], size - ret);
+                               &buffer[ret], size - ret, &skip);
             }
         }
       else
         {
           ret = backtrace(rtcb->stack_base_ptr,
                           rtcb->stack_base_ptr + rtcb->adj_stack_size,
-                          (void *)getfp(), NULL, buffer, size);
+                          (void *)getfp(), NULL, buffer, size, &skip);
         }
     }
   else
@@ -169,7 +176,7 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
                       tcb->stack_base_ptr + tcb->adj_stack_size,
                       (void *)tcb->xcp.regs[REG_FP],
                       (void *)tcb->xcp.regs[REG_EPC],
-                      buffer, size);
+                      buffer, size, &skip);
 
       leave_critical_section(flags);
     }
diff --git a/arch/xtensa/src/common/xtensa_backtrace.c b/arch/xtensa/src/common/xtensa_backtrace.c
index 3a6cc89..54b529f 100644
--- a/arch/xtensa/src/common/xtensa_backtrace.c
+++ b/arch/xtensa/src/common/xtensa_backtrace.c
@@ -106,8 +106,8 @@ static void get_window_regs(struct xtensa_windowregs_s *frame)
 
 #ifndef __XTENSA_CALL0_ABI__
 static int backtrace_window(uintptr_t *base, uintptr_t *limit,
-                     struct xtensa_windowregs_s *frame,
-                     void **buffer, int size)
+                            struct xtensa_windowregs_s *frame,
+                            void **buffer, int size, int *skip)
 {
   uint32_t windowstart;
   uint32_t ra;
@@ -136,7 +136,11 @@ static int backtrace_window(uintptr_t *base, uintptr_t *limit,
               continue;
             }
 
-          buffer[i++] = MAKE_PC_FROM_RA(ra);
+          i++;
+          if (*skip-- <= 0)
+            {
+              *buffer++ = MAKE_PC_FROM_RA(ra);
+            }
         }
     }
 
@@ -153,14 +157,18 @@ static int backtrace_window(uintptr_t *base, uintptr_t *limit,
  ****************************************************************************/
 
 static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
-                     uintptr_t *sp, uintptr_t *ra,
-                     void **buffer, int size)
+                           uintptr_t *sp, uintptr_t *ra,
+                           void **buffer, int size, int *skip)
 {
   int i = 0;
 
   if (ra)
     {
-      buffer[i++] = MAKE_PC_FROM_RA((uintptr_t)ra);
+      i++;
+      if (*skip-- <= 0)
+        {
+          *buffer++ = MAKE_PC_FROM_RA((uintptr_t)ra);
+        }
     }
 
   for (; i < size; sp = (uintptr_t *)*(sp - 3), i++)
@@ -176,7 +184,10 @@ static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
           break;
         }
 
-      buffer[i] = MAKE_PC_FROM_RA((uintptr_t)ra);
+      if (*skip-- <= 0)
+        {
+          *buffer++ = MAKE_PC_FROM_RA((uintptr_t)ra);
+        }
     }
 
   return i;
@@ -204,13 +215,14 @@ static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
  *   tcb    - Address of the task's TCB
  *   buffer - Return address from the corresponding stack frame
  *   size   - Maximum number of addresses that can be stored in buffer
+ *   skip   - number of addresses to be skipped
  *
  * Returned Value:
  *   up_backtrace() returns the number of addresses returned in buffer
  *
  ****************************************************************************/
 
-int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
+int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip)
 {
   struct tcb_s *rtcb = running_task();
   irqstate_t flags;
@@ -235,20 +247,21 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
           xtensa_window_spill();
 
           ret = backtrace_stack((void *)istackbase,
-                          (void *)(istackbase +
-                                   CONFIG_ARCH_INTERRUPTSTACK),
-                          (void *)up_getsp(), NULL, buffer, size);
+                                (void *)(istackbase +
+                                         CONFIG_ARCH_INTERRUPTSTACK),
+                                (void *)up_getsp(), NULL,
+                                buffer, size, &skip);
 #else
           ret = backtrace_stack(rtcb->stack_base_ptr,
-                          rtcb->stack_base_ptr + rtcb->adj_stack_size,
-                          (void *)up_getsp(), NULL, buffer, size);
+                                rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                                (void *)up_getsp(), NULL,
+                                buffer, size, &skip);
 #endif
           ret += backtrace_stack(rtcb->stack_base_ptr,
-                          rtcb->stack_base_ptr +
-                          rtcb->adj_stack_size,
-                          (void *)CURRENT_REGS[REG_A1],
-                          (void *)CURRENT_REGS[REG_A0],
-                          &buffer[ret], size - ret);
+                                 rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                                 (void *)CURRENT_REGS[REG_A1],
+                                 (void *)CURRENT_REGS[REG_A0],
+                                 &buffer[ret], size - ret, &skip);
         }
       else
         {
@@ -268,12 +281,13 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
           get_window_regs(&frame);
 
           ret = backtrace_window(rtcb->stack_base_ptr,
-                          rtcb->stack_base_ptr + rtcb->adj_stack_size,
-                          &frame, buffer, size);
+                                 rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                                 &frame, buffer, size, &skip);
 #endif
           ret += backtrace_stack(rtcb->stack_base_ptr,
-                          rtcb->stack_base_ptr + rtcb->adj_stack_size,
-                          (void *)up_getsp(), NULL, buffer, size - ret);
+                                 rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                                 (void *)up_getsp(), NULL,
+                                 buffer, size - ret, &skip);
         }
     }
   else
@@ -283,10 +297,10 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
       flags = enter_critical_section();
 
       ret = backtrace_stack(tcb->stack_base_ptr,
-                      tcb->stack_base_ptr + tcb->adj_stack_size,
-                      (void *)tcb->xcp.regs[REG_A1],
-                      (void *)tcb->xcp.regs[REG_A0],
-                      buffer, size);
+                            tcb->stack_base_ptr + tcb->adj_stack_size,
+                            (void *)tcb->xcp.regs[REG_A1],
+                            (void *)tcb->xcp.regs[REG_A0],
+                            buffer, size, &skip);
 
       leave_critical_section(flags);
     }
diff --git a/include/execinfo.h b/include/execinfo.h
index 6380eaf..30e56cd 100644
--- a/include/execinfo.h
+++ b/include/execinfo.h
@@ -38,8 +38,8 @@
  * ARRAY and return the exact number of values stored.
  */
 
-#define backtrace(buffer, size) sched_backtrace(gettid(), buffer, size)
-#define dump_stack()            sched_dumpstack(gettid())
+# define backtrace(buffer, size) sched_backtrace(gettid(), buffer, size, 0)
+# define dump_stack()            sched_dumpstack(gettid())
 
 #else
 # define backtrace(buffer, size) 0
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index e7e2f36..ca4b6cb 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -513,13 +513,15 @@ void up_assert(FAR const char *filename, int linenum);
  *   tcb    - Address of the task's TCB, NULL means dump the running task
  *   buffer - Return address from the corresponding stack frame
  *   size   - Maximum number of addresses that can be stored in buffer
+ *   skip   - number of addresses to be skipped
  *
  * Returned Value:
  *   up_backtrace() returns the number of addresses returned in buffer
  *
  ****************************************************************************/
 
-int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size);
+int up_backtrace(FAR struct tcb_s *tcb,
+                 FAR void **buffer, int size, int skip);
 #endif /* CONFIG_ARCH_HAVE_BACKTRACE */
 
 /****************************************************************************
diff --git a/include/sched.h b/include/sched.h
index 842ce4d..f3cbcd9 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -264,7 +264,7 @@ bool   sched_idletask(void);
 
 /* Task Backtrace */
 
-int    sched_backtrace(pid_t tid, FAR void **buffer, int size);
+int    sched_backtrace(pid_t tid, FAR void **buffer, int size, int skip);
 void   sched_dumpstack(pid_t tid);
 
 #undef EXTERN
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index 8b4e0a1..47310c2 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -45,7 +45,7 @@ SYSCALL_LOOKUP(sched_yield,                0)
 SYSCALL_LOOKUP(nxsched_get_stackinfo,      2)
 
 #ifdef CONFIG_SCHED_BACKTRACE
-  SYSCALL_LOOKUP(sched_backtrace,          3)
+  SYSCALL_LOOKUP(sched_backtrace,          4)
 #endif
 
 #ifdef CONFIG_SMP
diff --git a/libs/libc/sched/sched_backtrace.c b/libs/libc/sched/sched_backtrace.c
index 5c35bda..9e27d1f 100644
--- a/libs/libc/sched/sched_backtrace.c
+++ b/libs/libc/sched/sched_backtrace.c
@@ -64,7 +64,7 @@ backtrace_helper(FAR struct _Unwind_Context *ctx, FAR void *a)
    * Skip it.
    */
 
-  if (arg->cnt != -1)
+  if (arg->cnt >= 0)
     {
       arg->array[arg->cnt] = (FAR void *)_Unwind_GetIP(ctx);
       if (arg->cnt > 0)
@@ -88,7 +88,7 @@ backtrace_helper(FAR struct _Unwind_Context *ctx, FAR void *a)
       arg->cfa = cfa;
     }
 
-  if (++arg->cnt == arg->size)
+  if (++arg->cnt >= arg->size)
     {
       return _URC_END_OF_STACK;
     }
@@ -108,7 +108,7 @@ backtrace_helper(FAR struct _Unwind_Context *ctx, FAR void *a)
  *
  ****************************************************************************/
 
-int sched_backtrace(pid_t tid, FAR void **buffer, int size)
+int sched_backtrace(pid_t tid, FAR void **buffer, int size, int skip)
 {
   struct trace_arg arg;
 
@@ -120,7 +120,7 @@ int sched_backtrace(pid_t tid, FAR void **buffer, int size)
   arg.array = buffer;
   arg.cfa = 0;
   arg.size = size;
-  arg.cnt = -1;
+  arg.cnt = -skip - 1;
 
   if (size <= 0)
     {
@@ -138,7 +138,7 @@ int sched_backtrace(pid_t tid, FAR void **buffer, int size)
       --arg.cnt;
     }
 
-  return arg.cnt != -1 ? arg.cnt : 0;
+  return arg.cnt > 0 ? arg.cnt : 0;
 }
 
 #endif /* !CONFIG_ARCH_HAVE_BACKTRACE */
diff --git a/libs/libc/sched/sched_dumpstack.c b/libs/libc/sched/sched_dumpstack.c
index a6b871c..c504c11 100644
--- a/libs/libc/sched/sched_dumpstack.c
+++ b/libs/libc/sched/sched_dumpstack.c
@@ -29,7 +29,6 @@
 
 #include <stdio.h>
 #include <syslog.h>
-#include <execinfo.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -54,38 +53,43 @@
 
 void sched_dumpstack(pid_t tid)
 {
-  FAR void *address[DUMP_DEPTH];
+  int size = DUMP_DEPTH;
+  int skip;
+
+  for (skip = 0; size == DUMP_DEPTH; skip += size)
+    {
+      FAR void *address[DUMP_DEPTH];
 #ifndef CONFIG_ALLSYMS
-  const char *format = " %0*p";
-  char line[DUMP_LINESZ + 1];
-  int ret = 0;
+      const char *format = " %0*p";
+      char line[DUMP_LINESZ + 1];
+      int ret = 0;
 #endif
-  int size;
-  int i;
+      int i;
 
-  size = sched_backtrace(tid, address, DUMP_DEPTH);
-  if (size <= 0)
-    {
-      return;
-    }
+      size = sched_backtrace(tid, address, DUMP_DEPTH, skip);
+      if (size <= 0)
+        {
+          break;
+        }
 
 #ifndef CONFIG_ALLSYMS
-  for (i = 0; i < size; i++)
-    {
-      ret += snprintf(line + ret, sizeof(line) - ret,
-                      format, DUMP_WIDTH, address[i]);
-      if (i == size - 1 || ret % DUMP_LINESZ == 0)
+      for (i = 0; i < size; i++)
         {
-          syslog(LOG_EMERG, "backtrace|%2d:%s\n", tid, line);
-          ret = 0;
+          ret += snprintf(line + ret, sizeof(line) - ret,
+                          format, DUMP_WIDTH, address[i]);
+          if (i == size - 1 || ret % DUMP_LINESZ == 0)
+            {
+              syslog(LOG_EMERG, "backtrace|%2d:%s\n", tid, line);
+              ret = 0;
+            }
         }
-    }
 #else
-  syslog(LOG_EMERG, "backtrace:\n");
-  for (i = 0; i < size; i++)
-    {
-      syslog(LOG_EMERG, "[%2d] [<%p>] %pS\n",
-                         tid, address[i], address[i]);
-    }
+      syslog(LOG_EMERG, "backtrace:\n");
+      for (i = 0; i < size; i++)
+        {
+          syslog(LOG_EMERG, "[%2d] [<%p>] %pS\n",
+                            tid, address[i], address[i]);
+        }
 #endif
+    }
 }
diff --git a/sched/sched/sched_backtrace.c b/sched/sched/sched_backtrace.c
index 6c3ab7d..16fe43c 100644
--- a/sched/sched/sched_backtrace.c
+++ b/sched/sched/sched_backtrace.c
@@ -40,7 +40,7 @@
  *
  ****************************************************************************/
 
-int sched_backtrace(pid_t tid, FAR void **buffer, int size)
+int sched_backtrace(pid_t tid, FAR void **buffer, int size, int skip)
 {
   FAR struct tcb_s *rtcb = NULL;
 
@@ -53,5 +53,5 @@ int sched_backtrace(pid_t tid, FAR void **buffer, int size)
         }
     }
 
-  return up_backtrace(rtcb, buffer, size);
+  return up_backtrace(rtcb, buffer, size, skip);
 }
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index fd53acb..21445cf 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -132,7 +132,7 @@
 "sched_setscheduler","sched.h","","int","pid_t","int","const struct sched_param *"
 "sched_unlock","sched.h","","int"
 "sched_yield","sched.h","","int"
-"sched_backtrace","sched.h","defined(CONFIG_SCHED_BACKTRACE)","int","pid_t","FAR void **","int"
+"sched_backtrace","sched.h","defined(CONFIG_SCHED_BACKTRACE)","int","pid_t","FAR void **","int","int"
 "seekdir","dirent.h","","void","FAR DIR *","off_t"
 "select","sys/select.h","","int","int","FAR fd_set *","FAR fd_set *","FAR fd_set *","FAR struct timeval *"
 "sem_clockwait","semaphore.h","","int","FAR sem_t *","clockid_t","FAR const struct timespec *"