Despite -fno-omit-frame-pointer the compiler may omit the frame pointer,
often for relatively simple leaf functions. (To give a specific example,
the case I've run into this with is _pci_hide_device() and gcc 8.
Interestingly the even more simple neighboring iommu_has_feature() does
get a frame pointer set up, around just a single instruction. But this
may be a result of the size-of-asm() effects discussed elsewhere.)

Log the top-of-stack value if it looks valid _or_ if RIP looks invalid.

Also annotate all stack trace entries with a marker, to indicate their
origin:
R: register state
F: frame pointer based
S: raw stack contents

Signed-off-by: Jan Beulich <jbeul...@suse.com>
---
v3: Tag stack entries consistently, but differently than in v2.
v2: Re-base over changes to earlier patch.

--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -433,7 +433,7 @@ static void _show_trace(unsigned long sp
      {
          addr = *stack++;
          if ( is_active_kernel_text(addr) )
-            printk("   [<%p>] %pS\n", _p(addr), _p(addr));
+            printk("   [<%p>] S %pS\n", _p(addr), _p(addr));
      }
  }
  
@@ -476,7 +476,7 @@ static void _show_trace(unsigned long sp
              addr  = frame[1];
          }
  
-        printk("   [<%p>] %pS\n", _p(addr), _p(addr));
+        printk("   [<%p>] F %pS\n", _p(addr), _p(addr));
  
          low = (unsigned long)&frame[2];
      }
@@ -505,21 +505,26 @@ static void show_trace(const struct cpu_
       */
      if ( is_active_kernel_text(regs->rip) ||
           !is_active_kernel_text(tos) )
-        printk("   [<%p>] %pS\n", _p(regs->rip), _p(regs->rip));
-    else if ( fault )
+        printk("   [<%p>] R %pS\n", _p(regs->rip), _p(regs->rip));
+
+    if ( fault )
      {
          printk("   [Fault on access]\n");
          return;
      }
+
      /*
-     * Else RIP looks bad but the top of the stack looks good.  Perhaps we
-     * followed a wild function pointer? Lets assume the top of the stack is a
+     * If RIP looks bad or the top of the stack looks good, log the top of
+     * stack as well.  Perhaps we followed a wild function pointer, or we're
+     * in a function without frame pointer, or in a function prologue before
+     * the frame pointer gets set up?  Let's assume the top of the stack is a
       * return address; print it and skip past so _show_trace() doesn't print
       * it again.
       */
-    else
+    if ( !is_active_kernel_text(regs->rip) ||
+         is_active_kernel_text(tos) )
      {
-        printk("   [<%p>] %pS\n", _p(tos), _p(tos));
+        printk("   [<%p>] S %pS\n", _p(tos), _p(tos));
          sp++;
      }
  

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to