diff options
author | Jason Molenda <jmolenda@apple.com> | 2014-08-04 21:26:55 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2014-08-04 21:26:55 +0000 |
commit | 300dfcd28db7c07be9f37ee0e6222e51b05e21c5 (patch) | |
tree | 820babf59f46bcde67e441ad7253938b827be33f /lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp | |
parent | 5f11f5f979f15b10034e22c0aad7542c600e58f7 (diff) | |
download | bcm5719-llvm-300dfcd28db7c07be9f37ee0e6222e51b05e21c5.tar.gz bcm5719-llvm-300dfcd28db7c07be9f37ee0e6222e51b05e21c5.zip |
Add code to AssemblyParse_x86::get_non_call_site_unwind_plan
to recognize an epilogue that ends with a jmp to
objc_retainAutoreleaseReturnValue instead of a ret instruction.
<rdar://problem/17889928>
llvm-svn: 214783
Diffstat (limited to 'lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp')
-rw-r--r-- | lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index caed96857b2..6df4bade548 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -697,17 +697,28 @@ loopnext: // Now look at the byte at the end of the AddressRange for a limited attempt at describing the // epilogue. We're looking for the sequence - // [ 0x5d ] mov %rbp, %rsp + // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) + // [ 0xc3 ] ret + + // or + + // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) + // [ 0xe9 xx xx xx xx ] jmp objc_retainAutoreleaseReturnValue (this is sometimes the final insn in the function) + + // or + + // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) // [ 0xc3 ] ret // [ 0xe8 xx xx xx xx ] call __stack_chk_fail (this is sometimes the final insn in the function) // We want to add a Row describing how to unwind when we're stopped on the 'ret' instruction where the // CFA is no longer defined in terms of rbp, but is now defined in terms of rsp like on function entry. + // (or the 'jmp' instruction in the second case) uint64_t ret_insn_offset = LLDB_INVALID_ADDRESS; Address end_of_fun(m_func_bounds.GetBaseAddress()); end_of_fun.SetOffset (end_of_fun.GetOffset() + m_func_bounds.GetByteSize()); - + if (m_func_bounds.GetByteSize() > 7) { uint8_t bytebuf[7]; @@ -716,16 +727,23 @@ loopnext: if (target->ReadMemory (last_seven_bytes, prefer_file_cache, bytebuf, 7, error) != static_cast<size_t>(-1)) { - if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov, ret + if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov & ret { ret_insn_offset = m_func_bounds.GetByteSize() - 1; } - else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov, ret, call + else if (bytebuf[1] == 0x5d && bytebuf[2] == 0xe9) // mov & jmp + { + // When the pc is sitting on the 'jmp' instruction, we have the same + // unwind state as if it was sitting on a 'ret' instruction. + ret_insn_offset = m_func_bounds.GetByteSize() - 5; + } + else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov & ret & call { ret_insn_offset = m_func_bounds.GetByteSize() - 6; } } - } else if (m_func_bounds.GetByteSize() > 2) + } + else if (m_func_bounds.GetByteSize() > 2) { uint8_t bytebuf[2]; Address last_two_bytes(end_of_fun); @@ -733,7 +751,7 @@ loopnext: if (target->ReadMemory (last_two_bytes, prefer_file_cache, bytebuf, 2, error) != static_cast<size_t>(-1)) { - if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov, ret + if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov & ret { ret_insn_offset = m_func_bounds.GetByteSize() - 1; } |