[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