[Lldb-commits] [lldb] r119327 - /lldb/trunk/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp

Jason Molenda jmolenda at apple.com
Mon Nov 15 19:01:20 PST 2010


Author: jmolenda
Date: Mon Nov 15 21:01:20 2010
New Revision: 119327

URL: http://llvm.org/viewvc/llvm-project?rev=119327&view=rev
Log:
Add an UnwindPlan Row for the last instruction of a function when
we're using the stack pointer to define the CFA again.  Makes unwinds
while sitting at the 'ret' instruction work, assuming we have accurate
function address bounds.


Modified:
    lldb/trunk/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp?rev=119327&r1=119326&r2=119327&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp Mon Nov 15 21:01:20 2010
@@ -525,6 +525,7 @@
     int current_func_text_offset = 0;
     int current_sp_bytes_offset_from_cfa = 0;
     UnwindPlan::Row::RegisterLocation initial_regloc;
+    Error error;
 
     if (!m_cur_insn.IsValid())
     {
@@ -555,7 +556,6 @@
         int stack_offset, insn_len;
         int machine_regno;          // register numbers masked directly out of instructions
         uint32_t lldb_regno;        // register numbers in lldb's eRegisterKindLLDB numbering scheme
-        Error error;
 
         if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize)
         {
@@ -661,6 +661,43 @@
         current_func_text_offset += insn_len;
     }
     
+    // Now look at the byte at the end of the AddressRange for a limited attempt at describing the
+    // epilogue.  If this function is built -fomit-frame-pointer (so the CFA is defined in terms of the
+    // stack pointer) we'd need to profile every instruction which causes rsp to change to backtrace
+    // all the time.  But assuming the CFA is in terms of rbp most of the time, this one additional Row
+    // will be sufficient.
+
+    if (m_func_bounds.GetByteSize() > 2)
+    {
+        Address last_insn (m_func_bounds.GetBaseAddress());
+        last_insn.SetOffset (last_insn.GetOffset() + m_func_bounds.GetByteSize() - 1);
+        uint8_t bytebuf[1];
+        if (m_target.ReadMemory (last_insn, bytebuf, 1, error) != -1)
+        {
+            if (bytebuf[0] == 0xc3)   // ret aka retq
+            {
+                // Create a fresh, empty Row and RegisterLocation - don't mention any other registers
+                UnwindPlan::Row epi_row;
+                UnwindPlan::Row::RegisterLocation epi_regloc;
+
+                // When the ret instruction is about to be executed, here's our state
+                epi_row.SetOffset (m_func_bounds.GetByteSize() - 1);
+                epi_row.SetCFARegister (m_lldb_sp_regnum);
+                epi_row.SetCFAOffset (m_wordsize);
+               
+                // caller's stack pointer value before the call insn is the CFA address
+                epi_regloc.SetIsCFAPlusOffset (0);
+                epi_row.SetRegisterInfo (m_lldb_sp_regnum, epi_regloc);
+
+                // saved instruction pointer can be found at CFA - wordsize
+                epi_regloc.SetAtCFAPlusOffset (-m_wordsize);
+                epi_row.SetRegisterInfo (m_lldb_ip_regnum, epi_regloc);
+
+                unwind_plan.AppendRow (epi_row);
+            }
+        }
+    }
+    
     unwind_plan.SetSourceName ("assembly insn profiling");
 
     return true;





More information about the lldb-commits mailing list