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>
diff --git a/subsys/profiling/perf/backends/perf_riscv.c b/subsys/profiling/perf/backends/perf_riscv.c
index 43de474..3ef0994 100644
--- a/subsys/profiling/perf/backends/perf_riscv.c
+++ b/subsys/profiling/perf/backends/perf_riscv.c
@@ -12,6 +12,13 @@
 		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.
  * Return addresses are translated in corresponding function's names using .elf file.
@@ -75,6 +82,10 @@
 		if (idx >= size)
 			return 0;
 
+		if (!in_text_region((uintptr_t)fp[-1])) {
+			break;
+		}
+
 		buf[idx++] = (uintptr_t)fp[-1];
 		new_fp = (void **)fp[-2];
 
diff --git a/subsys/profiling/perf/backends/perf_x86.c b/subsys/profiling/perf/backends/perf_x86.c
index 1f21231..05f4207 100644
--- a/subsys/profiling/perf/backends/perf_x86.c
+++ b/subsys/profiling/perf/backends/perf_x86.c
@@ -13,6 +13,13 @@
 		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 */
 struct isf {
 	uint32_t ebp;
@@ -63,6 +70,10 @@
 		if (idx >= size)
 			return 0;
 
+		if (!in_text_region((uintptr_t)fp[1])) {
+			break;
+		}
+
 		buf[idx++] = (uintptr_t)fp[1];
 		void **new_fp = (void **)fp[0];
 
diff --git a/subsys/profiling/perf/backends/perf_x86_64.c b/subsys/profiling/perf/backends/perf_x86_64.c
index 7544501..d0386a0 100644
--- a/subsys/profiling/perf/backends/perf_x86_64.c
+++ b/subsys/profiling/perf/backends/perf_x86_64.c
@@ -13,6 +13,13 @@
 		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.
  * Return addresses are translated in corresponding function's names using .elf file.
@@ -49,6 +56,10 @@
 		if (idx >= size)
 			return 0;
 
+		if (!in_text_region((uintptr_t)fp[1])) {
+			break;
+		}
+
 		buf[idx++] = (uintptr_t)fp[1];
 		void **new_fp = (void **)fp[0];