[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen staging] x86/traps: widen condition for logging top-of-stack



commit 445891bb8ea77ebc9bee98c4507b077d96928521
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Sep 24 10:48:44 2019 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Sep 24 10:48:44 2019 +0200

    x86/traps: widen condition for logging top-of-stack
    
    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 <jbeulich@xxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/traps.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 31d270b1ee..98919a0725 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -439,7 +439,7 @@ static void _show_trace(unsigned long sp, unsigned long 
__maybe_unused bp)
     {
         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));
     }
 }
 
@@ -482,7 +482,7 @@ static void _show_trace(unsigned long sp, unsigned long bp)
             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];
     }
@@ -511,21 +511,26 @@ static void show_trace(const struct cpu_user_regs *regs)
      */
     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++;
     }
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.