sched/backtrace: Dump the complete stack regardless the depth

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2021-12-24 15:38:14 +08:00 committed by archer
parent 9eecd4c5e2
commit dd942f0b04
12 changed files with 162 additions and 104 deletions

View File

@ -49,13 +49,17 @@ __attribute__((no_sanitize_address))
#endif #endif
static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit, static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit,
FAR uintptr_t *fp, FAR uintptr_t *pc, FAR uintptr_t *fp, FAR uintptr_t *pc,
FAR void **buffer, int size) FAR void **buffer, int size, FAR int *skip)
{ {
int i = 0; int i = 0;
if (pc) if (pc)
{ {
buffer[i++] = pc; i++;
if (*skip-- <= 0)
{
*buffer++ = pc;
}
} }
for (; i < size; fp = (FAR uintptr_t *)*(fp - 1), i++) 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; break;
} }
buffer[i] = (FAR void *)*fp; if (*skip-- <= 0)
{
*buffer++ = (FAR void *)*fp;
}
} }
return i; return i;
@ -93,6 +100,7 @@ static int backtrace(FAR uintptr_t *base, FAR uintptr_t *limit,
* tcb - Address of the task's TCB * tcb - Address of the task's TCB
* buffer - Return address from the corresponding stack frame * buffer - Return address from the corresponding stack frame
* size - Maximum number of addresses that can be stored in buffer * size - Maximum number of addresses that can be stored in buffer
* skip - number of addresses to be skipped
* *
* Returned Value: * Returned Value:
* up_backtrace() returns the number of addresses returned in buffer * 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 #ifdef CONFIG_MM_KASAN
__attribute__((no_sanitize_address)) __attribute__((no_sanitize_address))
#endif #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(); FAR struct tcb_s *rtcb = running_task();
#if CONFIG_ARCH_INTERRUPTSTACK > 7 #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), ret = backtrace(istacklimit - (CONFIG_ARCH_INTERRUPTSTACK & ~7),
istacklimit, istacklimit,
(FAR void *)__builtin_frame_address(0), (FAR void *)__builtin_frame_address(0),
NULL, buffer, size); NULL, buffer, size, &skip);
#else #else
ret = backtrace(rtcb->stack_base_ptr, ret = backtrace(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(FAR void *)__builtin_frame_address(0), (FAR void *)__builtin_frame_address(0),
NULL, buffer, size); NULL, buffer, size, &skip);
#endif /* CONFIG_ARCH_INTERRUPTSTACK > 7 */ #endif /* CONFIG_ARCH_INTERRUPTSTACK > 7 */
if (ret < size) 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, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(FAR void *)CURRENT_REGS[REG_FP], (FAR void *)CURRENT_REGS[REG_FP],
(FAR void *)CURRENT_REGS[REG_PC], (FAR void *)CURRENT_REGS[REG_PC],
&buffer[ret], size - ret); &buffer[ret], size - ret, &skip);
} }
} }
else else
@ -150,7 +159,7 @@ int up_backtrace(FAR struct tcb_s *tcb, FAR void **buffer, int size)
ret = backtrace(rtcb->stack_base_ptr, ret = backtrace(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(FAR void *)__builtin_frame_address(0), (FAR void *)__builtin_frame_address(0),
NULL, buffer, size); NULL, buffer, size, &skip);
} }
} }
else 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, tcb->stack_base_ptr + tcb->adj_stack_size,
(FAR void *)tcb->xcp.regs[REG_FP], (FAR void *)tcb->xcp.regs[REG_FP],
(FAR void *)tcb->xcp.regs[REG_PC], (FAR void *)tcb->xcp.regs[REG_PC],
buffer, size); buffer, size, &skip);
leave_critical_section(flags); leave_critical_section(flags);
} }

View File

@ -316,10 +316,10 @@ static FAR void *backtrace_push_internal(FAR void **psp,
#ifdef CONFIG_MM_KASAN #ifdef CONFIG_MM_KASAN
__attribute__((no_sanitize_address)) __attribute__((no_sanitize_address))
#endif #endif
static int backtrace_push(FAR void *limit, FAR void **sp, static int backtrace_push(FAR void *limit, FAR void **sp, FAR void *pc,
FAR void *pc, FAR void **buffer, int size) FAR void **buffer, int size, FAR int *skip)
{ {
int i = 0; int i = 1;
if (!in_code_region(pc)) if (!in_code_region(pc))
{ {
@ -328,7 +328,10 @@ static int backtrace_push(FAR void *limit, FAR void **sp,
pc = (uintptr_t)pc & 0xfffffffe; pc = (uintptr_t)pc & 0xfffffffe;
buffer[i++] = pc; if (*skip-- <= 0)
{
*buffer++ = pc;
}
for (; i < size; i++) for (; i < size; i++)
{ {
@ -337,11 +340,21 @@ static int backtrace_push(FAR void *limit, FAR void **sp,
break; break;
} }
buffer[i] = backtrace_push_internal(sp, &pc); pc = backtrace_push_internal(sp, &pc);
if (!buffer[i]) if (!pc)
{ {
break; break;
} }
if (*skip-- <= 0)
{
*buffer++ = pc;
}
if (ip)
{
ip = NULL;
}
} }
return i; return i;
@ -359,7 +372,7 @@ static int backtrace_push(FAR void *limit, FAR void **sp,
__attribute__((no_sanitize_address)) __attribute__((no_sanitize_address))
#endif #endif
static int backtrace_branch(FAR void *limit, FAR void *sp, 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; uint16_t ins16;
uint32_t addr; uint32_t addr;
@ -377,7 +390,11 @@ static int backtrace_branch(FAR void *limit, FAR void *sp,
ins16 = *(FAR uint16_t *)addr; ins16 = *(FAR uint16_t *)addr;
if (INSTR_IS(ins16, T_BLX)) if (INSTR_IS(ins16, T_BLX))
{ {
buffer[i++] = addr; i++;
if (*skip-- <= 0)
{
*buffer++ = addr;
}
} }
/* BL Instruction /* BL Instruction
@ -393,7 +410,11 @@ static int backtrace_branch(FAR void *limit, FAR void *sp,
ins16 = *(FAR uint16_t *)addr; ins16 = *(FAR uint16_t *)addr;
if (INSTR_IS(ins16, T_BL)) 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 #ifdef CONFIG_MM_KASAN
__attribute__((no_sanitize_address)) __attribute__((no_sanitize_address))
#endif #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(); FAR struct tcb_s *rtcb = running_task();
irqstate_t flags; 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 + ret = backtrace_push(rtcb->stack_base_ptr +
rtcb->adj_stack_size, rtcb->adj_stack_size,
&sp, (FAR void *)up_backtrace + 10, &sp, (FAR void *)up_backtrace + 10,
buffer, size); buffer, size, &skip);
#endif #endif
if (ret < size) 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 + ret += backtrace_push(rtcb->stack_base_ptr +
rtcb->adj_stack_size, &sp, rtcb->adj_stack_size, &sp,
(FAR void *)CURRENT_REGS[REG_PC], (FAR void *)CURRENT_REGS[REG_PC],
&buffer[ret], size - ret); &buffer[ret], size - ret, &skip);
} }
} }
else 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 + ret = backtrace_push(rtcb->stack_base_ptr +
rtcb->adj_stack_size, &sp, rtcb->adj_stack_size, &sp,
(FAR void *)up_backtrace + 10, (FAR void *)up_backtrace + 10,
buffer, size); buffer, size, &skip);
} }
if (ret < size) if (ret < size)
{ {
ret += backtrace_branch(rtcb->stack_base_ptr + ret += backtrace_branch(rtcb->stack_base_ptr +
rtcb->adj_stack_size, sp, rtcb->adj_stack_size, sp,
&buffer[ret], size - ret); &buffer[ret], size - ret, &skip);
} }
} }
else 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 + ret += backtrace_push(tcb->stack_base_ptr +
tcb->adj_stack_size, &sp, tcb->adj_stack_size, &sp,
(FAR void *)tcb->xcp.regs[REG_LR], (FAR void *)tcb->xcp.regs[REG_LR],
&buffer[ret], size - ret); &buffer[ret], size - ret, &skip);
if (ret < size) if (ret < size)
{ {
ret += backtrace_branch(tcb->stack_base_ptr + ret += backtrace_branch(tcb->stack_base_ptr +
tcb->adj_stack_size, sp, tcb->adj_stack_size, sp,
&buffer[ret], size - ret); &buffer[ret], size - ret, &skip);
} }
} }

View File

@ -63,13 +63,17 @@ static inline uintptr_t getfp(void)
static int backtrace(uintptr_t *base, uintptr_t *limit, static int backtrace(uintptr_t *base, uintptr_t *limit,
uintptr_t *fp, uintptr_t *ra, uintptr_t *fp, uintptr_t *ra,
void **buffer, int size) void **buffer, int size, int *skip)
{ {
int i = 0; int i = 0;
if (ra) if (ra)
{ {
buffer[i++] = ra; i++;
if (*skip-- <= 0)
{
*buffer++ = ra;
}
} }
for (; i < size; fp = (uintptr_t *)*(fp - 2), i++) for (; i < size; fp = (uintptr_t *)*(fp - 2), i++)
@ -85,7 +89,10 @@ static int backtrace(uintptr_t *base, uintptr_t *limit,
break; break;
} }
buffer[i] = ra; if (*skip-- <= 0)
{
*buffer++ = ra;
}
} }
return i; return i;
@ -113,13 +120,14 @@ static int backtrace(uintptr_t *base, uintptr_t *limit,
* tcb - Address of the task's TCB * tcb - Address of the task's TCB
* buffer - Return address from the corresponding stack frame * buffer - Return address from the corresponding stack frame
* size - Maximum number of addresses that can be stored in buffer * size - Maximum number of addresses that can be stored in buffer
* skip - number of addresses to be skipped
* *
* Returned Value: * Returned Value:
* up_backtrace() returns the number of addresses returned in buffer * 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(); struct tcb_s *rtcb = running_task();
irqstate_t flags; irqstate_t flags;
@ -137,28 +145,27 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
#if CONFIG_ARCH_INTERRUPTSTACK > 15 #if CONFIG_ARCH_INTERRUPTSTACK > 15
ret = backtrace((void *)&g_intstackalloc, ret = backtrace((void *)&g_intstackalloc,
(void *)((uint32_t)&g_intstackalloc + (void *)((uint32_t)&g_intstackalloc +
CONFIG_ARCH_INTERRUPTSTACK), CONFIG_ARCH_INTERRUPTSTACK),
(void *)getfp(), NULL, buffer, size); (void *)getfp(), NULL, buffer, size, &skip);
#else #else
ret = backtrace(rtcb->stack_base_ptr, ret = backtrace(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(void *)getfp(), NULL, buffer, size); (void *)getfp(), NULL, buffer, size, &skip);
#endif #endif
if (ret < size) if (ret < size)
{ {
ret += backtrace(rtcb->stack_base_ptr, ret += backtrace(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->stack_base_ptr + rtcb->adj_stack_size,
rtcb->adj_stack_size,
(void *)CURRENT_REGS[REG_FP], (void *)CURRENT_REGS[REG_FP],
(void *)CURRENT_REGS[REG_EPC], (void *)CURRENT_REGS[REG_EPC],
&buffer[ret], size - ret); &buffer[ret], size - ret, &skip);
} }
} }
else else
{ {
ret = backtrace(rtcb->stack_base_ptr, ret = backtrace(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(void *)getfp(), NULL, buffer, size); (void *)getfp(), NULL, buffer, size, &skip);
} }
} }
else else
@ -169,7 +176,7 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
tcb->stack_base_ptr + tcb->adj_stack_size, tcb->stack_base_ptr + tcb->adj_stack_size,
(void *)tcb->xcp.regs[REG_FP], (void *)tcb->xcp.regs[REG_FP],
(void *)tcb->xcp.regs[REG_EPC], (void *)tcb->xcp.regs[REG_EPC],
buffer, size); buffer, size, &skip);
leave_critical_section(flags); leave_critical_section(flags);
} }

View File

@ -106,8 +106,8 @@ static void get_window_regs(struct xtensa_windowregs_s *frame)
#ifndef __XTENSA_CALL0_ABI__ #ifndef __XTENSA_CALL0_ABI__
static int backtrace_window(uintptr_t *base, uintptr_t *limit, static int backtrace_window(uintptr_t *base, uintptr_t *limit,
struct xtensa_windowregs_s *frame, struct xtensa_windowregs_s *frame,
void **buffer, int size) void **buffer, int size, int *skip)
{ {
uint32_t windowstart; uint32_t windowstart;
uint32_t ra; uint32_t ra;
@ -136,7 +136,11 @@ static int backtrace_window(uintptr_t *base, uintptr_t *limit,
continue; 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, static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
uintptr_t *sp, uintptr_t *ra, uintptr_t *sp, uintptr_t *ra,
void **buffer, int size) void **buffer, int size, int *skip)
{ {
int i = 0; int i = 0;
if (ra) 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++) for (; i < size; sp = (uintptr_t *)*(sp - 3), i++)
@ -176,7 +184,10 @@ static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
break; break;
} }
buffer[i] = MAKE_PC_FROM_RA((uintptr_t)ra); if (*skip-- <= 0)
{
*buffer++ = MAKE_PC_FROM_RA((uintptr_t)ra);
}
} }
return i; return i;
@ -204,13 +215,14 @@ static int backtrace_stack(uintptr_t *base, uintptr_t *limit,
* tcb - Address of the task's TCB * tcb - Address of the task's TCB
* buffer - Return address from the corresponding stack frame * buffer - Return address from the corresponding stack frame
* size - Maximum number of addresses that can be stored in buffer * size - Maximum number of addresses that can be stored in buffer
* skip - number of addresses to be skipped
* *
* Returned Value: * Returned Value:
* up_backtrace() returns the number of addresses returned in buffer * 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(); struct tcb_s *rtcb = running_task();
irqstate_t flags; irqstate_t flags;
@ -235,20 +247,21 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
xtensa_window_spill(); xtensa_window_spill();
ret = backtrace_stack((void *)istackbase, ret = backtrace_stack((void *)istackbase,
(void *)(istackbase + (void *)(istackbase +
CONFIG_ARCH_INTERRUPTSTACK), CONFIG_ARCH_INTERRUPTSTACK),
(void *)up_getsp(), NULL, buffer, size); (void *)up_getsp(), NULL,
buffer, size, &skip);
#else #else
ret = backtrace_stack(rtcb->stack_base_ptr, ret = backtrace_stack(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(void *)up_getsp(), NULL, buffer, size); (void *)up_getsp(), NULL,
buffer, size, &skip);
#endif #endif
ret += backtrace_stack(rtcb->stack_base_ptr, ret += backtrace_stack(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->stack_base_ptr + rtcb->adj_stack_size,
rtcb->adj_stack_size, (void *)CURRENT_REGS[REG_A1],
(void *)CURRENT_REGS[REG_A1], (void *)CURRENT_REGS[REG_A0],
(void *)CURRENT_REGS[REG_A0], &buffer[ret], size - ret, &skip);
&buffer[ret], size - ret);
} }
else else
{ {
@ -268,12 +281,13 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
get_window_regs(&frame); get_window_regs(&frame);
ret = backtrace_window(rtcb->stack_base_ptr, ret = backtrace_window(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
&frame, buffer, size); &frame, buffer, size, &skip);
#endif #endif
ret += backtrace_stack(rtcb->stack_base_ptr, ret += backtrace_stack(rtcb->stack_base_ptr,
rtcb->stack_base_ptr + rtcb->adj_stack_size, rtcb->stack_base_ptr + rtcb->adj_stack_size,
(void *)up_getsp(), NULL, buffer, size - ret); (void *)up_getsp(), NULL,
buffer, size - ret, &skip);
} }
} }
else else
@ -283,10 +297,10 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size)
flags = enter_critical_section(); flags = enter_critical_section();
ret = backtrace_stack(tcb->stack_base_ptr, ret = backtrace_stack(tcb->stack_base_ptr,
tcb->stack_base_ptr + tcb->adj_stack_size, tcb->stack_base_ptr + tcb->adj_stack_size,
(void *)tcb->xcp.regs[REG_A1], (void *)tcb->xcp.regs[REG_A1],
(void *)tcb->xcp.regs[REG_A0], (void *)tcb->xcp.regs[REG_A0],
buffer, size); buffer, size, &skip);
leave_critical_section(flags); leave_critical_section(flags);
} }

View File

@ -38,8 +38,8 @@
* ARRAY and return the exact number of values stored. * ARRAY and return the exact number of values stored.
*/ */
#define backtrace(buffer, size) sched_backtrace(gettid(), buffer, size) # define backtrace(buffer, size) sched_backtrace(gettid(), buffer, size, 0)
#define dump_stack() sched_dumpstack(gettid()) # define dump_stack() sched_dumpstack(gettid())
#else #else
# define backtrace(buffer, size) 0 # define backtrace(buffer, size) 0

View File

@ -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 * tcb - Address of the task's TCB, NULL means dump the running task
* buffer - Return address from the corresponding stack frame * buffer - Return address from the corresponding stack frame
* size - Maximum number of addresses that can be stored in buffer * size - Maximum number of addresses that can be stored in buffer
* skip - number of addresses to be skipped
* *
* Returned Value: * Returned Value:
* up_backtrace() returns the number of addresses returned in buffer * 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 */ #endif /* CONFIG_ARCH_HAVE_BACKTRACE */
/**************************************************************************** /****************************************************************************

View File

@ -264,7 +264,7 @@ bool sched_idletask(void);
/* Task Backtrace */ /* 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); void sched_dumpstack(pid_t tid);
#undef EXTERN #undef EXTERN

View File

@ -45,7 +45,7 @@ SYSCALL_LOOKUP(sched_yield, 0)
SYSCALL_LOOKUP(nxsched_get_stackinfo, 2) SYSCALL_LOOKUP(nxsched_get_stackinfo, 2)
#ifdef CONFIG_SCHED_BACKTRACE #ifdef CONFIG_SCHED_BACKTRACE
SYSCALL_LOOKUP(sched_backtrace, 3) SYSCALL_LOOKUP(sched_backtrace, 4)
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP

View File

@ -64,7 +64,7 @@ backtrace_helper(FAR struct _Unwind_Context *ctx, FAR void *a)
* Skip it. * Skip it.
*/ */
if (arg->cnt != -1) if (arg->cnt >= 0)
{ {
arg->array[arg->cnt] = (FAR void *)_Unwind_GetIP(ctx); arg->array[arg->cnt] = (FAR void *)_Unwind_GetIP(ctx);
if (arg->cnt > 0) if (arg->cnt > 0)
@ -88,7 +88,7 @@ backtrace_helper(FAR struct _Unwind_Context *ctx, FAR void *a)
arg->cfa = cfa; arg->cfa = cfa;
} }
if (++arg->cnt == arg->size) if (++arg->cnt >= arg->size)
{ {
return _URC_END_OF_STACK; 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; struct trace_arg arg;
@ -120,7 +120,7 @@ int sched_backtrace(pid_t tid, FAR void **buffer, int size)
arg.array = buffer; arg.array = buffer;
arg.cfa = 0; arg.cfa = 0;
arg.size = size; arg.size = size;
arg.cnt = -1; arg.cnt = -skip - 1;
if (size <= 0) if (size <= 0)
{ {
@ -138,7 +138,7 @@ int sched_backtrace(pid_t tid, FAR void **buffer, int size)
--arg.cnt; --arg.cnt;
} }
return arg.cnt != -1 ? arg.cnt : 0; return arg.cnt > 0 ? arg.cnt : 0;
} }
#endif /* !CONFIG_ARCH_HAVE_BACKTRACE */ #endif /* !CONFIG_ARCH_HAVE_BACKTRACE */

View File

@ -29,7 +29,6 @@
#include <stdio.h> #include <stdio.h>
#include <syslog.h> #include <syslog.h>
#include <execinfo.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -54,38 +53,43 @@
void sched_dumpstack(pid_t tid) 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 #ifndef CONFIG_ALLSYMS
const char *format = " %0*p"; const char *format = " %0*p";
char line[DUMP_LINESZ + 1]; char line[DUMP_LINESZ + 1];
int ret = 0; int ret = 0;
#endif #endif
int size; int i;
int i;
size = sched_backtrace(tid, address, DUMP_DEPTH); size = sched_backtrace(tid, address, DUMP_DEPTH, skip);
if (size <= 0) if (size <= 0)
{
return;
}
#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)
{ {
syslog(LOG_EMERG, "backtrace|%2d:%s\n", tid, line); break;
ret = 0; }
#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)
{
syslog(LOG_EMERG, "backtrace|%2d:%s\n", tid, line);
ret = 0;
}
} }
}
#else #else
syslog(LOG_EMERG, "backtrace:\n"); syslog(LOG_EMERG, "backtrace:\n");
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
{ {
syslog(LOG_EMERG, "[%2d] [<%p>] %pS\n", syslog(LOG_EMERG, "[%2d] [<%p>] %pS\n",
tid, address[i], address[i]); tid, address[i], address[i]);
} }
#endif #endif
}
} }

View File

@ -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; 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);
} }

View File

@ -132,7 +132,7 @@
"sched_setscheduler","sched.h","","int","pid_t","int","const struct sched_param *" "sched_setscheduler","sched.h","","int","pid_t","int","const struct sched_param *"
"sched_unlock","sched.h","","int" "sched_unlock","sched.h","","int"
"sched_yield","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" "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 *" "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 *" "sem_clockwait","semaphore.h","","int","FAR sem_t *","clockid_t","FAR const struct timespec *"

Can't render this file because it has a wrong number of fields in line 2.