subsys/profiling: fix extra frame in the traces

Check if the frame is within the text address before saving
into the buffer, this eliminates the extra, uninitialized frame
at the end of the unwind.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
Yong Cong Sin 2024-08-16 17:08:23 +08:00 committed by Henrik Brix Andersen
commit 44c070fdcd
3 changed files with 33 additions and 0 deletions

View file

@ -12,6 +12,13 @@ static bool valid_stack(uintptr_t addr, k_tid_t current)
addr < current->stack_info.start + current->stack_info.size; addr < current->stack_info.start + current->stack_info.size;
} }
static inline bool in_text_region(uintptr_t addr)
{
extern uintptr_t __text_region_start, __text_region_end;
return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end);
}
/* /*
* This function use frame pointers to unwind stack and get trace of return addresses. * This function use frame pointers to unwind stack and get trace of return addresses.
* Return addresses are translated in corresponding function's names using .elf file. * Return addresses are translated in corresponding function's names using .elf file.
@ -75,6 +82,10 @@ size_t arch_perf_current_stack_trace(uintptr_t *buf, size_t size)
if (idx >= size) if (idx >= size)
return 0; return 0;
if (!in_text_region((uintptr_t)fp[-1])) {
break;
}
buf[idx++] = (uintptr_t)fp[-1]; buf[idx++] = (uintptr_t)fp[-1];
new_fp = (void **)fp[-2]; new_fp = (void **)fp[-2];

View file

@ -13,6 +13,13 @@ static bool valid_stack(uintptr_t addr, k_tid_t current)
addr < current->stack_info.start + current->stack_info.size; addr < current->stack_info.start + current->stack_info.size;
} }
static inline bool in_text_region(uintptr_t addr)
{
extern uintptr_t __text_region_start, __text_region_end;
return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end);
}
/* interruption stack frame */ /* interruption stack frame */
struct isf { struct isf {
uint32_t ebp; uint32_t ebp;
@ -63,6 +70,10 @@ size_t arch_perf_current_stack_trace(uintptr_t *buf, size_t size)
if (idx >= size) if (idx >= size)
return 0; return 0;
if (!in_text_region((uintptr_t)fp[1])) {
break;
}
buf[idx++] = (uintptr_t)fp[1]; buf[idx++] = (uintptr_t)fp[1];
void **new_fp = (void **)fp[0]; void **new_fp = (void **)fp[0];

View file

@ -13,6 +13,13 @@ static bool valid_stack(uintptr_t addr, k_tid_t current)
addr < current->stack_info.start + current->stack_info.size; addr < current->stack_info.start + current->stack_info.size;
} }
static inline bool in_text_region(uintptr_t addr)
{
extern uintptr_t __text_region_start, __text_region_end;
return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end);
}
/* /*
* This function use frame pointers to unwind stack and get trace of return addresses. * This function use frame pointers to unwind stack and get trace of return addresses.
* Return addresses are translated in corresponding function's names using .elf file. * Return addresses are translated in corresponding function's names using .elf file.
@ -49,6 +56,10 @@ size_t arch_perf_current_stack_trace(uintptr_t *buf, size_t size)
if (idx >= size) if (idx >= size)
return 0; return 0;
if (!in_text_region((uintptr_t)fp[1])) {
break;
}
buf[idx++] = (uintptr_t)fp[1]; buf[idx++] = (uintptr_t)fp[1];
void **new_fp = (void **)fp[0]; void **new_fp = (void **)fp[0];