sched/backtrace: Dump the complete stack regardless the depth
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
9eecd4c5e2
commit
dd942f0b04
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
#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)
|
||||
size = sched_backtrace(tid, address, DUMP_DEPTH, skip);
|
||||
if (size <= 0)
|
||||
{
|
||||
syslog(LOG_EMERG, "backtrace|%2d:%s\n", tid, line);
|
||||
ret = 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)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
Loading…
x
Reference in New Issue
Block a user