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

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


The following commit(s) were added to refs/heads/master by this push:
     new a5bc9a9da2 arch/x86_64:Add FP backtrace function
a5bc9a9da2 is described below

commit a5bc9a9da2c92aa186132457cd1e188f22d088bf
Author: liwenxiang1 <[email protected]>
AuthorDate: Fri Sep 20 13:54:19 2024 +0800

    arch/x86_64:Add FP backtrace function
    
    Signed-off-by: liwenxiang1 <[email protected]>
---
 arch/Kconfig                                   |   1 +
 arch/x86_64/Kconfig                            |  18 +++
 arch/x86_64/src/common/Toolchain.defs          |   4 +
 arch/x86_64/src/intel64/CMakeLists.txt         |   4 +
 arch/x86_64/src/intel64/Make.defs              |   4 +
 arch/x86_64/src/intel64/intel64_backtrace_fp.c | 169 +++++++++++++++++++++++++
 arch/x86_64/src/intel64/intel64_handlers.c     |   2 +-
 arch/x86_64/src/intel64/intel64_initialstate.c |   2 +-
 arch/x86_64/src/intel64/intel64_regdump.c      |  13 --
 9 files changed, 202 insertions(+), 15 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 2ec252ecae..c4c095ddcc 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -141,6 +141,7 @@ config ARCH_X86_64
        select PCI_LATE_DRIVERS_REGISTER if PCI
        select LIBC_ARCH_ELF_64BIT if LIBC_ARCH_ELF
        select ARCH_TOOLCHAIN_GNU
+       select ARCH_HAVE_BACKTRACE
        ---help---
                x86-64 architectures.
 
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index fad91e08cf..ebc840d94f 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -49,6 +49,24 @@ config ARCH_CHIP_X86_64_CUSTOM
 
 endchoice
 
+if SCHED_BACKTRACE
+choice
+       prompt "Choose x86_64 unwinder"
+       default X86_64_UNWINDER_FRAME_POINTER
+       ---help---
+               This determines which method will be used for unwinding nuttx 
stack
+               traces for debug.
+
+config X86_64_UNWINDER_FRAME_POINTER
+       bool "Frame pointer unwinder"
+       select FRAME_POINTER
+       ---help---
+               This option enables the frame pointer unwinder for unwinding
+               nuttx stack traces.
+
+endchoice # Choose x86_64 unwinder
+endif
+
 # CPU features
 
 config ARCH_HAVE_MMX
diff --git a/arch/x86_64/src/common/Toolchain.defs 
b/arch/x86_64/src/common/Toolchain.defs
index b3f36be40f..d7a07fb0fe 100644
--- a/arch/x86_64/src/common/Toolchain.defs
+++ b/arch/x86_64/src/common/Toolchain.defs
@@ -28,6 +28,10 @@ else ifeq ($(CONFIG_DEBUG_FULLOPT),y)
   ARCHOPTIMIZATION += -Os
 endif
 
+ifeq ($(CONFIG_FRAME_POINTER),y)
+  ARCHOPTIMIZATION += -fno-omit-frame-pointer -fno-optimize-sibling-calls
+endif
+
 ARCHCPUFLAGS = -fPIC -fno-stack-protector -mno-red-zone -mrdrnd
 ARCHPICFLAGS = -fPIC
 ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
diff --git a/arch/x86_64/src/intel64/CMakeLists.txt 
b/arch/x86_64/src/intel64/CMakeLists.txt
index f5b1a76977..8985d39ea8 100644
--- a/arch/x86_64/src/intel64/CMakeLists.txt
+++ b/arch/x86_64/src/intel64/CMakeLists.txt
@@ -48,6 +48,10 @@ set(SRCS
     intel64_check_capability.c
     intel64_cpu.c)
 
+if(CONFIG_x86_64_UNWINDER_FRAME_POINTER)
+  list(APPEND SRCS intel64_backtrace_fp.c)
+endif()
+
 if(CONFIG_MM_PGALLOC)
   list(APPEND SRCS intel64_pgalloc.c)
 endif()
diff --git a/arch/x86_64/src/intel64/Make.defs 
b/arch/x86_64/src/intel64/Make.defs
index e1c8579c97..4700b93794 100644
--- a/arch/x86_64/src/intel64/Make.defs
+++ b/arch/x86_64/src/intel64/Make.defs
@@ -34,6 +34,10 @@ CHIP_CSRCS  = intel64_start.c intel64_handlers.c 
intel64_idle.c intel64_lowsetup
 CHIP_CSRCS += intel64_serial.c intel64_rng.c intel64_check_capability.c
 CHIP_CSRCS += intel64_cpu.c
 
+ifeq ($(CONFIG_x86_64_UNWINDER_FRAME_POINTER),y)
+  CMN_CSRCS += intel64_backtrace_fp.c
+endif
+
 ifeq ($(CONFIG_MM_PGALLOC),y)
 CHIP_CSRCS += intel64_pgalloc.c
 endif
diff --git a/arch/x86_64/src/intel64/intel64_backtrace_fp.c 
b/arch/x86_64/src/intel64/intel64_backtrace_fp.c
new file mode 100644
index 0000000000..dab1f36a57
--- /dev/null
+++ b/arch/x86_64/src/intel64/intel64_backtrace_fp.c
@@ -0,0 +1,169 @@
+/****************************************************************************
+ * arch/x86_64/src/intel64/intel64_backtrace_fp.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/arch.h>
+
+#include "sched/sched.h"
+
+#include <x86_64_internal.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: backtrace
+ *
+ * Description:
+ *  backtrace() parsing the return address through frame pointer
+ *
+ ****************************************************************************/
+
+nosanitize_address
+static int backtrace(uintptr_t *base, uintptr_t *limit,
+                     uintptr_t *rbp, uintptr_t *rip,
+                     void **buffer, int size, int *skip)
+{
+  int i = 0;
+
+  if (rip)
+    {
+      if ((*skip)-- <= 0)
+        {
+          buffer[i++] = rip;
+        }
+    }
+
+  for (; i < size; rbp = (uintptr_t *)(*rbp))
+    {
+      if (rbp > limit || rbp < base ||
+         *(uintptr_t *)rbp == 0)
+        {
+          break;
+        }
+
+      if ((*skip)-- <= 0)
+        {
+          buffer[i++] = (uintptr_t *)(*(rbp + 1));
+        }
+    }
+
+  return i;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_backtrace
+ *
+ * Description:
+ *  up_backtrace()  returns  a backtrace for the TCB, in the array
+ *  pointed to by buffer.  A backtrace is the series of currently active
+ *  function calls for the program.  Each item in the array pointed to by
+ *  buffer is of type void *, and is the return address from the
+ *  corresponding stack frame.  The size argument specifies the maximum
+ *  number of addresses that can be stored in buffer.   If  the backtrace is
+ *  larger than size, then the addresses corresponding to the size most
+ *  recent function calls are returned; to obtain the complete backtrace,
+ *  make sure that buffer and size are large enough.
+ *
+ * Input Parameters:
+ *   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
+ *
+ * Assumptions:
+ *   Have to make sure tcb keep safe during function executing, it means
+ *   1. Tcb have to be self or not-running.  In SMP case, the running task
+ *      PC & SP cannot be backtrace, as whose get from tcb is not the newest.
+ *   2. Tcb have to keep not be freed.  In task exiting case, have to
+ *      make sure the tcb get from pid and up_backtrace in one critical
+ *      section procedure.
+ *
+ ****************************************************************************/
+
+int up_backtrace(struct tcb_s *tcb,
+                 void **buffer, int size, int skip)
+{
+  struct tcb_s *rtcb = running_task();
+  int ret;
+
+  if (size <= 0 || !buffer)
+    {
+      return 0;
+    }
+
+  if (tcb == NULL || tcb == rtcb)
+    {
+      if (up_interrupt_context())
+        {
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+          void *istackbase = (void *)up_get_intstackbase(this_cpu());
+
+          ret = backtrace(istackbase,
+                          istackbase + IRQ_STACK_SIZE,
+                          (void *)__builtin_frame_address(0),
+                          NULL, buffer, size, &skip);
+#else
+          ret = backtrace(rtcb->stack_base_ptr,
+                          rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                          (void *)__builtin_frame_address(0),
+                          NULL, buffer, size, &skip);
+#endif /* CONFIG_ARCH_INTERRUPTSTACK > 3 */
+          if (ret < size)
+            {
+              ret += backtrace(rtcb->stack_base_ptr,
+                               rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                               (void *)up_current_regs()[REG_RBP],
+                               (void *)up_current_regs()[REG_RIP],
+                               &buffer[ret], size - ret, &skip);
+            }
+        }
+      else
+        {
+          ret = backtrace(rtcb->stack_base_ptr,
+                          rtcb->stack_base_ptr + rtcb->adj_stack_size,
+                          (void *)__builtin_frame_address(0),
+                          NULL, buffer, size, &skip);
+        }
+    }
+  else
+    {
+      ret = backtrace(tcb->stack_base_ptr,
+                      tcb->stack_base_ptr + tcb->adj_stack_size,
+                      (void *)tcb->xcp.regs[REG_RBP],
+                      (void *)tcb->xcp.regs[REG_RIP],
+                      buffer, size, &skip);
+    }
+
+  return ret;
+}
diff --git a/arch/x86_64/src/intel64/intel64_handlers.c 
b/arch/x86_64/src/intel64/intel64_handlers.c
index a4ad29c015..28a77e1c73 100644
--- a/arch/x86_64/src/intel64/intel64_handlers.c
+++ b/arch/x86_64/src/intel64/intel64_handlers.c
@@ -175,7 +175,7 @@ uint64_t *isr_handler(uint64_t *regs, uint64_t irq)
                "with error code %" PRId64 ":\n",
                irq, regs[REG_ERRCODE]);
 
-        up_dump_register(regs);
+        PANIC_WITH_REGS("panic", regs);
 
         up_trash_cpu();
         break;
diff --git a/arch/x86_64/src/intel64/intel64_initialstate.c 
b/arch/x86_64/src/intel64/intel64_initialstate.c
index e03f6ada85..196f9d329e 100644
--- a/arch/x86_64/src/intel64/intel64_initialstate.c
+++ b/arch/x86_64/src/intel64/intel64_initialstate.c
@@ -123,7 +123,7 @@ void up_initial_state(struct tcb_s *tcb)
    */
 
   xcp->regs[REG_RSP]    = (uint64_t)xcp->regs - 8;
-  xcp->regs[REG_RBP]    = (uint64_t)xcp->regs - 8;
+  xcp->regs[REG_RBP]    = 0;
 
   /* Save the task entry point */
 
diff --git a/arch/x86_64/src/intel64/intel64_regdump.c 
b/arch/x86_64/src/intel64/intel64_regdump.c
index d1aa274a04..87356f6e13 100644
--- a/arch/x86_64/src/intel64/intel64_regdump.c
+++ b/arch/x86_64/src/intel64/intel64_regdump.c
@@ -154,18 +154,5 @@ void up_dump_register(void *dumpregs)
          regs[REG_R14], regs[REG_R15]);
   _alert("Dumping Stack (+-64 bytes):\n");
 
-  if (regs[REG_RSP] > 0 && regs[REG_RSP] < 0x1000000)
-    {
-      print_mem((void *)regs[REG_RSP] - 512,
-          128 * 0x200000 - regs[REG_RSP] + 512);
-    }
-  else
-    {
-      print_mem((void *)regs[REG_RSP] - 512, 1024);
-    }
-
-#ifdef CONFIG_DEBUG_NOOPT
-  backtrace(regs[REG_RBP]);
-#endif
   _alert("-----------------------------------------\n");
 }

Reply via email to