diff options
Diffstat (limited to 'lldb/source/Plugins/Process')
37 files changed, 0 insertions, 12462 deletions
diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp index 4509eb7f150..57db2ad0405 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ThreadMacOSX.cpp @@ -23,8 +23,6 @@ #include "lldb/Breakpoint/WatchpointLocation.h" #include "lldb/Core/StreamString.h" #include "lldb/Target/Unwind.h" -#include "LibUnwindRegisterContext.h" -#include "UnwindLibUnwind.h" #include "UnwindMacOSXFrameBackchain.h" using namespace lldb; diff --git a/lldb/source/Plugins/Process/Utility/LibUnwindRegisterContext.cpp b/lldb/source/Plugins/Process/Utility/LibUnwindRegisterContext.cpp deleted file mode 100644 index 96bba7e9b99..00000000000 --- a/lldb/source/Plugins/Process/Utility/LibUnwindRegisterContext.cpp +++ /dev/null @@ -1,336 +0,0 @@ -//===-- LibUnwindRegisterContext.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LibUnwindRegisterContext.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Target/Thread.h" -// Project includes - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// LibUnwindRegisterContext constructor -//---------------------------------------------------------------------- -LibUnwindRegisterContext::LibUnwindRegisterContext -( - Thread &thread, - StackFrame *frame, - const lldb_private::unw_cursor_t& unwind_cursor -) : - RegisterContext (thread, frame), - m_unwind_cursor (unwind_cursor), - m_unwind_cursor_is_valid (true) -{ -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -LibUnwindRegisterContext::~LibUnwindRegisterContext() -{ -} - -void -LibUnwindRegisterContext::Invalidate () -{ - m_unwind_cursor_is_valid = false; -} - -size_t -LibUnwindRegisterContext::GetRegisterCount () -{ - return m_thread.GetRegisterContext()->GetRegisterCount(); -} - -const lldb::RegisterInfo * -LibUnwindRegisterContext::GetRegisterInfoAtIndex (uint32_t reg) -{ - return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); -} - -size_t -LibUnwindRegisterContext::GetRegisterSetCount () -{ - return m_thread.GetRegisterContext()->GetRegisterSetCount(); -} - - - -const lldb::RegisterSet * -LibUnwindRegisterContext::GetRegisterSet (uint32_t reg_set) -{ - return m_thread.GetRegisterContext()->GetRegisterSet (reg_set); -} - - - -bool -LibUnwindRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value) -{ - if (m_unwind_cursor_is_valid == false) - return false; - - // Read the register - unw_word_t reg_value; - if (unw_get_reg (&m_unwind_cursor, reg, ®_value) != UNW_ESUCCESS) - return false; - - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); - switch (reg_info->encoding) - { - case eEncodingUint: - switch (reg_info->byte_size) - { - case 1: - case 2: - case 4: - value = (uint32_t)reg_value; - return true; - - case 8: - value = (uint64_t)reg_value; - return true; - } - break; - - case eEncodingSint: - switch (reg_info->byte_size) - { - case 1: - case 2: - case 4: - value = (int32_t)reg_value; - return true; - - case 8: - value = (int64_t)reg_value; - return true; - } - break; - - case eEncodingIEEE754: - if (reg_info->byte_size > sizeof(unw_word_t)) - return false; - - switch (reg_info->byte_size) - { - case sizeof (float): - if (sizeof (float) == sizeof(uint32_t)) - { - value = (uint32_t)reg_value; - return true; - } - else if (sizeof (float) == sizeof(uint64_t)) - { - value = (uint64_t)reg_value; - return true; - } - break; - - case sizeof (double): - if (sizeof (double) == sizeof(uint32_t)) - { - value = (uint32_t)reg_value; - return true; - } - else if (sizeof (double) == sizeof(uint64_t)) - { - value = (uint64_t)reg_value; - return true; - } - break; - - case sizeof (long double): - if (sizeof (long double) == sizeof(uint32_t)) - { - value = (uint32_t)reg_value; - return true; - } - else if (sizeof (long double) == sizeof(uint64_t)) - { - value = (uint64_t)reg_value; - return true; - } - break; - } - break; - - default: - break; - } - return false; -} - - -bool -LibUnwindRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data) -{ - Scalar reg_value; - - if (ReadRegisterValue (reg, reg_value)) - { - if (reg_value.GetData(data)) - { - // "reg_value" is local and now "data" points to the data within - // "reg_value", so we must make a copy that will live within "data" - DataBufferSP data_sp (new DataBufferHeap (data.GetDataStart(), data.GetByteSize())); - data.SetData (data_sp, 0, data.GetByteSize()); - return true; - } - } - return false; -} - - -bool -LibUnwindRegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value) -{ - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); - if (reg_info == NULL) - return false; - unw_word_t reg_value = 0; - switch (value.GetType()) - { - case Scalar::e_void: - return false; - - case Scalar::e_sint: reg_value = value.SInt(); break; - case Scalar::e_uint: reg_value = value.UInt(); break; - case Scalar::e_slong: reg_value = value.SLong(); break; - case Scalar::e_ulong: reg_value = value.ULong(); break; - case Scalar::e_slonglong: reg_value = value.SLongLong(); break; - case Scalar::e_ulonglong: reg_value = value.ULongLong(); break; - case Scalar::e_float: - if (sizeof (float) == sizeof (unsigned int)) - reg_value = value.UInt(); - else if (sizeof (float) == sizeof (unsigned long)) - reg_value = value.ULong(); - else if (sizeof (float) == sizeof (unsigned long long)) - reg_value = value.ULongLong(); - else - return false; - break; - - case Scalar::e_double: - if (sizeof (double) == sizeof (unsigned int)) - reg_value = value.UInt(); - else if (sizeof (double) == sizeof (unsigned long)) - reg_value = value.ULong(); - else if (sizeof (double) == sizeof (unsigned long long)) - reg_value = value.ULongLong(); - else - return false; - break; - - case Scalar::e_long_double: - if (sizeof (long double) == sizeof (unsigned int)) - reg_value = value.UInt(); - else if (sizeof (long double) == sizeof (unsigned long)) - reg_value = value.ULong(); - else if (sizeof (long double) == sizeof (unsigned long long)) - reg_value = value.ULongLong(); - else - return false; - break; - } - - return unw_set_reg (&m_unwind_cursor, reg, reg_value) == UNW_ESUCCESS; -} - - -bool -LibUnwindRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset) -{ - const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); - - if (reg_info == NULL) - return false; - if (reg_info->byte_size > sizeof (unw_word_t)) - return false; - - Scalar value; - uint32_t offset = data_offset; - - switch (reg_info->encoding) - { - case eEncodingUint: - if (reg_info->byte_size <= 4) - value = data.GetMaxU32 (&offset, reg_info->byte_size); - else if (reg_info->byte_size <= 8) - value = data.GetMaxU64 (&offset, reg_info->byte_size); - else - return false; - break; - - case eEncodingSint: - if (reg_info->byte_size <= 4) - value = (int32_t)data.GetMaxU32 (&offset, reg_info->byte_size); - else if (reg_info->byte_size <= 8) - value = data.GetMaxS64 (&offset, reg_info->byte_size); - else - return false; - break; - - case eEncodingIEEE754: - switch (reg_info->byte_size) - { - case sizeof (float): - value = data.GetFloat (&offset); - break; - - case sizeof (double): - value = data.GetDouble (&offset); - break; - - case sizeof (long double): - value = data.GetLongDouble (&offset); - break; - default: - return false; - } - - default: - return false; - } - return WriteRegisterValue (reg, value); -} - - -bool -LibUnwindRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) -{ - // libunwind frames can't handle this it doesn't always have all register - // values. This call should only be called on frame zero anyway so there - // shouldn't be any problem - return false; -} - -bool -LibUnwindRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) -{ - // Since this class doesn't respond to "ReadAllRegisterValues()", it must - // not have been the one that saved all the register values. So we just let - // the thread's register context (the register context for frame zero) do - // the writing. - return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp); -} - - -uint32_t -LibUnwindRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) -{ - return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num); -} - diff --git a/lldb/source/Plugins/Process/Utility/LibUnwindRegisterContext.h b/lldb/source/Plugins/Process/Utility/LibUnwindRegisterContext.h deleted file mode 100644 index bd7d8bd3bea..00000000000 --- a/lldb/source/Plugins/Process/Utility/LibUnwindRegisterContext.h +++ /dev/null @@ -1,83 +0,0 @@ -//===-- LibUnwindRegisterContext.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_LibUnwindRegisterContext_h_ -#define lldb_LibUnwindRegisterContext_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/RegisterContext.h" - -#include "libunwind/include/libunwind.h" - -class LibUnwindRegisterContext : public lldb_private::RegisterContext -{ -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - LibUnwindRegisterContext (lldb_private::Thread &thread, - lldb_private::StackFrame *frame, - const lldb_private::unw_cursor_t &unwind_cursor); - - virtual - ~LibUnwindRegisterContext (); - - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - virtual void - Invalidate (); - - virtual size_t - GetRegisterCount (); - - virtual const lldb::RegisterInfo * - GetRegisterInfoAtIndex (uint32_t reg); - - virtual size_t - GetRegisterSetCount (); - - virtual const lldb::RegisterSet * - GetRegisterSet (uint32_t reg_set); - - virtual bool - ReadRegisterValue (uint32_t reg, lldb_private::Scalar &value); - - virtual bool - ReadRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data); - - virtual bool - ReadAllRegisterValues (lldb::DataBufferSP &data_sp); - - virtual bool - WriteRegisterValue (uint32_t reg, const lldb_private::Scalar &value); - - virtual bool - WriteRegisterBytes (uint32_t reg, lldb_private::DataExtractor &data, uint32_t data_offset); - - virtual bool - WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); - - virtual uint32_t - ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num); - -private: - lldb_private::unw_cursor_t m_unwind_cursor; - bool m_unwind_cursor_is_valid; - //------------------------------------------------------------------ - // For LibUnwindRegisterContext only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (LibUnwindRegisterContext); -}; - -#endif // lldb_LibUnwindRegisterContext_h_ diff --git a/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp b/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp deleted file mode 100644 index 7f6f1759bdb..00000000000 --- a/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp +++ /dev/null @@ -1,320 +0,0 @@ -//===-- MacOSXLibunwindCallbacks.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_MacOSXLibunwindCallbacks_cpp_ -#define liblldb_MacOSXLibunwindCallbacks_cpp_ -#if defined(__cplusplus) - -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/FileSpec.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" - -#include "lldb/lldb-enumerations.h" -#include "llvm-c/EnhancedDisassembly.h" - -#include "libunwind/include/libunwind.h" - -using namespace lldb; - -namespace lldb_private { - -/* Don't implement (libunwind does not use) - find_proc_info - put_unwind_info - get_dyn_info_list_addr - access_mem - resume -*/ -/* - Should implement (not needed yet) - access_fpreg - access_vecreg - proc_is_sigtramp - proc_is_inferior_function_call - access_reg_inf_func_call -*/ - -static int -access_reg (lldb_private::unw_addr_space_t as, lldb_private::unw_regnum_t regnum, lldb_private::unw_word_t *valp, int write, void *arg) -{ - if (arg == 0) - return -1; - Thread *th = (Thread *) arg; - /* FIXME Only support reading for now. */ - if (write == 1) - return -1; - if (th->GetRegisterContext()->GetRegisterInfoAtIndex(regnum) == NULL) - return -1; - DataExtractor de; - if (!th->GetRegisterContext()->ReadRegisterBytes (regnum, de)) - return -1; - memcpy (valp, de.GetDataStart(), de.GetByteSize()); - return UNW_ESUCCESS; -} - -static int -get_proc_name (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t ip, char *bufp, size_t buf_len, lldb_private::unw_word_t *offp, void *arg) -{ - if (arg == 0) - return -1; - Thread *thread = (Thread *) arg; - Target &target = thread->GetProcess().GetTarget(); - Address addr; - if (!target.GetSectionLoadList().ResolveLoadAddress(ip, addr)) - return -1; - - SymbolContext sc; - if (!target.GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction, sc)) - return -1; - if (!sc.symbol) - return -1; - strlcpy (bufp, sc.symbol->GetMangled().GetMangledName().AsCString(""), buf_len); - if (offp) - *offp = addr.GetLoadAddress(&target) - sc.symbol->GetValue().GetLoadAddress(&target); - return UNW_ESUCCESS; -} - -static int -find_image_info (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t load_addr, lldb_private::unw_word_t *mh, - lldb_private::unw_word_t *text_start, lldb_private::unw_word_t *text_end, - lldb_private::unw_word_t *eh_frame, lldb_private::unw_word_t *eh_frame_len, - lldb_private::unw_word_t *compact_unwind_start, lldb_private::unw_word_t *compact_unwind_len, void *arg) -{ - if (arg == 0) - return -1; - Thread *thread = (Thread *) arg; - Target &target = thread->GetProcess().GetTarget(); - Address addr; - if (!target.GetSectionLoadList().ResolveLoadAddress(load_addr, addr)) - return -1; - - SymbolContext sc; - if (!target.GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextModule, sc)) - return -1; - - SectionList *sl = sc.module_sp->GetObjectFile()->GetSectionList(); - static ConstString g_segment_name_TEXT("__TEXT"); - SectionSP text_segment_sp(sl->FindSectionByName(g_segment_name_TEXT)); - if (!text_segment_sp) - return -1; - - *mh = text_segment_sp->GetLoadBaseAddress (&target); - *text_start = text_segment_sp->GetLoadBaseAddress (&target); - *text_end = *text_start + text_segment_sp->GetByteSize(); - - static ConstString g_section_name_eh_frame ("__eh_frame"); - SectionSP eh_frame_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_eh_frame); - if (eh_frame_section_sp.get()) { - *eh_frame = eh_frame_section_sp->GetLoadBaseAddress (&target); - *eh_frame_len = eh_frame_section_sp->GetByteSize(); - } else { - *eh_frame = 0; - *eh_frame_len = 0; - } - - static ConstString g_section_name_unwind_info ("__unwind_info"); - SectionSP unwind_info_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_unwind_info); - if (unwind_info_section_sp.get()) { - *compact_unwind_start = unwind_info_section_sp->GetLoadBaseAddress (&target); - *compact_unwind_len = unwind_info_section_sp->GetByteSize(); - } else { - *compact_unwind_start = 0; - *compact_unwind_len = 0; - } - return UNW_ESUCCESS; -} - -static int -get_proc_bounds (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t ip, lldb_private::unw_word_t *low, lldb_private::unw_word_t *high, void *arg) -{ - if (arg == 0) - return -1; - Thread *thread = (Thread *) arg; - Target &target = thread->GetProcess().GetTarget(); - Address addr; - if (!target.GetSectionLoadList().ResolveLoadAddress(ip, addr)) - return -1; - SymbolContext sc; - if (!target.GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction | eSymbolContextSymbol, sc)) - return -1; - if (sc.function) - { - lldb::addr_t start, len; - start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(&target); - len = sc.function->GetAddressRange().GetByteSize(); - if (start == LLDB_INVALID_ADDRESS || len == LLDB_INVALID_ADDRESS) - return -1; - *low = start; - *high = start + len; - return UNW_ESUCCESS; - } - if (sc.symbol) - { - lldb::addr_t start, len; - start = sc.symbol->GetAddressRangeRef().GetBaseAddress().GetLoadAddress(&target); - len = sc.symbol->GetAddressRangeRef().GetByteSize(); - if (start == LLDB_INVALID_ADDRESS) - return -1; - *low = start; - if (len != LLDB_INVALID_ADDRESS) - *high = start + len; - else - *high = 0; - return UNW_ESUCCESS; - } - return -1; -} - -static int -access_raw (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, lldb_private::unw_word_t extent, uint8_t *valp, int write, void *arg) -{ - if (arg == 0) - return -1; - Thread *th = (Thread *) arg; - /* FIXME Only support reading for now. */ - if (write == 1) - return -1; - - Error error; - if (th->GetProcess().ReadMemory (addr, valp, extent, error) != extent) - return -1; - return UNW_ESUCCESS; -} - - -static int -reg_info -( - lldb_private::unw_addr_space_t as, - lldb_private::unw_regnum_t regnum, - lldb_private::unw_regtype_t *type, - char *buf, - size_t buflen, - void *arg -) -{ - if (arg == 0) - return -1; - Thread *th = (Thread *) arg; - RegisterContext *regc = th->GetRegisterContext(); - if (regnum > regc->GetRegisterCount()) - { - *type = UNW_NOT_A_REG; - return UNW_ESUCCESS; - } - - const char *name = regc->GetRegisterName (regnum); - if (name == NULL) - { - *type = UNW_NOT_A_REG; - return UNW_ESUCCESS; - } - strlcpy (buf, name, buflen); - - const lldb::RegisterInfo *reginfo = regc->GetRegisterInfoAtIndex (regnum); - if (reginfo == NULL || reginfo->encoding == eEncodingInvalid) - { - *type = UNW_NOT_A_REG; - return UNW_ESUCCESS; - } - if (reginfo->encoding == eEncodingUint || reginfo->encoding == eEncodingSint) - *type = UNW_INTEGER_REG; - if (reginfo->encoding == eEncodingIEEE754) - *type = UNW_FLOATING_POINT_REG; - if (reginfo->encoding == eEncodingVector) - *type = UNW_VECTOR_REG; - - return UNW_ESUCCESS; -} - - -static int -read_byte_for_edis (uint8_t *buf, uint64_t addr, void *arg) -{ - if (arg == 0) - return -1; - Thread *th = (Thread *) arg; - DataBufferHeap onebyte(1, 0); - Error error; - if (th->GetProcess().ReadMemory (addr, onebyte.GetBytes(), onebyte.GetByteSize(), error) != 1) - return -1; - *buf = onebyte.GetBytes()[0]; - return UNW_ESUCCESS; -} - -static int -instruction_length (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, int *length, void *arg) -{ - EDDisassemblerRef disasm; - EDInstRef cur_insn; - - if (arg == 0) - return -1; - Thread *thread = (Thread *) arg; - Target &target = thread->GetProcess().GetTarget(); - - const ArchSpec::CPU arch_cpu = target.GetArchitecture ().GetGenericCPUType(); - - if (arch_cpu == ArchSpec::eCPU_i386) - { - if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0) - return -1; - } - else if (arch_cpu == ArchSpec::eCPU_x86_64) - { - if (EDGetDisassembler (&disasm, "x86_64-apple-darwin", kEDAssemblySyntaxX86ATT) != 0) - return -1; - } - else - { - return -1; - } - - if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr, arg) != 1) - return -1; - *length = EDInstByteSize (cur_insn); - EDReleaseInst (cur_insn); - return UNW_ESUCCESS; -} - -lldb_private::unw_accessors_t -get_macosx_libunwind_callbacks () { - lldb_private::unw_accessors_t ap; - bzero (&ap, sizeof (lldb_private::unw_accessors_t)); - ap.find_proc_info = NULL; - ap.put_unwind_info = NULL; - ap.get_dyn_info_list_addr = NULL; - ap.find_image_info = find_image_info; - ap.access_mem = NULL; - ap.access_reg = access_reg; - ap.access_fpreg = NULL; - ap.access_vecreg = NULL; - ap.resume = NULL; - ap.get_proc_name = get_proc_name; - ap.get_proc_bounds = get_proc_bounds; - ap.access_raw = access_raw; - ap.reg_info = reg_info; - ap.proc_is_sigtramp = NULL; - ap.proc_is_inferior_function_call = NULL; - ap.access_reg_inf_func_call = NULL; - ap.instruction_length = instruction_length; - return ap; -} - - -} // namespace lldb_private - -#endif // #if defined(__cplusplus) -#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_cpp_ diff --git a/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.h b/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.h deleted file mode 100644 index 78bd27b2ad3..00000000000 --- a/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.h +++ /dev/null @@ -1,22 +0,0 @@ -//===-- MacOSXLibunwindCallbacks.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_MacOSXLibunwindCallbacks_h_ -#define liblldb_MacOSXLibunwindCallbacks_h_ -#if defined(__cplusplus) - -namespace lldb_private { - -unw_accessors_t get_macosx_libunwind_callbacks (); - -} // namespace lldb_utility - -#endif // #if defined(__cplusplus) -#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_h_ - diff --git a/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp b/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp deleted file mode 100644 index bbc58a21cc0..00000000000 --- a/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===-- UnwindLibUnwind.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/Thread.h" -#include "UnwindLibUnwind.h" -#include "LibUnwindRegisterContext.h" - -using namespace lldb; -using namespace lldb_private; - -UnwindLibUnwind::UnwindLibUnwind (Thread &thread, unw_addr_space_t addr_space) : - Unwind (thread), - m_addr_space (addr_space), - m_cursors() -{ - m_pc_regnum = thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - m_sp_regnum = thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); -} - -uint32_t -UnwindLibUnwind::GetFrameCount() -{ - if (m_cursors.empty()) - { - unw_cursor_t cursor; - unw_init_remote (&cursor, m_addr_space, &m_thread); - - m_cursors.push_back (cursor); - - while (1) - { - int stepresult = unw_step (&cursor); - if (stepresult > 0) - m_cursors.push_back (cursor); - else - break; - } - } - return m_cursors.size(); -} - -bool -UnwindLibUnwind::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc) -{ - const uint32_t frame_count = GetFrameCount(); - if (idx < frame_count) - { - int pc_err = unw_get_reg (&m_cursors[idx], m_pc_regnum, &pc); - int sp_err = unw_get_reg (&m_cursors[idx], m_sp_regnum, &cfa); - return pc_err == UNW_ESUCCESS && sp_err == UNW_ESUCCESS; - } - return false; -} - -RegisterContext * -UnwindLibUnwind::CreateRegisterContextForFrame (StackFrame *frame) -{ - uint32_t idx = frame->GetUnwindFrameIndex (); - const uint32_t frame_count = GetFrameCount(); - if (idx < frame_count) - return new LibUnwindRegisterContext (m_thread, frame, m_cursors[idx]); - return NULL; -} diff --git a/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.h b/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.h deleted file mode 100644 index 8b3489b80e1..00000000000 --- a/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- UnwindLibUnwind.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_UnwindLibUnwind_h_ -#define lldb_UnwindLibUnwind_h_ - -// C Includes -// C++ Includes -#include <vector> - -// Other libraries and framework includes -#include "libunwind/include/libunwind.h" - -// Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/Unwind.h" - -class UnwindLibUnwind : public lldb_private::Unwind -{ -public: - UnwindLibUnwind (lldb_private::Thread &thread, - lldb_private::unw_addr_space_t addr_space); - - virtual - ~UnwindLibUnwind() - { - } - - virtual void - Clear() - { - m_cursors.clear(); - } - - virtual uint32_t - GetFrameCount(); - - bool - GetFrameInfoAtIndex (uint32_t frame_idx, - lldb::addr_t& cfa, - lldb::addr_t& pc); - - lldb_private::RegisterContext * - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - - lldb_private::Thread & - GetThread(); - -private: - lldb_private::unw_addr_space_t m_addr_space; - std::vector<lldb_private::unw_cursor_t> m_cursors; - uint32_t m_pc_regnum; - uint32_t m_sp_regnum; - //------------------------------------------------------------------ - // For UnwindLibUnwind only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (UnwindLibUnwind); -}; - -#endif // lldb_UnwindLibUnwind_h_ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/include/libunwind.h b/lldb/source/Plugins/Process/Utility/libunwind/include/libunwind.h deleted file mode 100644 index df7025653ea..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/include/libunwind.h +++ /dev/null @@ -1,509 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- libunwind.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// C interface to libuwind -// -// Source compatible with Level 1 Base ABI documented at: -// http://www.codesourcery.com/public/cxx-abi/abi-eh.html -// -//===----------------------------------------------------------------------===// - - -#ifndef __LIBUNWIND__ -#define __LIBUNWIND__ - -#include <stdio.h> -#include <stdint.h> -#include <stddef.h> -#include <mach/mach_types.h> -#include <Availability.h> - -namespace lldb_private { - -#pragma mark Error codes - -enum { - UNW_ESUCCESS = 0, /* no error */ - UNW_EUNSPEC = -6540, /* unspecified (general) error */ - UNW_ENOMEM = -6541, /* out of memory */ - UNW_EBADREG = -6542, /* bad register number */ - UNW_EREADONLYREG = -6543, /* attempt to write read-only register */ - UNW_ESTOPUNWIND = -6544, /* stop unwinding */ - UNW_EINVALIDIP = -6545, /* invalid IP */ - UNW_EBADFRAME = -6546, /* bad frame */ - UNW_EINVAL = -6547, /* unsupported operation or bad value */ - UNW_EBADVERSION = -6548, /* unwind info has unsupported version */ - UNW_ENOINFO = -6549, /* no unwind info found */ - UNW_EREGUNAVAILABLE = -6550 /* contents of requested reg are not available */ -}; - -#pragma mark General data structures - -struct unw_context_t { uint64_t data[128]; }; -typedef struct unw_context_t unw_context_t; - -struct unw_cursor_t { uint64_t data[140]; }; -typedef struct unw_cursor_t unw_cursor_t; - -enum unw_as_type { UNW_LOCAL, UNW_REMOTE }; -struct unw_addr_space -{ - enum unw_as_type type; - uint8_t data[1]; -}; -typedef struct unw_addr_space* unw_addr_space_t; - -typedef int unw_regnum_t; -typedef uint64_t unw_word_t; -typedef double unw_fpreg_t; - -enum unw_vecreg_format { - UNW_VECREG_SIGNED, - UNW_VECREG_UNSIGNED, - UNW_VECREG_FLOAT -}; - -typedef struct -{ - union { - double doubles[8]; - float floats [16]; - - uint64_t dwords [8]; - uint32_t words [16]; - uint16_t hwords [32]; - uint8_t bytes [64]; - } data; - uint16_t unit_size; // bits - uint16_t num_units; - uint8_t format; -} unw_vecreg_t; - -struct unw_proc_info_t -{ - unw_word_t start_ip; /* start address of function */ - unw_word_t end_ip; /* address after end of function */ - unw_word_t lsda; /* address of language specific data area, or zero if not used */ - unw_word_t handler; /* personality routine, or zero if not used */ - unw_word_t gp; /* not used */ - unw_word_t flags; /* not used */ - uint32_t format; /* compact unwind encoding, or zero if none */ - uint32_t unwind_info_size; /* size of dwarf unwind info, or zero if none */ - unw_word_t unwind_info; /* address of dwarf unwind info, or zero if none */ - unw_word_t extra; /* mach_header of mach-o image containing function */ -}; -typedef struct unw_proc_info_t unw_proc_info_t; - -#pragma mark Local API - -#ifdef __cplusplus -extern "C" { -#endif - -extern int unw_getcontext(unw_context_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_init_local(unw_cursor_t*, unw_context_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_step(unw_cursor_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_get_reg(unw_cursor_t*, unw_regnum_t, unw_word_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_get_fpreg(unw_cursor_t*, unw_regnum_t, unw_fpreg_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_set_reg(unw_cursor_t*, unw_regnum_t, unw_word_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_set_fpreg(unw_cursor_t*, unw_regnum_t, unw_fpreg_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_resume(unw_cursor_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); - -extern const char* unw_regname(unw_cursor_t*, unw_regnum_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_get_proc_info(unw_cursor_t*, unw_proc_info_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_is_fpreg(unw_cursor_t*, unw_regnum_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_is_signal_frame(unw_cursor_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_get_proc_name(unw_cursor_t*, char*, size_t, unw_word_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); - - -#pragma mark Remote data structures - -typedef enum { - UNW_NOT_A_REG = 0, - UNW_INTEGER_REG, - UNW_FLOATING_POINT_REG, - UNW_VECTOR_REG, - UNW_OTHER_REG -} unw_regtype_t; - -typedef enum { - UNW_TARGET_UNSPECIFIED = 0, - UNW_TARGET_I386, - UNW_TARGET_X86_64, - UNW_TARGET_PPC, - UNW_TARGET_ARM -} unw_targettype_t; - -typedef enum { - UNW_LOG_LEVEL_NONE = 0x00000000, - UNW_LOG_LEVEL_INFO = 0x00000001, - UNW_LOG_LEVEL_API = 0x00000002, - UNW_LOG_LEVEL_VERBOSE = 0x00000004, - UNW_LOG_LEVEL_TIMINGS = 0x00000008, - UNW_LOG_LEVEL_DEBUG = 0x00000010, - UNW_LOG_LEVEL_ALL = 0x0FFFFFFF -} unw_log_level_t; - -typedef enum { - UNW_CACHE_NONE = 0, - UNW_CACHE_GLOBAL, - UNW_CACHE_PER_THREAD -} unw_caching_policy_t; - -typedef struct { - int (*find_proc_info)(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int need_unwind_info, void *arg); - int (*put_unwind_info)(unw_addr_space_t as, unw_proc_info_t *pip, void *arg); - int (*get_dyn_info_list_addr)(unw_addr_space_t as, unw_word_t *dilap, void *arg); - - // Reads or writes a memory object the size of a target pointer. - // Byte-swaps if necessary. - int (*access_mem)(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, int write, void *arg); - - // Register contents sent as-is (i.e. not byte-swapped). - // Register numbers are the driver program's numbering scheme as - // determined by the reg_info callbacks; libunwind will interrogate - // the driver program to figure out which numbers it uses to refer to - // which registers. - int (*access_reg)(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write, void *arg); - int (*access_fpreg)(unw_addr_space_t as, unw_regnum_t regnum, unw_fpreg_t *valp, int write, void *arg); - int (*resume)(unw_addr_space_t as, unw_cursor_t *cp, void *arg); - int (*get_proc_name)(unw_addr_space_t as, unw_word_t addr, char *bufp, size_t buf_len, unw_word_t *offp, void *arg); - - - // Added to find the start of the image (executable, bundle, dylib, etc) - // for a given address. - // as - The address space to use - // ip - The address libunwind wants to know about - // mh - The Mach-O header address for this image - // text_start - The start of __TEXT segment (all its sections) - // text_end - The end address of __TEXT segment (all its sections) - // eh_frame - The start of __TEXT,__eh_frame - // eh_frame_len - The length of __TEXT,__eh_frame - // compact_unwind_start - The start of __TEXT,__unwind_info - // compact_unwind_len - The length of __TEXT,__unwind_info - // arg - The driver-provided generic argument - // All addresses are the in-memory, slid, addresses. - // If eh_frame or unwind_info are missing, addr and len is returned as 0. - int (*find_image_info)(unw_addr_space_t as, unw_word_t ip, unw_word_t *mh, - unw_word_t *text_start, unw_word_t *text_end, - unw_word_t *eh_frame, unw_word_t *eh_frame_len, - unw_word_t *compact_unwind_start, - unw_word_t *compact_unwind_len, void *arg); - - // Added to get the start and end address of a function without needing - // all of the information (and potential allocation) that the - // find_proc_info() call entails. - // as - The address space to use - // ip - The address libunwind wants to know about - // low - The start address of the function at 'ip' - // high - The first address past the function at 'ip' - // arg - The driver-provided generic argument - // If HIGH is unknown, it should be set to 0. All addresses - // are the in-memory, slid, addresses. - int (*get_proc_bounds)(unw_addr_space_t as, unw_word_t ip, - unw_word_t *low, unw_word_t *high, void *arg); - - // Added to support accessing non-word-size memory objects across - // platforms. No byte swapping should be done. - // as - The address space to use - // addr - The starting address to access - // extent - The extent of the region to access, in bytes - // valp - The local region to be written from / read into - // write - non-zero if the data is to be written into the target - // rather than read - // arg - The driver-provided generic argument (see unw_init_remote) - int (*access_raw)(unw_addr_space_t as, unw_word_t addr, unw_word_t extent, - uint8_t *valp, int write, void *arg); - - // Added to support identifying registers. - // libunwind will interrogate the driver program via this callback to - // identify what register numbers it is using; the register names are - // used to correlate that the driver program's register numbers with - // libunwind's internal register numbers. The driver program should - // use its own register numbers when requesting registers with - // unw_get_reg() and libunwind will provide the driver program's - // register numbers to the access_reg callback function. - // as - The address space to use - // regnum - The register number - // type - Write the register type to this address - // For a non-existent register, return UNW_ESUCCESS but - // write UNW_NOT_A_REG to type - // buf - If non-NULL, the register name is written to this address - // buf_len - The size of the buffer provided for the register name - // arg - The driver-provided generic argument (see unw_init_remote) - int (*reg_info)(unw_addr_space_t as, unw_regnum_t regnum, - unw_regtype_t* type, char *bufp, size_t buf_len, void *arg); - - // Added to read a vector register's value from the remote machine. - // as - The address space to use - // regnum - The register number - // valp - The local region to be written from / read into - // write - non-zero if the data is to be written into the target - // rather than read - // arg - The driver-specified generic argument - int (*access_vecreg)(unw_addr_space_t as, unw_regnum_t regnum, - unw_vecreg_t* valp, int write, void *arg); - - // Added to identify if an unwind cursor is pointing to _sigtramp(). - // After a _sigtramp we have an entire register set available and we should - // return any of the registers requested. - // as - The address space to use - // ip - The address of the function libunwind is examining - // arg - The driver-provided generic argument - // This function returns non-zero if ip is in _sigtramp. - int (*proc_is_sigtramp) (unw_addr_space_t as, unw_word_t ip, void *arg); - - // Added to identify if an unwind cursor is pointing to a debugger's - // inferior function call dummy frame. - // The driver program will need to provide the full register set (via the - // standard access_reg callback) for the function that was executing - // when the inferior function call was made; it will use these register - // values and not try to unwind out of the inferior function call dummy - // frame. - // After a inf func call we have an entire register set available and - // we should return any of the registers requested. - // as - The address space to use - // ip - The address of the function libunwind is examining - // sp - The stack pointer value of the frame - // arg - The driver-provided generic argument (see unw_init_remote) - // This function returns non-zero if ip/sp is an inferior function call - // dummy frame. - int (*proc_is_inferior_function_call) (unw_addr_space_t as, unw_word_t ip, - unw_word_t sp, void *arg); - - // Added to retrieve a register value from a above a debugger's inferior - // function call dummy frame. Similar to _sigtramp but the debugger will - // have the register context squirreled away in its own memory (or possibly - // saved on the stack somewhere). - // May be NULL if the program being unwound will not have a debugger - // calling functions mid-execution. - // as - The address space to use - // ip - The pc value for the dummy frame - // sp - The stack pointer for the dummy frame - // regnum - The register number in the driver program's register - // numbering scheme. - // valp - Pointer to a word of memory to be read/written - // write - Non-zero if libunwind is writing a new value to the reg, - // else it is reading the contents of that register. - // arg - The driver-provided generic argument (see unw_init_remote) - int (*access_reg_inf_func_call)(unw_addr_space_t as, unw_word_t ip, - unw_word_t sp, unw_regnum_t regnum, - unw_word_t *valp, int write, void *arg); - - // Added to iterate over unknown assembly instructions when analyzing a - // function prologue. Needed for ISAs with variable length instructions - // (i386, x86_64) or multiple instruction sizes (arm, thumb). - // Returns zero if the instruction length was successfully measured. - // as - The address space to use - // addr - The address of the instruction being measured - // length - Set to the length of the instruction - // arg - The driver-provided generic argument (see unw_init_remote) - int (*instruction_length)(unw_addr_space_t as, unw_word_t addr, - int *length, void *arg); - -} unw_accessors_t; - -extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t, void*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern unw_accessors_t* unw_get_accessors(unw_addr_space_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern unw_addr_space_t unw_create_addr_space(unw_accessors_t*, unw_targettype_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern void unw_flush_caches(unw_addr_space_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern int unw_set_caching_policy(unw_addr_space_t, unw_caching_policy_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern void unw_destroy_addr_space(unw_addr_space_t asp) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); -extern void unw_set_logging_level(unw_addr_space_t, FILE *, unw_log_level_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); - -// Should be called when remote unwinding if a bundle in the remote process -// is unloaded -extern void unw_image_was_unloaded(unw_addr_space_t, unw_word_t mh) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); - -// Try to discern where the function's prologue instructions end -// start - start address of the function, required -// end - first address beyond the function, or zero if unknown -// endofprologue - set to the address after the last prologue instruction if successful -extern int unw_end_of_prologue_setup(unw_cursor_t*, unw_word_t start, unw_word_t end, unw_word_t *endofprologue) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA); - -/* - * Dynamic unwinding API - * NOT IMPLEMENTED on Mac OS X - * extern void _U_dyn_register(unw_dyn_info_t*); - * extern void _U_dyn_cancel(unw_dyn_info_t*); - */ - -#ifdef __cplusplus -} -#endif - -#pragma mark Register numbers - -// architecture independent register numbers -enum { - UNW_REG_IP = -1, // instruction pointer - UNW_REG_SP = -2 // stack pointer -}; - - -// 32-bit x86 registers -enum { - UNW_X86_EAX = 0, - UNW_X86_ECX = 1, - UNW_X86_EDX = 2, - UNW_X86_EBX = 3, - UNW_X86_EBP = 4, - UNW_X86_ESP = 5, - UNW_X86_ESI = 6, - UNW_X86_EDI = 7 -}; - - -// 64-bit x86_64 registers -enum { - UNW_X86_64_RAX = 0, - UNW_X86_64_RDX = 1, - UNW_X86_64_RCX = 2, - UNW_X86_64_RBX = 3, - UNW_X86_64_RSI = 4, - UNW_X86_64_RDI = 5, - UNW_X86_64_RBP = 6, - UNW_X86_64_RSP = 7, - UNW_X86_64_R8 = 8, - UNW_X86_64_R9 = 9, - UNW_X86_64_R10 = 10, - UNW_X86_64_R11 = 11, - UNW_X86_64_R12 = 12, - UNW_X86_64_R13 = 13, - UNW_X86_64_R14 = 14, - UNW_X86_64_R15 = 15 -}; - - -// 32-bit ppc register numbers -enum { - UNW_PPC_R0 = 0, - UNW_PPC_R1 = 1, - UNW_PPC_R2 = 2, - UNW_PPC_R3 = 3, - UNW_PPC_R4 = 4, - UNW_PPC_R5 = 5, - UNW_PPC_R6 = 6, - UNW_PPC_R7 = 7, - UNW_PPC_R8 = 8, - UNW_PPC_R9 = 9, - UNW_PPC_R10 = 10, - UNW_PPC_R11 = 11, - UNW_PPC_R12 = 12, - UNW_PPC_R13 = 13, - UNW_PPC_R14 = 14, - UNW_PPC_R15 = 15, - UNW_PPC_R16 = 16, - UNW_PPC_R17 = 17, - UNW_PPC_R18 = 18, - UNW_PPC_R19 = 19, - UNW_PPC_R20 = 20, - UNW_PPC_R21 = 21, - UNW_PPC_R22 = 22, - UNW_PPC_R23 = 23, - UNW_PPC_R24 = 24, - UNW_PPC_R25 = 25, - UNW_PPC_R26 = 26, - UNW_PPC_R27 = 27, - UNW_PPC_R28 = 28, - UNW_PPC_R29 = 29, - UNW_PPC_R30 = 30, - UNW_PPC_R31 = 31, - UNW_PPC_F0 = 32, - UNW_PPC_F1 = 33, - UNW_PPC_F2 = 34, - UNW_PPC_F3 = 35, - UNW_PPC_F4 = 36, - UNW_PPC_F5 = 37, - UNW_PPC_F6 = 38, - UNW_PPC_F7 = 39, - UNW_PPC_F8 = 40, - UNW_PPC_F9 = 41, - UNW_PPC_F10 = 42, - UNW_PPC_F11 = 43, - UNW_PPC_F12 = 44, - UNW_PPC_F13 = 45, - UNW_PPC_F14 = 46, - UNW_PPC_F15 = 47, - UNW_PPC_F16 = 48, - UNW_PPC_F17 = 49, - UNW_PPC_F18 = 50, - UNW_PPC_F19 = 51, - UNW_PPC_F20 = 52, - UNW_PPC_F21 = 53, - UNW_PPC_F22 = 54, - UNW_PPC_F23 = 55, - UNW_PPC_F24 = 56, - UNW_PPC_F25 = 57, - UNW_PPC_F26 = 58, - UNW_PPC_F27 = 59, - UNW_PPC_F28 = 60, - UNW_PPC_F29 = 61, - UNW_PPC_F30 = 62, - UNW_PPC_F31 = 63, - UNW_PPC_MQ = 64, - UNW_PPC_LR = 65, - UNW_PPC_CTR = 66, - UNW_PPC_AP = 67, - UNW_PPC_CR0 = 68, - UNW_PPC_CR1 = 69, - UNW_PPC_CR2 = 70, - UNW_PPC_CR3 = 71, - UNW_PPC_CR4 = 72, - UNW_PPC_CR5 = 73, - UNW_PPC_CR6 = 74, - UNW_PPC_CR7 = 75, - UNW_PPC_XER = 76, - UNW_PPC_V0 = 77, - UNW_PPC_V1 = 78, - UNW_PPC_V2 = 79, - UNW_PPC_V3 = 80, - UNW_PPC_V4 = 81, - UNW_PPC_V5 = 82, - UNW_PPC_V6 = 83, - UNW_PPC_V7 = 84, - UNW_PPC_V8 = 85, - UNW_PPC_V9 = 86, - UNW_PPC_V10 = 87, - UNW_PPC_V11 = 88, - UNW_PPC_V12 = 89, - UNW_PPC_V13 = 90, - UNW_PPC_V14 = 91, - UNW_PPC_V15 = 92, - UNW_PPC_V16 = 93, - UNW_PPC_V17 = 94, - UNW_PPC_V18 = 95, - UNW_PPC_V19 = 96, - UNW_PPC_V20 = 97, - UNW_PPC_V21 = 98, - UNW_PPC_V22 = 99, - UNW_PPC_V23 = 100, - UNW_PPC_V24 = 101, - UNW_PPC_V25 = 102, - UNW_PPC_V26 = 103, - UNW_PPC_V27 = 104, - UNW_PPC_V28 = 105, - UNW_PPC_V29 = 106, - UNW_PPC_V30 = 107, - UNW_PPC_V31 = 108, - UNW_PPC_VRSAVE = 109, - UNW_PPC_VSCR = 110, - UNW_PPC_SPE_ACC = 111, - UNW_PPC_SPEFSCR = 112 - -}; - - -} // namespace lldb_private - - -#endif - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/include/mach-o/compact_unwind_encoding.h b/lldb/source/Plugins/Process/Utility/libunwind/include/mach-o/compact_unwind_encoding.h deleted file mode 100644 index bee2ad578d6..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/include/mach-o/compact_unwind_encoding.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- compact_unwind_encoding.h -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#ifndef __COMPACT_UNWIND_ENCODING__ -#define __COMPACT_UNWIND_ENCODING__ - -#include <stdint.h> - -namespace lldb_private { - -// -// Each final linked mach-o image has an optional __TEXT, __unwind_info section. -// This section is much smaller and faster to use than the __eh_frame section. -// - - - -// -// Compilers usually emit standard Dwarf FDEs. The linker recognizes standard FDEs and -// synthesizes a matching compact_unwind_encoding_t and adds it to the __unwind_info table. -// It is also possible for the compiler to emit __unwind_info entries for functions that -// have different unwind requirements at different ranges in the function. -// -typedef uint32_t compact_unwind_encoding_t; - - - -// -// The __unwind_info section is laid out for an efficient two level lookup. -// The header of the section contains a coarse index that maps function address -// to the page (4096 byte block) containing the unwind info for that function. -// - -#define UNWIND_SECTION_VERSION 1 -struct unwind_info_section_header -{ - uint32_t version; // UNWIND_SECTION_VERSION - uint32_t commonEncodingsArraySectionOffset; - uint32_t commonEncodingsArrayCount; - uint32_t personalityArraySectionOffset; - uint32_t personalityArrayCount; - uint32_t indexSectionOffset; - uint32_t indexCount; - // compact_unwind_encoding_t[] - // uintptr_t personalities[] - // unwind_info_section_header_index_entry[] - // unwind_info_section_header_lsda_index_entry[] -}; - -struct unwind_info_section_header_index_entry -{ - uint32_t functionOffset; - uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page - uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range -}; - -struct unwind_info_section_header_lsda_index_entry -{ - uint32_t functionOffset; - uint32_t lsdaOffset; -}; - -// -// There are two kinds of second level index pages: regular and compressed. -// A compressed page can hold up to 1021 entries, but it cannot be used -// if too many different encoding types are used. The regular page holds -// 511 entries. -// - -struct unwind_info_regular_second_level_entry -{ - uint32_t functionOffset; - compact_unwind_encoding_t encoding; -}; - -#define UNWIND_SECOND_LEVEL_REGULAR 2 -struct unwind_info_regular_second_level_page_header -{ - uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR - uint16_t entryPageOffset; - uint16_t entryCount; - // entry array -}; - -#define UNWIND_SECOND_LEVEL_COMPRESSED 3 -struct unwind_info_compressed_second_level_page_header -{ - uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED - uint16_t entryPageOffset; - uint16_t entryCount; - uint16_t encodingsPageOffset; - uint16_t encodingsCount; - // 32-bit entry array - // encodings array -}; - -#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) -#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) - - - -// architecture independent bits -enum { - UNWIND_IS_NOT_FUNCTION_START = 0x80000000, - UNWIND_HAS_LSDA = 0x40000000, - UNWIND_PERSONALITY_MASK = 0x30000000, -}; - - -// x86_64 -// -// 1-bit: start -// 1-bit: has lsda -// 2-bit: personality index -// -// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf -// rbp based: -// 15-bits (5*3-bits per reg) register permutation -// 8-bits for stack offset -// frameless: -// 8-bits stack size -// 3-bits stack adjust -// 3-bits register count -// 10-bits register permutation -// -enum { - UNWIND_X86_64_MODE_MASK = 0x0F000000, - UNWIND_X86_64_MODE_COMPATIBILITY = 0x00000000, - UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, - UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_64_MODE_STACK_IND = 0x03000000, - UNWIND_X86_64_MODE_DWARF = 0x04000000, - - UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, - - UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - - UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, -}; - -enum { - UNWIND_X86_64_REG_NONE = 0, - UNWIND_X86_64_REG_RBX = 1, - UNWIND_X86_64_REG_R12 = 2, - UNWIND_X86_64_REG_R13 = 3, - UNWIND_X86_64_REG_R14 = 4, - UNWIND_X86_64_REG_R15 = 5, - UNWIND_X86_64_REG_RBP = 6, -}; - - -// x86 -// -// 1-bit: start -// 1-bit: has lsda -// 2-bit: personality index -// -// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf -// ebp based: -// 15-bits (5*3-bits per reg) register permutation -// 8-bits for stack offset -// frameless: -// 8-bits stack size -// 3-bits stack adjust -// 3-bits register count -// 10-bits register permutation -// -enum { - UNWIND_X86_MODE_MASK = 0x0F000000, - UNWIND_X86_MODE_COMPATIBILITY = 0x00000000, - UNWIND_X86_MODE_EBP_FRAME = 0x01000000, - UNWIND_X86_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_MODE_STACK_IND = 0x03000000, - UNWIND_X86_MODE_DWARF = 0x04000000, - - UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, - - UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - - UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, -}; - -enum { - UNWIND_X86_REG_NONE = 0, - UNWIND_X86_REG_EBX = 1, - UNWIND_X86_REG_ECX = 2, - UNWIND_X86_REG_EDX = 3, - UNWIND_X86_REG_EDI = 4, - UNWIND_X86_REG_ESI = 5, - UNWIND_X86_REG_EBP = 6, -}; - -}; // namespace lldb_private - -#endif - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/include/unwind.h b/lldb/source/Plugins/Process/Utility/libunwind/include/unwind.h deleted file mode 100644 index 80b9d2881c2..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/include/unwind.h +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- unwind.h ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// C interface to libuwind -// -// Source compatible with Level 1 Base ABI documented at: -// http://www.codesourcery.com/public/cxx-abi/abi-eh.html -// -//===----------------------------------------------------------------------===// - - -#ifndef __UNWIND_H__ -#define __UNWIND_H__ - -#include <stdint.h> -#include <stddef.h> -#include <Availability.h> - -namespace lldb_private { - -typedef enum { - _URC_NO_REASON = 0, - _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - _URC_FATAL_PHASE2_ERROR = 2, - _URC_FATAL_PHASE1_ERROR = 3, - _URC_NORMAL_STOP = 4, - _URC_END_OF_STACK = 5, - _URC_HANDLER_FOUND = 6, - _URC_INSTALL_CONTEXT = 7, - _URC_CONTINUE_UNWIND = 8 -} _Unwind_Reason_Code; - -typedef enum { - _UA_SEARCH_PHASE = 1, - _UA_CLEANUP_PHASE = 2, - _UA_HANDLER_FRAME = 4, - _UA_FORCE_UNWIND = 8, - _UA_END_OF_STACK = 16 // gcc extension to C++ ABI -} _Unwind_Action; - - -struct _Unwind_Context; // opaque -struct _Unwind_Exception; // forward declaration - -struct _Unwind_Exception { - uint64_t exception_class; - void (*exception_cleanup)(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc); - uintptr_t private_1; // non-zero means forced unwind - uintptr_t private_2; // holds sp that phase1 found for phase2 to use -}; - - -typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) - (int version, - _Unwind_Action actions, - uint64_t exceptionClass, - struct _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context, - void* stop_parameter ); - - -typedef _Unwind_Reason_Code (*__personality_routine) - (int version, - _Unwind_Action actions, - uint64_t exceptionClass, - struct _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context); - - - -#ifdef __cplusplus -extern "C" { -#endif - -// -// The following are the base functions documented by the C++ ABI -// -#if __arm__ - extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception* exception_object); - extern void _Unwind_SjLj_Resume(struct _Unwind_Exception* exception_object); -#else - extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception* exception_object); - extern void _Unwind_Resume(struct _Unwind_Exception* exception_object); -#endif -extern void _Unwind_DeleteException(struct _Unwind_Exception* exception_object); -extern uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index); -extern void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value); -extern uintptr_t _Unwind_GetIP(struct _Unwind_Context* context); -extern void _Unwind_SetIP(struct _Unwind_Context*, uintptr_t new_value); -extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context); -extern uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context); -#if __arm__ - extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter ); -#else - extern _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter ); -#endif - -#if __arm__ - typedef struct _Unwind_FunctionContext* _Unwind_FunctionContext_t; - extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc); - extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc); -#endif - -// -// The following are semi-suppoted extensions to the C++ ABI -// - - -// -// called by __cxa_rethrow(). -// -#if __arm__ - extern _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception* exception_object); -#else - extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception* exception_object); -#endif - - -// -// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the -// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack -// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON. -// -typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context*, void*); -extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*); - - -// -// _Unwind_GetCFA is a gcc extension that can be called from within a personality -// handler to get the CFA (stack pointer before call) of current frame. -// -extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context*); - - -// -// _Unwind_GetIPInfo is a gcc extension that can be called from within a personality -// handler. Similar to _Unwind_GetIP() but also returns in *ipBefore a non-zero -// value if the instruction pointer is at or before the instruction causing -// the unwind. Normally, in a function call, the IP returned is the return address -// which is after the call instruction and may be past the end of the function -// containing the call instruction. -// -extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore); - - -// -// __register_frame() is used with dynamically generated code to register the FDE -// for a generated (JIT) code. The FDE must use pc-rel addressing to point to its -// function and optional LSDA. __register_frame() has existed in all versions of -// Mac OS X, but in 10.4 and 10.5 it was buggy and did not actually register the -// FDE with the unwinder. In 10.6 and later it does register properly. -// -extern void __register_frame(const void* fde); -extern void __deregister_frame(const void* fde); - - -// -// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has -// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind info" -// which the runtime uses in preference to dwarf unwind info. This function -// will only work if the target function has an FDE but no compact unwind info. -// -struct dwarf_eh_bases -{ - uintptr_t tbase; - uintptr_t dbase; - uintptr_t func; -}; -extern const void* _Unwind_Find_FDE(const void* pc, struct dwarf_eh_bases*); - - -// -// This function attempts to find the start (address of first instruction) of -// a function given an address inside the function. It only works if the function -// has an FDE (dwarf unwind info). -// This function is unimplemented on Mac OS X 10.6 and later. Instead, use -// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result. -extern void* _Unwind_FindEnclosingFunction(void* pc); - - -// Mac OS X does not support text-rel and data-rel addressing so these functions are unimplemented -extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context) __attribute__((unavailable)); -extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context) __attribute__((unavailable)); - - - -// Mac OS X 10.4 and 10.5 had implementations of these functions in libgcc_s.dylib, -// but they never worked. These functions are no longer available. -extern void __register_frame_info_bases(const void* fde, void* ob, void* tb, void* db) __attribute__((unavailable)); -extern void __register_frame_info(const void* fde, void* ob) __attribute__((unavailable)); -extern void __register_frame_info_table_bases(const void* fde, void* ob,void* tb, void* db) __attribute__((unavailable)); -extern void __register_frame_info_table(const void* fde, void* ob) __attribute__((unavailable)); -extern void __register_frame_table(const void* fde) __attribute__((unavailable)); -extern void* __deregister_frame_info(const void* fde) __attribute__((unavailable)); -extern void* __deregister_frame_info_bases(const void* fde) __attribute__((unavailable)); - - -#ifdef __cplusplus -} -#endif - -}; // namespace lldb_private - -#endif // __UNWIND_H__ - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/AddressSpace.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/AddressSpace.hpp deleted file mode 100644 index 6a7734e9a55..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/AddressSpace.hpp +++ /dev/null @@ -1,455 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- AddressSpace.hpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// -// C++ interface to lower levels of libuwind -// - -#ifndef __ADDRESSSPACE_HPP__ -#define __ADDRESSSPACE_HPP__ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> -#include <mach-o/loader.h> -#include <mach-o/getsect.h> -#if !defined (SUPPORT_REMOTE_UNWINDING) -#include <mach-o/dyld_priv.h> -#endif -#include <mach/i386/thread_status.h> -#include <Availability.h> - -#include "FileAbstraction.hpp" -#include "libunwind.h" -#include "InternalMacros.h" -#include "dwarf2.h" -#include "RemoteProcInfo.hpp" - -#if defined (SUPPORT_REMOTE_UNWINDING) -bool _dyld_find_unwind_sections(void* addr, void* info) -{ - assert("unwinding with a non-remote process not supported."); - return false; -} -#endif // SUPPORT_REMOTE_UNWINDING - -namespace lldb_private { - -/// -/// LocalAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread -/// in the same process. It compiles away and making local unwinds very fast. -/// -class LocalAddressSpace -{ -public: - - #if __LP64__ - typedef uint64_t pint_t; - typedef int64_t sint_t; - #else - typedef uint32_t pint_t; - typedef int32_t sint_t; - #endif - int getBytes(pint_t addr, pint_t extent, uint8_t* buf) { memcpy(buf, (void*)addr, extent); return 1; } - uint8_t get8(pint_t addr) { return *((uint8_t*)addr); } - uint16_t get16(pint_t addr) { return *((uint16_t*)addr); } - uint32_t get32(pint_t addr) { return *((uint32_t*)addr); } - uint64_t get64(pint_t addr) { return *((uint64_t*)addr); } - double getDouble(pint_t addr) { return *((double*)addr); } - v128 getVector(pint_t addr) { return *((v128*)addr); } - - uint8_t get8(pint_t addr, int& err) { return *((uint8_t*)addr); err = 0; } - uint16_t get16(pint_t addr, int& err) { return *((uint16_t*)addr); err = 0; } - uint32_t get32(pint_t addr, int& err) { return *((uint32_t*)addr); err = 0; } - uint64_t get64(pint_t addr, int& err) { return *((uint64_t*)addr); err = 0; } - double getDouble(pint_t addr, int& err) { return *((double*)addr); err = 0; } - v128 getVector(pint_t addr, int& err) { return *((v128*)addr); err = 0; } - - uintptr_t getP(pint_t addr); - uintptr_t getP(pint_t addr, int &err); - static uint64_t getULEB128(pint_t& addr, pint_t end); - static int64_t getSLEB128(pint_t& addr, pint_t end); - - pint_t getEncodedP(pint_t& addr, pint_t end, uint8_t encoding); - bool findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset); - bool findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart); - -#if defined (SUPPORT_REMOTE_UNWINDING) - RemoteProcInfo* getRemoteProcInfo () { return NULL; } - unw_accessors_t* accessors() { return NULL; } - unw_addr_space_t wrap() { return NULL; } -#endif -}; - -LocalAddressSpace sThisAddress; - -inline uintptr_t LocalAddressSpace::getP(pint_t addr) -{ -#if __LP64__ - return get64(addr); -#else - return get32(addr); -#endif -} - -inline uintptr_t LocalAddressSpace::getP(pint_t addr, int &err) -{ -#if __LP64__ - return get64(addr); -#else - return get32(addr); -#endif - err = 0; -} - -/* Read a ULEB128 into a 64-bit word. */ -inline uint64_t -LocalAddressSpace::getULEB128(pint_t& addr, pint_t end) -{ - const uint8_t* p = (uint8_t*)addr; - const uint8_t* pend = (uint8_t*)end; - uint64_t result = 0; - int bit = 0; - do { - uint64_t b; - - if ( p == pend ) - ABORT("truncated uleb128 expression"); - - b = *p & 0x7f; - - if (bit >= 64 || b << bit >> bit != b) { - ABORT("malformed uleb128 expression"); - } - else { - result |= b << bit; - bit += 7; - } - } while ( *p++ >= 0x80 ); - addr = (pint_t)p; - return result; -} - -/* Read a SLEB128 into a 64-bit word. */ -inline int64_t -LocalAddressSpace::getSLEB128(pint_t& addr, pint_t end) -{ - const uint8_t* p = (uint8_t*)addr; - int64_t result = 0; - int bit = 0; - uint8_t byte; - do { - byte = *p++; - result |= ((byte & 0x7f) << bit); - bit += 7; - } while (byte & 0x80); - // sign extend negative numbers - if ( (byte & 0x40) != 0 ) - result |= (-1LL) << bit; - addr = (pint_t)p; - return result; -} - -LocalAddressSpace::pint_t -LocalAddressSpace::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding) -{ - pint_t startAddr = addr; - const uint8_t* p = (uint8_t*)addr; - pint_t result; - - // first get value - switch (encoding & 0x0F) { - case DW_EH_PE_ptr: - result = getP(addr); - p += sizeof(pint_t); - addr = (pint_t)p; - break; - case DW_EH_PE_uleb128: - result = getULEB128(addr, end); - break; - case DW_EH_PE_udata2: - result = get16(addr); - p += 2; - addr = (pint_t)p; - break; - case DW_EH_PE_udata4: - result = get32(addr); - p += 4; - addr = (pint_t)p; - break; - case DW_EH_PE_udata8: - result = get64(addr); - p += 8; - addr = (pint_t)p; - break; - case DW_EH_PE_sleb128: - result = getSLEB128(addr, end); - break; - case DW_EH_PE_sdata2: - result = (int16_t)get16(addr); - p += 2; - addr = (pint_t)p; - break; - case DW_EH_PE_sdata4: - result = (int32_t)get32(addr); - p += 4; - addr = (pint_t)p; - break; - case DW_EH_PE_sdata8: - result = get64(addr); - p += 8; - addr = (pint_t)p; - break; - default: - ABORT("unknown pointer encoding"); - } - - // then add relative offset - switch ( encoding & 0x70 ) { - case DW_EH_PE_absptr: - // do nothing - break; - case DW_EH_PE_pcrel: - result += startAddr; - break; - case DW_EH_PE_textrel: - ABORT("DW_EH_PE_textrel pointer encoding not supported"); - break; - case DW_EH_PE_datarel: - ABORT("DW_EH_PE_datarel pointer encoding not supported"); - break; - case DW_EH_PE_funcrel: - ABORT("DW_EH_PE_funcrel pointer encoding not supported"); - break; - case DW_EH_PE_aligned: - ABORT("DW_EH_PE_aligned pointer encoding not supported"); - break; - default: - ABORT("unknown pointer encoding"); - break; - } - - if ( encoding & DW_EH_PE_indirect ) - result = getP(result); - - return result; -} - - -inline bool LocalAddressSpace::findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart) -{ -#if !defined (SUPPORT_REMOTE_UNWINDING) - dyld_unwind_sections info; - if ( _dyld_find_unwind_sections((void*)addr, &info) ) { - mh = (pint_t)info.mh; - dwarfStart = (pint_t)info.dwarf_section; - dwarfLen = (pint_t)info.dwarf_section_length; - compactStart = (pint_t)info.compact_unwind_section; - return true; - } -#else - assert("unwinding with a non-remote process not supported."); -#endif - return false; -} - - -inline bool LocalAddressSpace::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset) -{ - dl_info dyldInfo; - if ( dladdr((void*)addr, &dyldInfo) ) { - if ( dyldInfo.dli_sname != NULL ) { - strlcpy(buf, dyldInfo.dli_sname, bufLen); - *offset = (addr - (pint_t)dyldInfo.dli_saddr); - return true; - } - } - return false; -} - -#if defined (SUPPORT_REMOTE_UNWINDING) -/// -/// OtherAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread -/// in the another process. The other process can be a different endianness and a different -/// pointer size and is handled by the P template parameter. -/// -template <typename P> -class OtherAddressSpace -{ -public: - OtherAddressSpace (unw_addr_space_t remote_addr_space, void* arg) : fAddrSpace ((unw_addr_space_remote *)remote_addr_space), fArg(arg) - { - if (fAddrSpace->type != UNW_REMOTE) - ABORT("OtherAddressSpace ctor called with non-remote address space."); - fRemoteProcInfo = fAddrSpace->ras; - } - - typedef typename P::uint_t pint_t; - typedef typename P::int_t sint_t; - - int getBytes(pint_t addr, pint_t extent, uint8_t* buf) { return fRemoteProcInfo->getBytes (addr, extent, buf, fArg); } - uint8_t get8(pint_t addr) { return fRemoteProcInfo->get8(addr, fArg); } - uint16_t get16(pint_t addr) { return fRemoteProcInfo->get16(addr, fArg); } - uint32_t get32(pint_t addr) { return fRemoteProcInfo->get32(addr, fArg); } - uint64_t get64(pint_t addr) { return fRemoteProcInfo->get64(addr, fArg); } - pint_t getP(pint_t addr) { return fRemoteProcInfo->getP(addr, fArg); } - - uint8_t get8(pint_t addr, int& err) { return fRemoteProcInfo->get8(addr, err, fArg); } - uint16_t get16(pint_t addr, int& err) { return fRemoteProcInfo->get16(addr, err, fArg); } - uint32_t get32(pint_t addr, int& err) { return fRemoteProcInfo->get32(addr, err, fArg); } - uint64_t get64(pint_t addr, int& err) { return fRemoteProcInfo->get64(addr, err, fArg); } - pint_t getP(pint_t addr, int &err) { return fRemoteProcInfo->getP(addr, err, fArg); } - - uint64_t getULEB128(pint_t& addr, pint_t end) { return fRemoteProcInfo->getULEB128 (addr, end, fArg); } - int64_t getSLEB128(pint_t& addr, pint_t end) { return fRemoteProcInfo->getSLEB128 (addr, end, fArg); } - pint_t getEncodedP(pint_t& addr, pint_t end, uint8_t encoding); - double getDouble(pint_t addr); - v128 getVector(pint_t addr); - bool findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset); - bool findFunctionExtent(pint_t addr, unw_word_t* begin, unw_word_t* end); - bool findUnwindSections(pint_t addr, pint_t& mh, pint_t& eh_frame_start, pint_t& eh_frame_len, pint_t& compactStart); - RemoteProcInfo* getRemoteProcInfo () { return fRemoteProcInfo; } - unw_accessors_t* accessors() { return fRemoteProcInfo->getAccessors(); } - unw_addr_space_t wrap() { return (unw_addr_space_t) fAddrSpace; } -private: - void* localCopy(pint_t addr); - unw_addr_space_remote *fAddrSpace; - RemoteProcInfo* fRemoteProcInfo; - void* fArg; -}; - -template <typename P> -typename OtherAddressSpace<P>::pint_t OtherAddressSpace<P>::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding) -{ - pint_t startAddr = addr; - pint_t p = addr; - pint_t result; - - // first get value - switch (encoding & 0x0F) { - case DW_EH_PE_ptr: - result = fRemoteProcInfo->getP(addr, fArg); - p += sizeof(pint_t); - addr = p; - break; - case DW_EH_PE_uleb128: - result = fRemoteProcInfo->getULEB128(addr, end, fArg); - break; - case DW_EH_PE_udata2: - result = fRemoteProcInfo->get16(addr, fArg); - p += 2; - addr = p; - break; - case DW_EH_PE_udata4: - result = fRemoteProcInfo->get32(addr, fArg); - p += 4; - addr = p; - break; - case DW_EH_PE_udata8: - result = fRemoteProcInfo->get64(addr, fArg); - p += 8; - addr = p; - break; - case DW_EH_PE_sleb128: - result = fRemoteProcInfo->getSLEB128(addr, end, fArg); - break; - case DW_EH_PE_sdata2: - result = (int16_t)fRemoteProcInfo->get16(addr, fArg); - p += 2; - addr = p; - break; - case DW_EH_PE_sdata4: - result = (int32_t)fRemoteProcInfo->get32(addr, fArg); - p += 4; - addr = p; - break; - case DW_EH_PE_sdata8: - result = fRemoteProcInfo->get64(addr, fArg); - p += 8; - addr = p; - break; - default: - ABORT("unknown pointer encoding"); - } - - // then add relative offset - switch ( encoding & 0x70 ) { - case DW_EH_PE_absptr: - // do nothing - break; - case DW_EH_PE_pcrel: - result += startAddr; - break; - case DW_EH_PE_textrel: - ABORT("DW_EH_PE_textrel pointer encoding not supported"); - break; - case DW_EH_PE_datarel: - ABORT("DW_EH_PE_datarel pointer encoding not supported"); - break; - case DW_EH_PE_funcrel: - ABORT("DW_EH_PE_funcrel pointer encoding not supported"); - break; - case DW_EH_PE_aligned: - ABORT("DW_EH_PE_aligned pointer encoding not supported"); - break; - default: - ABORT("unknown pointer encoding"); - break; - } - - if ( encoding & DW_EH_PE_indirect ) - result = fRemoteProcInfo->getP(result, fArg); - - return result; -} - -template <typename P> -double OtherAddressSpace<P>::getDouble(pint_t addr) -{ - return fRemoteProcInfo->getDouble(addr, fArg); -} - -template <typename P> -v128 OtherAddressSpace<P>::getVector(pint_t addr) -{ - return fRemoteProcInfo->getVector(addr, fArg); -} - -template <typename P> -bool OtherAddressSpace<P>::findUnwindSections(pint_t addr, pint_t& mh, pint_t& eh_frame_start, pint_t& eh_frame_len, pint_t& compactStart) -{ - compactStart = 0; - uint64_t t_mh, t_text_start, t_text_end, t_eh_frame_start, t_eh_frame_len, t_compact_start; - if (fRemoteProcInfo->getImageAddresses (addr, t_mh, t_text_start, t_text_end, t_eh_frame_start, t_eh_frame_len, t_compact_start, fArg)) - { - mh = t_mh; - eh_frame_start = t_eh_frame_start; - eh_frame_len = t_eh_frame_len; - compactStart = t_compact_start; - return true; - } - return false; -} - -template <typename P> -bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset) -{ - return fRemoteProcInfo->findFunctionName (addr, buf, bufLen, offset, fArg); -} - -#endif // SUPPORT_REMOTE_UNWINDING - - -} // namespace lldb_private - - - -#endif // __ADDRESSSPACE_HPP__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/ArchDefaultUnwinder.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/ArchDefaultUnwinder.hpp deleted file mode 100644 index f7b8790579f..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/ArchDefaultUnwinder.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- ArchDefaultUnwinder.hpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// Unwind a stack frame using nothing but the default conventions on -// this architecture. - -#ifndef __ARCH_DEFAULT_UNWINDER_HPP -#define __ARCH_DEFAULT_UNWINDER_HPP - -#if defined (SUPPORT_REMOTE_UNWINDING) - -#include "AddressSpace.hpp" -#include "Registers.hpp" -#include "RemoteRegisterMap.hpp" -#include "RemoteProcInfo.hpp" - -namespace lldb_private -{ - -// As a last ditch attempt to unwind a stack frame, unwind by the -// architecture's typical conventions. We try compact unwind, eh frame CFI, -// and then assembly profiling if we have function bounds -- but if we're -// looking at an address with no function bounds or unwind info, make a best -// guess at how to get out. - -// In practice, this is usually hit when we try to step out of start() in a -// stripped application binary, we've jumped to 0x0, or we're in jitted code -// in the heap. - -template <typename A, typename R> -int stepByArchitectureDefault_x86 (A& addressSpace, R& registers, - uint64_t pc, int wordsize) { - R newRegisters(registers); - RemoteRegisterMap *rmap = addressSpace.getRemoteProcInfo()->getRegisterMap(); - int frame_reg = rmap->unwind_regno_for_frame_pointer(); - int stack_reg = rmap->unwind_regno_for_stack_pointer(); - int err; - - /* If the pc is 0x0 either we call'ed 0 (went thorugh a null function - pointer) or this is a thread in the middle of being created that has - no stack at all. - For the call-0x0 case, we know how to unwind that - the pc is at - the stack pointer. - - Otherwise follow the usual convention of trusting that RBP/EBP has the - start of the stack frame and we can find the caller's pc based on - that. */ - - uint64_t newpc, newframeptr; - newpc = 0; - newframeptr = -1; - if (pc == 0) { - uint64_t oldsp = registers.getRegister(stack_reg); - err = 0; - if (oldsp != 0) { - newpc = addressSpace.getP(registers.getRegister(stack_reg), err); - if (err != 0) - return UNW_EUNSPEC; - newRegisters.setIP (newpc); - newRegisters.setRegister (stack_reg, registers.getRegister(stack_reg) + - wordsize); - } - } - else { - newpc = addressSpace.getP(registers.getRegister(frame_reg) + - wordsize, err); - if (err != 0) - return UNW_EUNSPEC; - - newRegisters.setIP (newpc); - newframeptr = addressSpace.getP(registers.getRegister(frame_reg), - err); - if (err != 0) - return UNW_EUNSPEC; - - newRegisters.setRegister (frame_reg, newframeptr); - newRegisters.setRegister (stack_reg, registers.getRegister(frame_reg) + - (wordsize * 2)); - } - registers = newRegisters; - if (newpc == 0 || newframeptr == 0) - return UNW_STEP_END; - return UNW_STEP_SUCCESS; -} - -template <typename A> -int stepByArchitectureDefault (A& addressSpace, Registers_x86_64 ®isters, - uint64_t pc) { - return stepByArchitectureDefault_x86 (addressSpace, registers, pc, 8); -} - -template <typename A> -int stepByArchitectureDefault (A& addressSpace, Registers_x86& registers, - uint64_t pc) { - return stepByArchitectureDefault_x86 (addressSpace, registers, pc, 4); -} - -}; // namespace lldb_private - -#endif // SUPPORT_REMOTE_UNWINDING -#endif // __ARCH_DEFAULT_UNWINDER_HPP diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/AssemblyInstructions.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/AssemblyInstructions.hpp deleted file mode 100644 index 1e695d5e4f0..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/AssemblyInstructions.hpp +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- AssemblyInstructions.hpp --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __ASSEMBLY_INSTRUCTIONS_HPP -#define __ASSEMBLY_INSTRUCTIONS_HPP - -#if defined (SUPPORT_REMOTE_UNWINDING) - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_CONSTANT_MACROS -#define __STDC_CONSTANT_MACROS -#endif - -#include <limits.h> -#include <stdint.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <map> - -#include "libunwind.h" -#include "AssemblyParser.hpp" -#include "AddressSpace.hpp" -#include "Registers.hpp" -#include "RemoteUnwindProfile.h" - -namespace lldb_private -{ - -// A debug function to dump the contents of an RemoteUnwindProfile to -// stdout in a human readable form. - -template <typename A, typename R> -void printProfile (A& addressSpace, uint64_t pc, RemoteUnwindProfile* profile, R& registers) { - RemoteProcInfo *procinfo = addressSpace.getRemoteProcInfo(); - RemoteRegisterMap *regmap = procinfo->getRegisterMap(); - - procinfo->logDebug ("Print profile: given pc of 0x%llx, profile has range 0x%llx - 0x%llx", pc, profile->fStart, profile->fEnd); - procinfo->logDebug ("CFA locations:"); - std::map<uint64_t, RemoteUnwindProfile::CFALocation>::iterator i; - for (i = profile->cfa.begin(); i != profile->cfa.end(); ++i) { - procinfo->logDebug (" as of 0x%llx cfa is based off of reg %d (%s) offset %d", i->first, i->second.regno, regmap->unwind_regno_to_name(i->second.regno), i->second.offset); - } - procinfo->logDebug ("Caller's saved IP is at %d bytes offset from the cfa", (int)profile->returnAddress.value); - procinfo->logDebug ("Register saves:"); - std::map<uint64_t, std::vector<RemoteUnwindProfile::SavedReg> >::iterator j; - for (j = profile->saved_registers.begin(); j != profile->saved_registers.end(); ++j) { - char *tbuf1, *tbuf2, *tbuf3; - asprintf (&tbuf1, " at pc 0x%llx there are %d registers saved ", j->first, (int) j->second.size()); - std::vector<RemoteUnwindProfile::SavedReg>::iterator k; - for (k = j->second.begin(); k != j->second.end(); ++k) { - if (k->location == RemoteUnwindProfile::kRegisterOffsetFromCFA) { - asprintf (&tbuf2, "[reg %d (%s) is %d bytes from cfa] ", k->regno, regmap->unwind_regno_to_name(k->regno), (int) k->value); - int newlen = strlen (tbuf1) + strlen (tbuf2) + 1; - tbuf3 = (char *) malloc (newlen); - strcpy (tbuf3, tbuf1); - strcat (tbuf3, tbuf2); - free (tbuf1); - free (tbuf2); - tbuf1 = tbuf3; - } - if (k->location == RemoteUnwindProfile::kRegisterIsCFA) { - asprintf (&tbuf2, "[reg %d (%s) is the same as the cfa] ", k->regno, regmap->unwind_regno_to_name(k->regno)); - int newlen = strlen (tbuf1) + strlen (tbuf2) + 1; - tbuf3 = (char *) malloc (newlen); - strcpy (tbuf3, tbuf1); - strcat (tbuf3, tbuf2); - free (tbuf1); - free (tbuf2); - tbuf1 = tbuf3; - } - } - procinfo->logDebug ("%s", tbuf1); - free (tbuf1); - } -} - -template <typename A, typename R> -int stepWithAssembly (A& addressSpace, uint64_t pc, RemoteUnwindProfile* profile, R& registers) { - R newRegisters(registers); - RemoteProcInfo *procinfo = addressSpace.getRemoteProcInfo(); - if (pc > profile->fEnd) - ABORT("stepWithAssembly called with pc not in RemoteUnwindProfile's bounds"); - - if (procinfo && (procinfo->getDebugLoggingLevel() & UNW_LOG_LEVEL_DEBUG)) - printProfile (addressSpace, pc, profile, registers); - - std::map<uint64_t, RemoteUnwindProfile::CFALocation>::iterator i = profile->cfa.lower_bound (pc); - if (i == profile->cfa.begin() && i == profile->cfa.end()) - return UNW_EINVAL; - if (i == profile->cfa.end()) { - --i; - } else { - if (i != profile->cfa.begin() && i->first != pc) - --i; - } - - uint64_t cfa = registers.getRegister (i->second.regno) + i->second.offset; - - std::map<uint64_t, std::vector<RemoteUnwindProfile::SavedReg> >::iterator j; - - for (j = profile->saved_registers.begin(); j != profile->saved_registers.end() && j->first <= pc; ++j) { - std::vector<RemoteUnwindProfile::SavedReg>::iterator k = j->second.begin(); - for (; k != j->second.end(); ++k) { - RemoteUnwindProfile::SavedReg sr = *k; - if (sr.type == RemoteUnwindProfile::kGeneralPurposeRegister) { - uint64_t result; - int err = 0; - switch (sr.location) { - case RemoteUnwindProfile::kRegisterOffsetFromCFA: - result = addressSpace.getP(cfa + sr.value, err); - break; - case RemoteUnwindProfile::kRegisterIsCFA: - result = cfa; - break; - default: - ABORT("Unknown saved register location in stepWithAssembly."); - } - // If we failed to read remote memory, stop unwinding. - if (err) - return UNW_STEP_END; - newRegisters.setRegister (sr.regno, result); - } - } - } - newRegisters.setSP(cfa); - uint64_t ip = addressSpace.getP(cfa + profile->returnAddress.value); - if (ip == 0) - return UNW_STEP_END; - newRegisters.setIP(ip); - registers = newRegisters; - return UNW_STEP_SUCCESS; -} - -}; // namespace lldb_private - -#endif // SUPPORT_REMOTE_UNWINDING -#endif //ASSEMBLY_INSTRUCTIONS_HPP diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/AssemblyParser.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/AssemblyParser.hpp deleted file mode 100644 index 50d0c938ebc..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/AssemblyParser.hpp +++ /dev/null @@ -1,411 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- AssemblyParser.hpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// Disassemble the prologue instructions in functions, create a profile -// of stack movements and register saves performed therein. - -#ifndef __ASSEMBLY_PARSER_HPP -#define __ASSEMBLY_PARSER_HPP - -#if defined (SUPPORT_REMOTE_UNWINDING) - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_CONSTANT_MACROS -#define __STDC_CONSTANT_MACROS -#endif -#include <limits.h> -#include <stdint.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <map> -#include <vector> - -#include "libunwind.h" -#include "RemoteProcInfo.hpp" -#include "Registers.hpp" -#include "FileAbstraction.hpp" -#include "AddressSpace.hpp" -#include "RemoteUnwindProfile.h" - -namespace lldb_private -{ - -// Analyze the instructions in an x86_64/i386 function prologue, fill out an RemoteUnwindProfile. - -class AssemblyParse_x86 { -public: - enum { kMaxInstructionByteSize = 32 }; - - AssemblyParse_x86 (RemoteProcInfo& procinfo, unw_accessors_t *acc, unw_addr_space_t as, void *arg) : fArg(arg), fRemoteProcInfo(procinfo), fAccessors(acc), fAs(as) { - fRegisterMap = fRemoteProcInfo.getRegisterMap(); - if (fRemoteProcInfo.getTargetArch() == UNW_TARGET_X86_64) { - fStackPointerRegnum = UNW_X86_64_RSP; - fFramePointerRegnum = UNW_X86_64_RBP; - fWordSize = 8; - } else { - fStackPointerRegnum = UNW_X86_ESP; - fFramePointerRegnum = UNW_X86_EBP; - fWordSize = 4; - } - } - - uint32_t extract_4_LE (uint8_t *b) { - uint32_t v = 0; - for (int i = 3; i >= 0; i--) - v = (v << 8) | b[i]; - return v; - } - - bool push_rbp_pattern_p (); - bool push_0_pattern_p (); - bool mov_rsp_rbp_pattern_p (); - bool sub_rsp_pattern_p (int *amount); - bool push_reg_p (int *regno); - bool mov_reg_to_local_stack_frame_p (int *regno, int *rbp_offset); - bool ret_pattern_p (); - bool profileFunction (uint64_t start, uint64_t end, RemoteUnwindProfile& profile); - -private: - - void *fArg; - uint8_t fCurInsnByteBuf[kMaxInstructionByteSize]; - int fCurInsnSize; - RemoteProcInfo& fRemoteProcInfo; - RemoteRegisterMap *fRegisterMap; - unw_accessors_t *fAccessors; - unw_addr_space_t fAs; - int fWordSize; - int fStackPointerRegnum; - int fFramePointerRegnum; -}; - -// Macro to detect if this is a REX mode prefix byte. -#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48) - -// The high bit which should be added to the source register number (the "R" bit) -#define REX_W_SRCREG(opcode) (((opcode) & 0x4) >> 2) - -// The high bit which should be added to the destination register number (the "B" bit) -#define REX_W_DSTREG(opcode) ((opcode) & 0x1) - -// pushq %rbp [0x55] -bool AssemblyParse_x86::push_rbp_pattern_p () { - uint8_t *p = fCurInsnByteBuf; - if (*p == 0x55) - return true; - return false; -} - -// pushq $0 ; the first instruction in start() [0x6a 0x00] -bool AssemblyParse_x86::push_0_pattern_p () -{ - uint8_t *p = fCurInsnByteBuf; - if (*p == 0x6a && *(p + 1) == 0x0) - return true; - return false; -} - -// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] -// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5] -bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () { - uint8_t *p = fCurInsnByteBuf; - if (fWordSize == 8 && *p == 0x48) - p++; - if (*(p) == 0x8b && *(p + 1) == 0xec) - return true; - if (*(p) == 0x89 && *(p + 1) == 0xe5) - return true; - return false; -} - -// subq $0x20, %rsp -bool AssemblyParse_x86::sub_rsp_pattern_p (int *amount) { - uint8_t *p = fCurInsnByteBuf; - if (fWordSize == 8 && *p == 0x48) - p++; - // 8-bit immediate operand - if (*p == 0x83 && *(p + 1) == 0xec) { - *amount = (int8_t) *(p + 2); - return true; - } - // 32-bit immediate operand - if (*p == 0x81 && *(p + 1) == 0xec) { - *amount = (int32_t) extract_4_LE (p + 2); - return true; - } - // Not handled: [0x83 0xc4] for imm8 with neg values - // [0x81 0xc4] for imm32 with neg values - return false; -} - -// pushq %rbx -// pushl $ebx -bool AssemblyParse_x86::push_reg_p (int *regno) { - uint8_t *p = fCurInsnByteBuf; - int regno_prefix_bit = 0; - // If we have a rex prefix byte, check to see if a B bit is set - if (fWordSize == 8 && *p == 0x41) { - regno_prefix_bit = 1 << 3; - p++; - } - if (*p >= 0x50 && *p <= 0x57) { - int r = (*p - 0x50) | regno_prefix_bit; - if (fRegisterMap->machine_regno_to_unwind_regno (r, *regno) == true) { - return true; - } - } - return false; -} - -// Look for an instruction sequence storing a nonvolatile register -// on to the stack frame. - -// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0] -// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4] -bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int *regno, int *rbp_offset) { - uint8_t *p = fCurInsnByteBuf; - int src_reg_prefix_bit = 0; - int target_reg_prefix_bit = 0; - - if (fWordSize == 8 && REX_W_PREFIX_P (*p)) { - src_reg_prefix_bit = REX_W_SRCREG (*p) << 3; - target_reg_prefix_bit = REX_W_DSTREG (*p) << 3; - if (target_reg_prefix_bit == 1) { - // rbp/ebp don't need a prefix bit - we know this isn't the - // reg we care about. - return false; - } - p++; - } - - if (*p == 0x89) { - /* Mask off the 3-5 bits which indicate the destination register - if this is a ModR/M byte. */ - int opcode_destreg_masked_out = *(p + 1) & (~0x38); - - /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101 - and three bits between them, e.g. 01nnn101 - We're looking for a destination of ebp-disp8 or ebp-disp32. */ - int immsize; - if (opcode_destreg_masked_out == 0x45) - immsize = 2; - else if (opcode_destreg_masked_out == 0x85) - immsize = 4; - else - return false; - - int offset = 0; - if (immsize == 2) - offset = (int8_t) *(p + 2); - if (immsize == 4) - offset = (uint32_t) extract_4_LE (p + 2); - if (offset > 0) - return false; - - int savedreg = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit; - if (fRegisterMap->machine_regno_to_unwind_regno (savedreg, *regno) == true) { - *rbp_offset = offset > 0 ? offset : -offset; - return true; - } - } - return false; -} - -// ret [0xc9] or [0xc2 imm8] or [0xca imm8] -bool AssemblyParse_x86::ret_pattern_p () { - uint8_t *p = fCurInsnByteBuf; - if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3) - return true; - return false; -} - -bool AssemblyParse_x86::profileFunction (uint64_t start, uint64_t end, RemoteUnwindProfile& profile) { - if (start == -1 || end == 0) - return false; - - profile.fStart = start; - profile.fEnd = end; - profile.fRegSizes[RemoteUnwindProfile::kGeneralPurposeRegister] = fWordSize; - profile.fRegSizes[RemoteUnwindProfile::kFloatingPointRegister] = 8; - profile.fRegSizes[RemoteUnwindProfile::kVectorRegister] = 16; - - // On function entry, the CFA is rsp+fWordSize - - RemoteUnwindProfile::CFALocation initial_cfaloc; - initial_cfaloc.regno = fStackPointerRegnum; - initial_cfaloc.offset = fWordSize; - profile.cfa[start] = initial_cfaloc; - - // The return address is at CFA - fWordSize - // CFA doesn't change value during the lifetime of the function (hence "C") - // so the returnAddress is the same for the duration of the function. - - profile.returnAddress.regno = 0; - profile.returnAddress.location = RemoteUnwindProfile::kRegisterOffsetFromCFA; - profile.returnAddress.value = -fWordSize; - profile.returnAddress.adj = 0; - profile.returnAddress.type = RemoteUnwindProfile::kGeneralPurposeRegister; - - // The caller's rsp has the same value as the CFA at all points during - // this function's lifetime. - - RemoteUnwindProfile::SavedReg rsp_loc; - rsp_loc.regno = fStackPointerRegnum; - rsp_loc.location = RemoteUnwindProfile::kRegisterIsCFA; - rsp_loc.value = 0; - rsp_loc.adj = 0; - rsp_loc.type = RemoteUnwindProfile::kGeneralPurposeRegister; - profile.saved_registers[start].push_back(rsp_loc); - profile.fRegistersSaved[fStackPointerRegnum] = 1; - - int non_prologue_insn_count = 0; - int insn_count = 0; - uint64_t cur_addr = start; - uint64_t first_insn_past_prologue = start; - int push_rbp_seen = 0; - int current_cfa_register = fStackPointerRegnum; - int sp_adjustments = 0; - - while (cur_addr < end && non_prologue_insn_count < 10) - { - int offset, regno; - uint64_t next_addr; - insn_count++; - int is_prologue_insn = 0; - - if (fAccessors->instruction_length (fAs, cur_addr, &fCurInsnSize, fArg) != 0) { - /* An error parsing the instruction; stop scanning. */ - break; - } - assert (fCurInsnSize <= kMaxInstructionByteSize); - if (fRemoteProcInfo.getBytes (cur_addr, fCurInsnSize, fCurInsnByteBuf, fArg) == 0) - return false; - next_addr = cur_addr + fCurInsnSize; - - // start () opens with a 'push $0x0' which is in the saved ip slot on the stack - - // so we know to stop backtracing here. We need to ignore this instruction. - if (push_0_pattern_p () && push_rbp_seen == 0 && insn_count == 1) - { - cur_addr = next_addr; - first_insn_past_prologue = next_addr; - continue; - } - - if (push_rbp_pattern_p () && push_rbp_seen == 0) - { - if (current_cfa_register == fStackPointerRegnum) { - sp_adjustments -= fWordSize; - RemoteUnwindProfile::CFALocation cfaloc; - cfaloc.regno = fStackPointerRegnum; - cfaloc.offset = abs (sp_adjustments - fWordSize); - profile.cfa[next_addr] = cfaloc; - } - - RemoteUnwindProfile::SavedReg sreg; - sreg.regno = fFramePointerRegnum; - sreg.location = RemoteUnwindProfile::kRegisterOffsetFromCFA; - sreg.value = sp_adjustments - fWordSize; - sreg.adj = 0; - sreg.type = RemoteUnwindProfile::kGeneralPurposeRegister; - profile.saved_registers[next_addr].push_back(sreg); - - push_rbp_seen = 1; - profile.fRegistersSaved[fFramePointerRegnum] = 1; - is_prologue_insn = 1; - goto next_iteration; - } - if (mov_rsp_rbp_pattern_p ()) { - RemoteUnwindProfile::CFALocation cfaloc; - cfaloc.regno = fFramePointerRegnum; - cfaloc.offset = abs (sp_adjustments - fWordSize); - profile.cfa[next_addr] = cfaloc; - current_cfa_register = fFramePointerRegnum; - is_prologue_insn = 1; - goto next_iteration; - } - if (ret_pattern_p ()) { - break; - } - if (sub_rsp_pattern_p (&offset)) { - sp_adjustments -= offset; - if (current_cfa_register == fStackPointerRegnum) { - RemoteUnwindProfile::CFALocation cfaloc; - cfaloc.regno = fStackPointerRegnum; - cfaloc.offset = abs (sp_adjustments - fWordSize); - profile.cfa[next_addr] = cfaloc; - } - is_prologue_insn = 1; - } - if (push_reg_p (®no)) { - sp_adjustments -= fWordSize; - if (current_cfa_register == fStackPointerRegnum) { - RemoteUnwindProfile::CFALocation cfaloc; - cfaloc.regno = fStackPointerRegnum; - cfaloc.offset = abs (sp_adjustments - fWordSize); - profile.cfa[next_addr] = cfaloc; - is_prologue_insn = 1; - } - if (fRegisterMap->nonvolatile_reg_p (regno) && profile.fRegistersSaved[regno] == 0) { - RemoteUnwindProfile::SavedReg sreg; - sreg.regno = regno; - sreg.location = RemoteUnwindProfile::kRegisterOffsetFromCFA; - sreg.value = sp_adjustments - fWordSize; - sreg.adj = 0; - sreg.type = RemoteUnwindProfile::kGeneralPurposeRegister; - profile.saved_registers[next_addr].push_back(sreg); - profile.fRegistersSaved[regno] = 1; - is_prologue_insn = 1; - } - } - if (mov_reg_to_local_stack_frame_p (®no, &offset) - && fRegisterMap->nonvolatile_reg_p (regno) - && profile.fRegistersSaved[regno] == 0) { - RemoteUnwindProfile::SavedReg sreg; - sreg.regno = regno; - sreg.location = RemoteUnwindProfile::kRegisterOffsetFromCFA; - sreg.value = offset - fWordSize; - sreg.adj = 0; - sreg.type = RemoteUnwindProfile::kGeneralPurposeRegister; - profile.saved_registers[next_addr].push_back(sreg); - profile.fRegistersSaved[regno] = 1; - is_prologue_insn = 1; - } -next_iteration: - if (is_prologue_insn) { - first_insn_past_prologue = next_addr; - non_prologue_insn_count = 0; - } - cur_addr = next_addr; - non_prologue_insn_count++; - } - profile.fFirstInsnPastPrologue = first_insn_past_prologue; - return true; -} - - - - -bool AssemblyParse (RemoteProcInfo *procinfo, unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, RemoteUnwindProfile &profile, void *arg) { - if (procinfo->getTargetArch() == UNW_TARGET_X86_64 || procinfo->getTargetArch() == UNW_TARGET_I386) { - AssemblyParse_x86 parser(*procinfo, acc, as, arg); - return parser.profileFunction (start, end, profile); - } else { - ABORT("Only x86_64 and i386 assembly parsing supported at this time"); - return false; - } -} - -}; // namespace lldb_private - -#endif // SUPPORT_REMOTE_UNWINDING -#endif //ASSEMBLY_PARSER_HPP diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/CompactUnwinder.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/CompactUnwinder.hpp deleted file mode 100644 index dda2308ada6..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/CompactUnwinder.hpp +++ /dev/null @@ -1,1019 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- CompactUnwinder.hpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// -// C++ interface to lower levels of libuwind -// - -#ifndef __COMPACT_UNWINDER_HPP__ -#define __COMPACT_UNWINDER_HPP__ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include <libunwind.h> -#include <mach-o/compact_unwind_encoding.h> - -#include "AddressSpace.hpp" -#include "Registers.hpp" - - - -#define EXTRACT_BITS(value, mask) \ - ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) ) - -#define SUPPORT_OLD_BINARIES 0 - -namespace lldb_private { - - - -/// -/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka unwind) by -/// modifying a Registers_x86 register set -/// -template <typename A> -class CompactUnwinder_x86 -{ -public: - - static int stepWithCompactEncoding(compact_unwind_encoding_t info, uint32_t functionStart, A& addressSpace, Registers_x86& registers); - -private: - typename A::pint_t pint_t; - - static void frameUnwind(A& addressSpace, Registers_x86& registers); - static void framelessUnwind(A& addressSpace, typename A::pint_t returnAddressLocation, Registers_x86& registers); - static int stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers); - static int stepWithCompactEncodingFrameless(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers, bool indirectStackSize); -#if SUPPORT_OLD_BINARIES - static int stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers); -#endif -}; - - - -template <typename A> -int CompactUnwinder_x86<A>::stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers) -{ - //fprintf(stderr, "stepWithCompactEncoding(0x%08X)\n", compactEncoding); - switch ( compactEncoding & UNWIND_X86_MODE_MASK ) { -#if SUPPORT_OLD_BINARIES - case UNWIND_X86_MODE_COMPATIBILITY: - return stepWithCompactEncodingCompat(compactEncoding, functionStart, addressSpace, registers); -#endif - case UNWIND_X86_MODE_EBP_FRAME: - return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, addressSpace, registers); - case UNWIND_X86_MODE_STACK_IMMD: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, false); - case UNWIND_X86_MODE_STACK_IND: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, true); - } - ABORT("invalid compact unwind encoding"); -} - - -template <typename A> -int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A& addressSpace, Registers_x86& registers) -{ - uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); - uint32_t savedRegistersLocations = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS); - - uint64_t savedRegisters = registers.getEBP() - 4*savedRegistersOffset; - for (int i=0; i < 5; ++i) { - switch (savedRegistersLocations & 0x7) { - case UNWIND_X86_REG_NONE: - // no register saved in this slot - break; - case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); - break; - default: - DEBUG_MESSAGE("bad register for EBP frame, encoding=%08X for function starting at 0x%X\n", compactEncoding, functionStart); - ABORT("invalid compact unwind encoding"); - } - savedRegisters += 4; - savedRegistersLocations = (savedRegistersLocations >> 3); - } - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; -} - - -template <typename A> -int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(compact_unwind_encoding_t encoding, uint32_t functionStart, - A& addressSpace, Registers_x86& registers, bool indirectStackSize) -{ - uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); - uint32_t stackAdjust = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); - uint32_t regCount = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); - uint32_t stackSize = stackSizeEncoded*4; - if ( indirectStackSize ) { - // stack size is encoded in subl $xxx,%esp instruction - uint32_t subl = addressSpace.get32(functionStart+stackSizeEncoded); - stackSize = subl + 4*stackAdjust; - } - // decompress permutation - int permunreg[6]; - switch ( regCount ) { - case 6: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation/60; - permutation -= (permunreg[0]*60); - permunreg[1] = permutation/12; - permutation -= (permunreg[1]*12); - permunreg[2] = permutation/3; - permutation -= (permunreg[2]*3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation/20; - permutation -= (permunreg[0]*20); - permunreg[1] = permutation/4; - permutation -= (permunreg[1]*4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation/5; - permutation -= (permunreg[0]*5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - // re-number registers back to standard numbers - int registersSaved[6]; - bool used[7] = { false, false, false, false, false, false, false }; - for (uint32_t i=0; i < regCount; ++i) { - int renum = 0; - for (int u=1; u < 7; ++u) { - if ( !used[u] ) { - if ( renum == permunreg[i] ) { - registersSaved[i] = u; - used[u] = true; - break; - } - ++renum; - } - } - } - uint64_t savedRegisters = registers.getSP() + stackSize - 4 - 4*regCount; - for (uint32_t i=0; i < regCount; ++i) { - switch ( registersSaved[i] ) { - case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EBP: - registers.setEBP(addressSpace.get32(savedRegisters)); - break; - default: - DEBUG_MESSAGE("bad register for frameless, encoding=%08X for function starting at 0x%X\n", encoding, functionStart); - ABORT("invalid compact unwind encoding"); - } - savedRegisters += 4; - } - framelessUnwind(addressSpace, savedRegisters, registers); - return UNW_STEP_SUCCESS; -} - - -#if SUPPORT_OLD_BINARIES -template <typename A> -int CompactUnwinder_x86<A>::stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A& addressSpace, Registers_x86& registers) -{ - //fprintf(stderr, "stepWithCompactEncoding(0x%08X)\n", compactEncoding); - typename A::pint_t savedRegisters; - uint32_t stackValue = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_SIZE); - uint32_t stackSize; - uint32_t stackAdjust; - switch (compactEncoding & UNWIND_X86_CASE_MASK ) { - case UNWIND_X86_UNWIND_INFO_UNSPECIFIED: - return UNW_ENOINFO; - - case UNWIND_X86_EBP_FRAME_NO_REGS: - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_EBX: - savedRegisters = registers.getEBP() - 4; - registers.setEBX(addressSpace.get32(savedRegisters)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_ESI: - savedRegisters = registers.getEBP() - 4; - registers.setESI(addressSpace.get32(savedRegisters)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_EDI: - savedRegisters = registers.getEBP() - 4; - registers.setEDI(addressSpace.get32(savedRegisters)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_EBX_ESI: - savedRegisters = registers.getEBP() - 8; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_ESI_EDI: - savedRegisters = registers.getEBP() - 8; - registers.setESI(addressSpace.get32(savedRegisters)); - registers.setEDI(addressSpace.get32(savedRegisters+4)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_EBX_ESI_EDI: - savedRegisters = registers.getEBP() - 12; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - registers.setEDI(addressSpace.get32(savedRegisters+8)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_EBP_FRAME_EBX_EDI: - savedRegisters = registers.getEBP() - 8; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setEDI(addressSpace.get32(savedRegisters+4)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_NO_REGS: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*0; - framelessUnwind(addressSpace, savedRegisters+4*0, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_EBX: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*1; - registers.setEBX(addressSpace.get32(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+4*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_ESI: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*1; - registers.setESI(addressSpace.get32(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+4*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_EDI: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*1; - registers.setEDI(addressSpace.get32(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+4*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_EBX_ESI: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*2; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - framelessUnwind(addressSpace, savedRegisters+4*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_ESI_EDI: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*2; - registers.setESI(addressSpace.get32(savedRegisters)); - registers.setEDI(addressSpace.get32(savedRegisters+4)); - framelessUnwind(addressSpace, savedRegisters+4*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_ESI_EDI_EBP: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*3; - registers.setESI(addressSpace.get32(savedRegisters)); - registers.setEDI(addressSpace.get32(savedRegisters+4)); - registers.setEBP(addressSpace.get32(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+4*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_EBX_ESI_EDI: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*3; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - registers.setEDI(addressSpace.get32(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+4*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IMM_STK_EBX_ESI_EDI_EBP: - stackSize = stackValue * 4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*4; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - registers.setEDI(addressSpace.get32(savedRegisters+8)); - registers.setEBP(addressSpace.get32(savedRegisters+12)); - framelessUnwind(addressSpace, savedRegisters+4*4, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_NO_REGS: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*0; - framelessUnwind(addressSpace, savedRegisters+4*0, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_EBX: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*1; - registers.setEBX(addressSpace.get32(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+4*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_ESI: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*1; - registers.setESI(addressSpace.get32(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+4*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_EDI: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*1; - registers.setEDI(addressSpace.get32(savedRegisters)); - return UNW_STEP_SUCCESS; - framelessUnwind(addressSpace, savedRegisters+4*1, registers); - - case UNWIND_X86_IND_STK_EBX_ESI: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*2; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - framelessUnwind(addressSpace, savedRegisters+4*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_ESI_EDI: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*2; - registers.setESI(addressSpace.get32(savedRegisters)); - registers.setEDI(addressSpace.get32(savedRegisters+4)); - framelessUnwind(addressSpace, savedRegisters+4*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_ESI_EDI_EBP: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*3; - registers.setESI(addressSpace.get32(savedRegisters)); - registers.setEDI(addressSpace.get32(savedRegisters+4)); - registers.setEBP(addressSpace.get32(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+4*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_EBX_ESI_EDI: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*3; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - registers.setEDI(addressSpace.get32(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+4*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_IND_STK_EBX_ESI_EDI_EBP: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_STACK_ADJUST); - stackSize += stackAdjust*4; - savedRegisters = registers.getSP() + stackSize - 4 - 4*4; - registers.setEBX(addressSpace.get32(savedRegisters)); - registers.setESI(addressSpace.get32(savedRegisters+4)); - registers.setEDI(addressSpace.get32(savedRegisters+8)); - registers.setEBP(addressSpace.get32(savedRegisters+12)); - framelessUnwind(addressSpace, savedRegisters+4*4, registers); - return UNW_STEP_SUCCESS; - - default: - DEBUG_MESSAGE("unknown compact unwind encoding %08X for function starting at 0x%X\n", - compactEncoding & UNWIND_X86_CASE_MASK, functionStart); - ABORT("unknown compact unwind encoding"); - } - return UNW_EINVAL; -} -#endif // SUPPORT_OLD_BINARIES - - - -template <typename A> -void CompactUnwinder_x86<A>::frameUnwind(A& addressSpace, Registers_x86& registers) -{ - typename A::pint_t bp = registers.getEBP(); - // ebp points to old ebp - registers.setEBP(addressSpace.get32(bp)); - // old esp is ebp less saved ebp and return address - registers.setSP(bp+8); - // pop return address into eip - registers.setIP(addressSpace.get32(bp+4)); -} - -template <typename A> -void CompactUnwinder_x86<A>::framelessUnwind(A& addressSpace, typename A::pint_t returnAddressLocation, Registers_x86& registers) -{ - // return address is on stack after last saved register - registers.setIP(addressSpace.get32(returnAddressLocation)); - // old esp is before return address - registers.setSP(returnAddressLocation+4); -} - - - - - -/// -/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka unwind) by -/// modifying a Registers_x86_64 register set -/// -template <typename A> -class CompactUnwinder_x86_64 -{ -public: - - static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers); - -private: - typename A::pint_t pint_t; - - static void frameUnwind(A& addressSpace, Registers_x86_64& registers); - static void framelessUnwind(A& addressSpace, uint64_t returnAddressLocation, Registers_x86_64& registers); - static int stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers); - static int stepWithCompactEncodingFrameless(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers, bool indirectStackSize); -#if SUPPORT_OLD_BINARIES - static int stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers); -#endif -}; - - -template <typename A> -int CompactUnwinder_x86_64<A>::stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers) -{ - //fprintf(stderr, "stepWithCompactEncoding(0x%08X)\n", compactEncoding); - switch ( compactEncoding & UNWIND_X86_64_MODE_MASK ) { -#if SUPPORT_OLD_BINARIES - case UNWIND_X86_64_MODE_COMPATIBILITY: - return stepWithCompactEncodingCompat(compactEncoding, functionStart, addressSpace, registers); -#endif - case UNWIND_X86_64_MODE_RBP_FRAME: - return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, addressSpace, registers); - case UNWIND_X86_64_MODE_STACK_IMMD: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, false); - case UNWIND_X86_64_MODE_STACK_IND: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, true); - } - ABORT("invalid compact unwind encoding"); -} - - -template <typename A> -int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A& addressSpace, Registers_x86_64& registers) -{ - uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); - uint32_t savedRegistersLocations = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); - - uint64_t savedRegisters = registers.getRBP() - 8*savedRegistersOffset; - for (int i=0; i < 5; ++i) { - int readerr = 0; - switch (savedRegistersLocations & 0x7) { - case UNWIND_X86_64_REG_NONE: - // no register saved in this slot - break; - case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters, readerr)); - break; - case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters, readerr)); - break; - case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters, readerr)); - break; - case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters, readerr)); - break; - case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters, readerr)); - break; - default: - DEBUG_MESSAGE("bad register for RBP frame, encoding=%08X for function starting at 0x%llX\n", compactEncoding, functionStart); - ABORT("invalid compact unwind encoding"); - } - // Error reading memory while doing a remote unwind? - if (readerr) - return UNW_STEP_END; - - savedRegisters += 8; - savedRegistersLocations = (savedRegistersLocations >> 3); - } - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; -} - - -template <typename A> -int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(compact_unwind_encoding_t encoding, uint64_t functionStart, - A& addressSpace, Registers_x86_64& registers, bool indirectStackSize) -{ - uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); - uint32_t stackAdjust = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); - uint32_t regCount = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); - uint32_t stackSize = stackSizeEncoded*8; - if ( indirectStackSize ) { - // stack size is encoded in subl $xxx,%esp instruction - uint32_t subl = addressSpace.get32(functionStart+stackSizeEncoded); - stackSize = subl + 8*stackAdjust; - } - // decompress permutation - int permunreg[6]; - switch ( regCount ) { - case 6: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation/60; - permutation -= (permunreg[0]*60); - permunreg[1] = permutation/12; - permutation -= (permunreg[1]*12); - permunreg[2] = permutation/3; - permutation -= (permunreg[2]*3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation/20; - permutation -= (permunreg[0]*20); - permunreg[1] = permutation/4; - permutation -= (permunreg[1]*4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation/5; - permutation -= (permunreg[0]*5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - // re-number registers back to standard numbers - int registersSaved[6]; - bool used[7] = { false, false, false, false, false, false, false }; - for (uint32_t i=0; i < regCount; ++i) { - int renum = 0; - for (int u=1; u < 7; ++u) { - if ( !used[u] ) { - if ( renum == permunreg[i] ) { - registersSaved[i] = u; - used[u] = true; - break; - } - ++renum; - } - } - } - uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8*regCount; - for (uint32_t i=0; i < regCount; ++i) { - switch ( registersSaved[i] ) { - case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_RBP: - registers.setRBP(addressSpace.get64(savedRegisters)); - break; - default: - DEBUG_MESSAGE("bad register for frameless, encoding=%08X for function starting at 0x%llX\n", encoding, functionStart); - ABORT("invalid compact unwind encoding"); - } - savedRegisters += 8; - } - framelessUnwind(addressSpace, savedRegisters, registers); - return UNW_STEP_SUCCESS; -} - -#if SUPPORT_OLD_BINARIES -template <typename A> -int CompactUnwinder_x86_64<A>::stepWithCompactEncodingCompat(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A& addressSpace, Registers_x86_64& registers) -{ - uint64_t savedRegisters; - uint32_t stackValue = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_SIZE); - uint64_t stackSize; - uint32_t stackAdjust; - - switch (compactEncoding & UNWIND_X86_64_CASE_MASK ) { - case UNWIND_X86_64_UNWIND_INFO_UNSPECIFIED: - return UNW_ENOINFO; - - case UNWIND_X86_64_RBP_FRAME_NO_REGS: - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_RBP_FRAME_RBX: - savedRegisters = registers.getRBP() - 8*1; - registers.setRBX(addressSpace.get64(savedRegisters)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_RBP_FRAME_RBX_R12: - savedRegisters = registers.getRBP() - 8*2; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_RBP_FRAME_RBX_R12_R13: - savedRegisters = registers.getRBP() - 8*3; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_RBP_FRAME_RBX_R12_R13_R14: - savedRegisters = registers.getRBP() - 8*4; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - registers.setR14(addressSpace.get64(savedRegisters+24)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_RBP_FRAME_RBX_R12_R13_R14_R15: - savedRegisters = registers.getRBP() - 8*5; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - registers.setR14(addressSpace.get64(savedRegisters+24)); - registers.setR15(addressSpace.get64(savedRegisters+32)); - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_NO_REGS: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*0; - framelessUnwind(addressSpace, savedRegisters+8*0, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*1; - registers.setRBX(addressSpace.get64(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+8*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_R12: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*2; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+8*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_RBP: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*2; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+8*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_R12_R13: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*3; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - framelessUnwind(addressSpace, savedRegisters+8*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_R12_R13_R14: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*4; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - registers.setR14(addressSpace.get64(savedRegisters+24)); - framelessUnwind(addressSpace, savedRegisters+8*4, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_R12_R13_R14_R15: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*5; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - registers.setR14(addressSpace.get64(savedRegisters+24)); - registers.setR15(addressSpace.get64(savedRegisters+32)); - framelessUnwind(addressSpace, savedRegisters+8*5, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_RBP_R12_R13_R14_R15: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*6; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - registers.setR13(addressSpace.get64(savedRegisters+24)); - registers.setR14(addressSpace.get64(savedRegisters+32)); - registers.setR15(addressSpace.get64(savedRegisters+40)); - framelessUnwind(addressSpace, savedRegisters+8*6, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_RBP_R12: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*3; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - framelessUnwind(addressSpace, savedRegisters+8*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_RBP_R12_R13: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*4; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - registers.setR13(addressSpace.get64(savedRegisters+24)); - framelessUnwind(addressSpace, savedRegisters+8*4, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IMM_STK_RBX_RBP_R12_R13_R14: - stackSize = stackValue * 8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*5; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - registers.setR13(addressSpace.get64(savedRegisters+24)); - registers.setR14(addressSpace.get64(savedRegisters+32)); - framelessUnwind(addressSpace, savedRegisters+8*5, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_NO_REGS: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*0; - framelessUnwind(addressSpace, savedRegisters+8*0, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*1; - registers.setRBX(addressSpace.get64(savedRegisters)); - framelessUnwind(addressSpace, savedRegisters+8*1, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_R12: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*2; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+8*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_RBP: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*2; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - framelessUnwind(addressSpace, savedRegisters+8*2, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_R12_R13: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*3; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - framelessUnwind(addressSpace, savedRegisters+8*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_R12_R13_R14: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*4; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - registers.setR14(addressSpace.get64(savedRegisters+24)); - framelessUnwind(addressSpace, savedRegisters+8*4, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_R12_R13_R14_R15: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*5; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setR12(addressSpace.get64(savedRegisters+8)); - registers.setR13(addressSpace.get64(savedRegisters+16)); - registers.setR14(addressSpace.get64(savedRegisters+24)); - registers.setR15(addressSpace.get64(savedRegisters+32)); - framelessUnwind(addressSpace, savedRegisters+8*5, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_RBP_R12_R13_R14_R15: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*6; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - registers.setR13(addressSpace.get64(savedRegisters+24)); - registers.setR14(addressSpace.get64(savedRegisters+32)); - registers.setR15(addressSpace.get64(savedRegisters+40)); - framelessUnwind(addressSpace, savedRegisters+8*6, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_RBP_R12: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*3; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - framelessUnwind(addressSpace, savedRegisters+8*3, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_RBP_R12_R13: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*4; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - registers.setR13(addressSpace.get64(savedRegisters+24)); - framelessUnwind(addressSpace, savedRegisters+8*4, registers); - return UNW_STEP_SUCCESS; - - case UNWIND_X86_64_IND_STK_RBX_RBP_R12_R13_R14: - stackSize = addressSpace.get32(functionStart+stackValue); - stackAdjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_STACK_ADJUST); - stackSize += stackAdjust*8; - savedRegisters = registers.getSP() + stackSize - 8 - 8*5; - registers.setRBX(addressSpace.get64(savedRegisters)); - registers.setRBP(addressSpace.get64(savedRegisters+8)); - registers.setR12(addressSpace.get64(savedRegisters+16)); - registers.setR13(addressSpace.get64(savedRegisters+24)); - registers.setR14(addressSpace.get64(savedRegisters+32)); - framelessUnwind(addressSpace, savedRegisters+8*5, registers); - return UNW_STEP_SUCCESS; - - default: - DEBUG_MESSAGE("unknown compact unwind encoding %08X for function starting at 0x%llX\n", - compactEncoding & UNWIND_X86_64_CASE_MASK, functionStart); - ABORT("unknown compact unwind encoding"); - } - return UNW_EINVAL; -} -#endif // SUPPORT_OLD_BINARIES - - -template <typename A> -void CompactUnwinder_x86_64<A>::frameUnwind(A& addressSpace, Registers_x86_64& registers) -{ - uint64_t rbp = registers.getRBP(); - // ebp points to old ebp - registers.setRBP(addressSpace.get64(rbp)); - // old esp is ebp less saved ebp and return address - registers.setSP(rbp+16); - // pop return address into eip - registers.setIP(addressSpace.get64(rbp+8)); -} - -template <typename A> -void CompactUnwinder_x86_64<A>::framelessUnwind(A& addressSpace, uint64_t returnAddressLocation, Registers_x86_64& registers) -{ - // return address is on stack after last saved register - registers.setIP(addressSpace.get64(returnAddressLocation)); - // old esp is before return address - registers.setSP(returnAddressLocation+8); -} - - -}; // namespace lldb_private - - - -#endif // __COMPACT_UNWINDER_HPP__ - - - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/DwarfInstructions.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/DwarfInstructions.hpp deleted file mode 100644 index 8b835b8cd29..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/DwarfInstructions.hpp +++ /dev/null @@ -1,1627 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- DwarfInstructions.hpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// -// processor specific parsing of dwarf unwind instructions -// - -#ifndef __DWARF_INSTRUCTIONS_HPP__ -#define __DWARF_INSTRUCTIONS_HPP__ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include <algorithm> -#include <vector> - -#include <libunwind.h> -#include <mach-o/compact_unwind_encoding.h> - -#include "dwarf2.h" -#include "AddressSpace.hpp" -#include "Registers.hpp" -#include "DwarfParser.hpp" -#include "InternalMacros.h" -//#include "CompactUnwinder.hpp" - -#define EXTRACT_BITS(value, mask) \ - ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) ) - -#define CFI_INVALID_ADDRESS ((pint_t)(-1)) - -namespace lldb_private { - -/// -/// Used by linker when parsing __eh_frame section -/// -template <typename A> -struct CFI_Reference { - typedef typename A::pint_t pint_t; - uint8_t encodingOfTargetAddress; - uint32_t offsetInCFI; - pint_t targetAddress; -}; -template <typename A> -struct CFI_Atom_Info { - typedef typename A::pint_t pint_t; - pint_t address; - uint32_t size; - bool isCIE; - union { - struct { - CFI_Reference<A> function; - CFI_Reference<A> cie; - CFI_Reference<A> lsda; - uint32_t compactUnwindInfo; - } fdeInfo; - struct { - CFI_Reference<A> personality; - } cieInfo; - } u; -}; - -typedef void (*WarnFunc)(void* ref, uint64_t funcAddr, const char* msg); - -/// -/// DwarfInstructions maps abtract dwarf unwind instructions to a particular architecture -/// -template <typename A, typename R> -class DwarfInstructions -{ -public: - typedef typename A::pint_t pint_t; - typedef typename A::sint_t sint_t; - - static const char* parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, - CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn); - - - static compact_unwind_encoding_t createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, - pint_t* lsda, pint_t* personality, - char warningBuffer[1024]); - - static int stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers); - -private: - - enum { - DW_X86_64_RET_ADDR = 16 - }; - - enum { - DW_X86_RET_ADDR = 8 - }; - - static pint_t evaluateExpression(pint_t expression, A& addressSpace, const R& registers, pint_t initialStackValue); - static pint_t getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, - const typename CFI_Parser<A>::RegisterLocation& savedReg); - static double getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, - const typename CFI_Parser<A>::RegisterLocation& savedReg); - static v128 getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, - const typename CFI_Parser<A>::RegisterLocation& savedReg); - - // x86 specific variants - static int lastRestoreReg(const Registers_x86&); - static bool isReturnAddressRegister(int regNum, const Registers_x86&); - static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86&); - - static uint32_t getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure); - static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86&); - static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, - const Registers_x86&, const typename CFI_Parser<A>::PrologInfo& prolog, - char warningBuffer[1024]); - - // x86_64 specific variants - static int lastRestoreReg(const Registers_x86_64&); - static bool isReturnAddressRegister(int regNum, const Registers_x86_64&); - static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86_64&); - - static uint32_t getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure); - static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86_64&); - static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, - const Registers_x86_64&, const typename CFI_Parser<A>::PrologInfo& prolog, - char warningBuffer[1024]); -}; - - - - -template <typename A, typename R> -const char* DwarfInstructions<A,R>::parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, - CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn) -{ - typename CFI_Parser<A>::CIE_Info cieInfo; - CFI_Atom_Info<A>* entry = infos; - CFI_Atom_Info<A>* end = &infos[infosCount]; - const pint_t ehSectionEnd = ehSectionStart + sectionLength; - for (pint_t p=ehSectionStart; p < ehSectionEnd; ) { - pint_t currentCFI = p; - uint64_t cfiLength = addressSpace.get32(p); - p += 4; - if ( cfiLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cfiLength = addressSpace.get64(p); - p += 8; - } - if ( cfiLength == 0 ) - return NULL; // end marker - if ( entry >= end ) - return "too little space allocated for parseCFIs"; - pint_t nextCFI = p + cfiLength; - uint32_t id = addressSpace.get32(p); - if ( id == 0 ) { - // is CIE - const char* err = CFI_Parser<A>::parseCIE(addressSpace, currentCFI, &cieInfo); - if ( err != NULL ) - return err; - entry->address = currentCFI; - entry->size = nextCFI - currentCFI; - entry->isCIE = true; - entry->u.cieInfo.personality.targetAddress = cieInfo.personality; - entry->u.cieInfo.personality.offsetInCFI = cieInfo.personalityOffsetInCIE; - entry->u.cieInfo.personality.encodingOfTargetAddress = cieInfo.personalityEncoding; - ++entry; - } - else { - // is FDE - entry->address = currentCFI; - entry->size = nextCFI - currentCFI; - entry->isCIE = false; - entry->u.fdeInfo.function.targetAddress = CFI_INVALID_ADDRESS; - entry->u.fdeInfo.cie.targetAddress = CFI_INVALID_ADDRESS; - entry->u.fdeInfo.lsda.targetAddress = CFI_INVALID_ADDRESS; - uint32_t ciePointer = addressSpace.get32(p); - pint_t cieStart = p-ciePointer; - // validate pointer to CIE is within section - if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) ) - return "FDE points to CIE outside __eh_frame section"; - // optimize usual case where cie is same for all FDEs - if ( cieStart != cieInfo.cieStart ) { - const char* err = CFI_Parser<A>::parseCIE(addressSpace, cieStart, &cieInfo); - if ( err != NULL ) - return err; - } - entry->u.fdeInfo.cie.targetAddress = cieStart; - entry->u.fdeInfo.cie.offsetInCFI = p-currentCFI; - entry->u.fdeInfo.cie.encodingOfTargetAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; - p += 4; - // parse pc begin and range - pint_t offsetOfFunctionAddress = p-currentCFI; - pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F); - //fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); - // test if pc is within the function this FDE covers - entry->u.fdeInfo.function.targetAddress = pcStart; - entry->u.fdeInfo.function.offsetInCFI = offsetOfFunctionAddress; - entry->u.fdeInfo.function.encodingOfTargetAddress = cieInfo.pointerEncoding; - // check for augmentation length - if ( cieInfo.fdesHaveAugmentationData ) { - uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if ( cieInfo.lsdaEncoding != 0 ) { - // peek at value (without indirection). Zero means no lsda - pint_t lsdaStart = p; - if ( addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding & 0x0F) != 0 ) { - // reset pointer and re-parse lsda address - p = lsdaStart; - pint_t offsetOfLSDAAddress = p-currentCFI; - entry->u.fdeInfo.lsda.targetAddress = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding); - entry->u.fdeInfo.lsda.offsetInCFI = offsetOfLSDAAddress; - entry->u.fdeInfo.lsda.encodingOfTargetAddress = cieInfo.lsdaEncoding; - } - } - p = endOfAug; - } - // compute compact unwind encoding - typename CFI_Parser<A>::FDE_Info fdeInfo; - fdeInfo.fdeStart = currentCFI; - fdeInfo.fdeLength = nextCFI - currentCFI; - fdeInfo.fdeInstructions = p; - fdeInfo.pcStart = pcStart; - fdeInfo.pcEnd = pcStart + pcRange; - fdeInfo.lsda = entry->u.fdeInfo.lsda.targetAddress; - typename CFI_Parser<A>::PrologInfo prolog; - R dummy; // for proper selection of architecture specific functions - if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) { - char warningBuffer[1024]; - entry->u.fdeInfo.compactUnwindInfo = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer); - if ( fdeInfo.lsda != CFI_INVALID_ADDRESS ) - entry->u.fdeInfo.compactUnwindInfo |= UNWIND_HAS_LSDA; - if ( warningBuffer[0] != '\0' ) - warn(ref, fdeInfo.pcStart, warningBuffer); - } - else { - warn(ref, CFI_INVALID_ADDRESS, "dwarf unwind instructions could not be parsed"); - entry->u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy); - } - ++entry; - } - p = nextCFI; - } - if ( entry != end ) - return "wrong entry count for parseCFIs"; - return NULL; // success -} - - - - -template <typename A, typename R> -compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, - pint_t* lsda, pint_t* personality, - char warningBuffer[1024]) -{ - typename CFI_Parser<A>::FDE_Info fdeInfo; - typename CFI_Parser<A>::CIE_Info cieInfo; - R dummy; // for proper selection of architecture specific functions - if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) { - typename CFI_Parser<A>::PrologInfo prolog; - if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) { - *lsda = fdeInfo.lsda; - *personality = cieInfo.personality; - compact_unwind_encoding_t encoding; - encoding = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer); - if ( fdeInfo.lsda != 0 ) - encoding |= UNWIND_HAS_LSDA; - return encoding; - } - else { - strcpy(warningBuffer, "dwarf unwind instructions could not be parsed"); - return encodeToUseDwarf(dummy); - } - } - else { - strcpy(warningBuffer, "dwarf FDE could not be parsed"); - return encodeToUseDwarf(dummy); - } -} - - -template <typename A, typename R> -typename A::pint_t DwarfInstructions<A,R>::getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, - const typename CFI_Parser<A>::RegisterLocation& savedReg) -{ - switch ( savedReg.location ) { - case CFI_Parser<A>::kRegisterInCFA: - return addressSpace.getP(cfa + savedReg.value); - - case CFI_Parser<A>::kRegisterAtExpression: - return addressSpace.getP(evaluateExpression(savedReg.value, addressSpace, registers, cfa)); - - case CFI_Parser<A>::kRegisterIsExpression: - return evaluateExpression(savedReg.value, addressSpace, registers, cfa); - - case CFI_Parser<A>::kRegisterInRegister: - return registers.getRegister(savedReg.value); - - case CFI_Parser<A>::kRegisterUnused: - case CFI_Parser<A>::kRegisterOffsetFromCFA: - // FIX ME - break; - } - ABORT("unsupported restore location for register"); -} - -template <typename A, typename R> -double DwarfInstructions<A,R>::getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, - const typename CFI_Parser<A>::RegisterLocation& savedReg) -{ - switch ( savedReg.location ) { - case CFI_Parser<A>::kRegisterInCFA: - return addressSpace.getDouble(cfa + savedReg.value); - - case CFI_Parser<A>::kRegisterAtExpression: - return addressSpace.getDouble(evaluateExpression(savedReg.value, addressSpace, registers, cfa)); - - case CFI_Parser<A>::kRegisterIsExpression: - case CFI_Parser<A>::kRegisterUnused: - case CFI_Parser<A>::kRegisterOffsetFromCFA: - case CFI_Parser<A>::kRegisterInRegister: - // FIX ME - break; - } - ABORT("unsupported restore location for float register"); -} - -template <typename A, typename R> -v128 DwarfInstructions<A,R>::getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, - const typename CFI_Parser<A>::RegisterLocation& savedReg) -{ - switch ( savedReg.location ) { - case CFI_Parser<A>::kRegisterInCFA: - return addressSpace.getVector(cfa + savedReg.value); - - case CFI_Parser<A>::kRegisterAtExpression: - return addressSpace.getVector(evaluateExpression(savedReg.value, addressSpace, registers, cfa)); - - case CFI_Parser<A>::kRegisterIsExpression: - case CFI_Parser<A>::kRegisterUnused: - case CFI_Parser<A>::kRegisterOffsetFromCFA: - case CFI_Parser<A>::kRegisterInRegister: - // FIX ME - break; - } - ABORT("unsupported restore location for vector register"); -} - - -template <typename A, typename R> -int DwarfInstructions<A,R>::stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers) -{ - //fprintf(stderr, "stepWithDwarf(pc=0x%0llX, fdeStart=0x%0llX)\n", (uint64_t)pc, (uint64_t)fdeStart); - typename CFI_Parser<A>::FDE_Info fdeInfo; - typename CFI_Parser<A>::CIE_Info cieInfo; - if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) { - typename CFI_Parser<A>::PrologInfo prolog; - if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog) ) { - R newRegisters = registers; - - // get pointer to cfa (architecture specific) - pint_t cfa = getCFA(addressSpace, prolog, registers); - - // restore registers that dwarf says were saved - pint_t returnAddress = 0; - for (int i=0; i <= lastRestoreReg(newRegisters); ++i) { - if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) { - if ( registers.validFloatRegister(i) ) - newRegisters.setFloatRegister(i, getSavedFloatRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); - else if ( registers.validVectorRegister(i) ) - newRegisters.setVectorRegister(i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); - else if ( isReturnAddressRegister(i, registers) ) - returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]); - else if ( registers.validRegister(i) ) - newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); - else - return UNW_EBADREG; - } - } - - // by definition the CFA is the stack pointer at the call site, so restoring SP means setting it to CFA - newRegisters.setSP(cfa); - - // return address is address after call site instruction, so setting IP to that does a return - newRegisters.setIP(returnAddress); - - // do the actual step by replacing the register set with the new ones - registers = newRegisters; - - return UNW_STEP_SUCCESS; - } - } - return UNW_EBADFRAME; -} - - - -template <typename A, typename R> -typename A::pint_t DwarfInstructions<A,R>::evaluateExpression(pint_t expression, A& addressSpace, - const R& registers, pint_t initialStackValue) -{ - const bool log = false; - pint_t p = expression; - pint_t expressionEnd = expression+20; // just need something until length is read - uint64_t length = addressSpace.getULEB128(p, expressionEnd); - expressionEnd = p + length; - if (log) fprintf(stderr, "evaluateExpression(): length=%llu\n", length); - pint_t stack[100]; - pint_t* sp = stack; - *(++sp) = initialStackValue; - - while ( p < expressionEnd ) { - if (log) { - for(pint_t* t = sp; t > stack; --t) { - fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t)); - } - } - uint8_t opcode = addressSpace.get8(p++); - sint_t svalue; - pint_t value; - uint32_t reg; - switch (opcode) { - case DW_OP_addr: - // push immediate address sized value - value = addressSpace.getP(p); - p += sizeof(pint_t); - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_deref: - // pop stack, dereference, push result - value = *sp--; - *(++sp) = addressSpace.getP(value); - if (log) fprintf(stderr, "dereference 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_const1u: - // push immediate 1 byte value - value = addressSpace.get8(p); - p += 1; - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_const1s: - // push immediate 1 byte signed value - svalue = (int8_t)addressSpace.get8(p); - p += 1; - *(++sp) = svalue; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); - break; - - case DW_OP_const2u: - // push immediate 2 byte value - value = addressSpace.get16(p); - p += 2; - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_const2s: - // push immediate 2 byte signed value - svalue = (int16_t)addressSpace.get16(p); - p += 2; - *(++sp) = svalue; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); - break; - - case DW_OP_const4u: - // push immediate 4 byte value - value = addressSpace.get32(p); - p += 4; - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_const4s: - // push immediate 4 byte signed value - svalue = (int32_t)addressSpace.get32(p); - p += 4; - *(++sp) = svalue; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); - break; - - case DW_OP_const8u: - // push immediate 8 byte value - value = addressSpace.get64(p); - p += 8; - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_const8s: - // push immediate 8 byte signed value - value = (int32_t)addressSpace.get64(p); - p += 8; - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_constu: - // push immediate ULEB128 value - value = addressSpace.getULEB128(p, expressionEnd); - *(++sp) = value; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_consts: - // push immediate SLEB128 value - svalue = addressSpace.getSLEB128(p, expressionEnd); - *(++sp) = svalue; - if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); - break; - - case DW_OP_dup: - // push top of stack - value = *sp; - *(++sp) = value; - if (log) fprintf(stderr, "duplicate top of stack\n"); - break; - - case DW_OP_drop: - // pop - --sp; - if (log) fprintf(stderr, "pop top of stack\n"); - break; - - case DW_OP_over: - // dup second - value = sp[-1]; - *(++sp) = value; - if (log) fprintf(stderr, "duplicate second in stack\n"); - break; - - case DW_OP_pick: - // pick from - reg = addressSpace.get8(p); - p += 1; - value = sp[-reg]; - *(++sp) = value; - if (log) fprintf(stderr, "duplicate %d in stack\n", reg); - break; - - case DW_OP_swap: - // swap top two - value = sp[0]; - sp[0] = sp[-1]; - sp[-1] = value; - if (log) fprintf(stderr, "swap top of stack\n"); - break; - - case DW_OP_rot: - // rotate top three - value = sp[0]; - sp[0] = sp[-1]; - sp[-1] = sp[-2]; - sp[-2] = value; - if (log) fprintf(stderr, "rotate top three of stack\n"); - break; - - case DW_OP_xderef: - // pop stack, dereference, push result - value = *sp--; - *sp = *((uint64_t*)value); - if (log) fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_abs: - svalue = *sp; - if ( svalue < 0 ) - *sp = -svalue; - if (log) fprintf(stderr, "abs\n"); - break; - - case DW_OP_and: - value = *sp--; - *sp &= value; - if (log) fprintf(stderr, "and\n"); - break; - - case DW_OP_div: - svalue = *sp--; - *sp = *sp / svalue; - if (log) fprintf(stderr, "div\n"); - break; - - case DW_OP_minus: - svalue = *sp--; - *sp = *sp - svalue; - if (log) fprintf(stderr, "minus\n"); - break; - - case DW_OP_mod: - svalue = *sp--; - *sp = *sp % svalue; - if (log) fprintf(stderr, "module\n"); - break; - - case DW_OP_mul: - svalue = *sp--; - *sp = *sp * svalue; - if (log) fprintf(stderr, "mul\n"); - break; - - case DW_OP_neg: - *sp = 0 - *sp; - if (log) fprintf(stderr, "neg\n"); - break; - - case DW_OP_not: - svalue = *sp; - *sp = ~svalue; - if (log) fprintf(stderr, "not\n"); - break; - - case DW_OP_or: - value = *sp--; - *sp |= value; - if (log) fprintf(stderr, "or\n"); - break; - - case DW_OP_plus: - value = *sp--; - *sp += value; - if (log) fprintf(stderr, "plus\n"); - break; - - case DW_OP_plus_uconst: - // pop stack, add uelb128 constant, push result - *sp += addressSpace.getULEB128(p, expressionEnd); - if (log) fprintf(stderr, "add constant\n"); - break; - - case DW_OP_shl: - value = *sp--; - *sp = *sp << value; - if (log) fprintf(stderr, "shift left\n"); - break; - - case DW_OP_shr: - value = *sp--; - *sp = *sp >> value; - if (log) fprintf(stderr, "shift left\n"); - break; - - case DW_OP_shra: - value = *sp--; - svalue = *sp; - *sp = svalue >> value; - if (log) fprintf(stderr, "shift left arithmetric\n"); - break; - - case DW_OP_xor: - value = *sp--; - *sp ^= value; - if (log) fprintf(stderr, "xor\n"); - break; - - case DW_OP_skip: - svalue = (int16_t)addressSpace.get16(p); - p += 2; - p += svalue; - if (log) fprintf(stderr, "skip %lld\n", (uint64_t)svalue); - break; - - case DW_OP_bra: - svalue = (int16_t)addressSpace.get16(p); - p += 2; - if ( *sp-- ) - p += svalue; - if (log) fprintf(stderr, "bra %lld\n", (uint64_t)svalue); - break; - - case DW_OP_eq: - value = *sp--; - *sp = (*sp == value); - if (log) fprintf(stderr, "eq\n"); - break; - - case DW_OP_ge: - value = *sp--; - *sp = (*sp >= value); - if (log) fprintf(stderr, "ge\n"); - break; - - case DW_OP_gt: - value = *sp--; - *sp = (*sp > value); - if (log) fprintf(stderr, "gt\n"); - break; - - case DW_OP_le: - value = *sp--; - *sp = (*sp <= value); - if (log) fprintf(stderr, "le\n"); - break; - - case DW_OP_lt: - value = *sp--; - *sp = (*sp < value); - if (log) fprintf(stderr, "lt\n"); - break; - - case DW_OP_ne: - value = *sp--; - *sp = (*sp != value); - if (log) fprintf(stderr, "ne\n"); - break; - - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - value = opcode - DW_OP_lit0; - *(++sp) = value; - if (log) fprintf(stderr, "push literal 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - reg = opcode - DW_OP_reg0; - *(++sp) = registers.getRegister(reg); - if (log) fprintf(stderr, "push reg %d\n", reg); - break; - - case DW_OP_regx: - reg = addressSpace.getULEB128(p, expressionEnd); - *(++sp) = registers.getRegister(reg); - if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue); - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - reg = opcode - DW_OP_breg0; - svalue = addressSpace.getSLEB128(p, expressionEnd); - *(++sp) = registers.getRegister(reg) + svalue; - if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue); - break; - - case DW_OP_bregx: - reg = addressSpace.getULEB128(p, expressionEnd); - svalue = addressSpace.getSLEB128(p, expressionEnd); - *(++sp) = registers.getRegister(reg) + svalue; - if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue); - break; - - case DW_OP_fbreg: - ABORT("DW_OP_fbreg not implemented"); - break; - - case DW_OP_piece: - ABORT("DW_OP_piece not implemented"); - break; - - case DW_OP_deref_size: - // pop stack, dereference, push result - value = *sp--; - switch ( addressSpace.get8(p++) ) { - case 1: - value = addressSpace.get8(value); - break; - case 2: - value = addressSpace.get16(value); - break; - case 4: - value = addressSpace.get32(value); - break; - case 8: - value = addressSpace.get64(value); - break; - default: - ABORT("DW_OP_deref_size with bad size"); - } - *(++sp) = value; - if (log) fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t)value); - break; - - case DW_OP_xderef_size: - case DW_OP_nop: - case DW_OP_push_object_addres: - case DW_OP_call2: - case DW_OP_call4: - case DW_OP_call_ref: - default: - ABORT("dwarf opcode not implemented"); - } - - } - if (log) fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t)*sp); - return *sp; -} - - - -// -// x86_64 specific functions -// - -template <typename A, typename R> -int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86_64&) -{ - COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_64_RET_ADDR ); - return DW_X86_64_RET_ADDR; -} - -template <typename A, typename R> -bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86_64&) -{ - return (regNum == DW_X86_64_RET_ADDR); -} - -template <typename A, typename R> -typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, - const Registers_x86_64& registers) -{ - if ( prolog.cfaRegister != 0 ) - return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset; - else if ( prolog.cfaExpression != 0 ) - return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0); - else - ABORT("getCFA(): unknown location for x86_64 cfa"); -} - - - -template <typename A, typename R> -compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86_64&) -{ - return UNWIND_X86_64_MODE_DWARF; -} - -template <typename A, typename R> -compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86&) -{ - return UNWIND_X86_MODE_DWARF; -} - - - -template <typename A, typename R> -uint32_t DwarfInstructions<A,R>::getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure) -{ - if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 32) ) { - failure = true; - return 0; - } - unsigned int slotIndex = regOffsetFromBaseOffset/8; - - switch ( reg ) { - case UNW_X86_64_RBX: - return UNWIND_X86_64_REG_RBX << (slotIndex*3); - case UNW_X86_64_R12: - return UNWIND_X86_64_REG_R12 << (slotIndex*3); - case UNW_X86_64_R13: - return UNWIND_X86_64_REG_R13 << (slotIndex*3); - case UNW_X86_64_R14: - return UNWIND_X86_64_REG_R14 << (slotIndex*3); - case UNW_X86_64_R15: - return UNWIND_X86_64_REG_R15 << (slotIndex*3); - } - - // invalid register - failure = true; - return 0; -} - - - -template <typename A, typename R> -compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, - const Registers_x86_64& r, const typename CFI_Parser<A>::PrologInfo& prolog, - char warningBuffer[1024]) -{ - warningBuffer[0] = '\0'; - - // don't create compact unwind info for unsupported dwarf kinds - if ( prolog.registerSavedMoreThanOnce ) { - strcpy(warningBuffer, "register saved more than once (might be shrink wrap)"); - return UNWIND_X86_64_MODE_DWARF; - } - if ( prolog.cfaOffsetWasNegative ) { - strcpy(warningBuffer, "cfa had negative offset (dwarf might contain epilog)"); - return UNWIND_X86_64_MODE_DWARF; - } - if ( prolog.spExtraArgSize != 0 ) { - strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size"); - return UNWIND_X86_64_MODE_DWARF; - } - - // figure out which kind of frame this function uses - bool standardRBPframe = ( - (prolog.cfaRegister == UNW_X86_64_RBP) - && (prolog.cfaRegisterOffset == 16) - && (prolog.savedRegisters[UNW_X86_64_RBP].location == CFI_Parser<A>::kRegisterInCFA) - && (prolog.savedRegisters[UNW_X86_64_RBP].value == -16) ); - bool standardRSPframe = (prolog.cfaRegister == UNW_X86_64_RSP); - if ( !standardRBPframe && !standardRSPframe ) { - // no compact encoding for this - strcpy(warningBuffer, "does not use RBP or RSP based frame"); - return UNWIND_X86_64_MODE_DWARF; - } - - // scan which registers are saved - int saveRegisterCount = 0; - bool rbxSaved = false; - bool r12Saved = false; - bool r13Saved = false; - bool r14Saved = false; - bool r15Saved = false; - bool rbpSaved = false; - for (int i=0; i < 64; ++i) { - if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) { - if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) { - sprintf(warningBuffer, "register %d saved somewhere other that in frame", i); - return UNWIND_X86_64_MODE_DWARF; - } - switch (i) { - case UNW_X86_64_RBX: - rbxSaved = true; - ++saveRegisterCount; - break; - case UNW_X86_64_R12: - r12Saved = true; - ++saveRegisterCount; - break; - case UNW_X86_64_R13: - r13Saved = true; - ++saveRegisterCount; - break; - case UNW_X86_64_R14: - r14Saved = true; - ++saveRegisterCount; - break; - case UNW_X86_64_R15: - r15Saved = true; - ++saveRegisterCount; - break; - case UNW_X86_64_RBP: - rbpSaved = true; - ++saveRegisterCount; - break; - case DW_X86_64_RET_ADDR: - break; - default: - sprintf(warningBuffer, "non-standard register %d being saved in prolog", i); - return UNWIND_X86_64_MODE_DWARF; - } - } - } - const int64_t cfaOffsetRBX = prolog.savedRegisters[UNW_X86_64_RBX].value; - const int64_t cfaOffsetR12 = prolog.savedRegisters[UNW_X86_64_R12].value; - const int64_t cfaOffsetR13 = prolog.savedRegisters[UNW_X86_64_R13].value; - const int64_t cfaOffsetR14 = prolog.savedRegisters[UNW_X86_64_R14].value; - const int64_t cfaOffsetR15 = prolog.savedRegisters[UNW_X86_64_R15].value; - const int64_t cfaOffsetRBP = prolog.savedRegisters[UNW_X86_64_RBP].value; - - // encode standard RBP frames - compact_unwind_encoding_t encoding = 0; - if ( standardRBPframe ) { - // | | - // +--------------+ <- CFA - // | ret addr | - // +--------------+ - // | rbp | - // +--------------+ <- rbp - // ~ ~ - // +--------------+ - // | saved reg3 | - // +--------------+ <- CFA - offset+16 - // | saved reg2 | - // +--------------+ <- CFA - offset+8 - // | saved reg1 | - // +--------------+ <- CFA - offset - // | | - // +--------------+ - // | | - // <- rsp - // - encoding = UNWIND_X86_64_MODE_RBP_FRAME; - - // find save location of farthest register from rbp - int furthestCfaOffset = 0; - if ( rbxSaved & (cfaOffsetRBX < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetRBX; - if ( r12Saved & (cfaOffsetR12 < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetR12; - if ( r13Saved & (cfaOffsetR13 < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetR13; - if ( r14Saved & (cfaOffsetR14 < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetR14; - if ( r15Saved & (cfaOffsetR15 < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetR15; - - if ( furthestCfaOffset == 0 ) { - // no registers saved, nothing more to encode - return encoding; - } - - // add stack offset to encoding - int rbpOffset = furthestCfaOffset + 16; - int encodedOffset = rbpOffset/(-8); - if ( encodedOffset > 255 ) { - strcpy(warningBuffer, "offset of saved registers too far to encode"); - return UNWIND_X86_64_MODE_DWARF; - } - encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_64_RBP_FRAME_OFFSET)); - - // add register saved from each stack location - bool encodingFailure = false; - if ( rbxSaved ) - encoding |= getRBPEncodedRegister(UNW_X86_64_RBX, cfaOffsetRBX - furthestCfaOffset, encodingFailure); - if ( r12Saved ) - encoding |= getRBPEncodedRegister(UNW_X86_64_R12, cfaOffsetR12 - furthestCfaOffset, encodingFailure); - if ( r13Saved ) - encoding |= getRBPEncodedRegister(UNW_X86_64_R13, cfaOffsetR13 - furthestCfaOffset, encodingFailure); - if ( r14Saved ) - encoding |= getRBPEncodedRegister(UNW_X86_64_R14, cfaOffsetR14 - furthestCfaOffset, encodingFailure); - if ( r15Saved ) - encoding |= getRBPEncodedRegister(UNW_X86_64_R15, cfaOffsetR15 - furthestCfaOffset, encodingFailure); - - if ( encodingFailure ){ - strcpy(warningBuffer, "saved registers not contiguous"); - return UNWIND_X86_64_MODE_DWARF; - } - - return encoding; - } - else { - // | | - // +--------------+ <- CFA - // | ret addr | - // +--------------+ - // | saved reg1 | - // +--------------+ <- CFA - 16 - // | saved reg2 | - // +--------------+ <- CFA - 24 - // | saved reg3 | - // +--------------+ <- CFA - 32 - // | saved reg4 | - // +--------------+ <- CFA - 40 - // | saved reg5 | - // +--------------+ <- CFA - 48 - // | saved reg6 | - // +--------------+ <- CFA - 56 - // | | - // <- esp - // - - // for RSP based frames we need to encode stack size in unwind info - encoding = UNWIND_X86_64_MODE_STACK_IMMD; - uint64_t stackValue = prolog.cfaRegisterOffset / 8; - uint32_t stackAdjust = 0; - bool immedStackSize = true; - const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_64_FRAMELESS_STACK_SIZE); - if ( stackValue > stackMaxImmedValue ) { - // stack size is too big to fit as an immediate value, so encode offset of subq instruction in function - pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4; - uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns); - stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/8; - stackValue = functionContentAdjustStackIns - funcAddr; - immedStackSize = false; - if ( stackAdjust > 7 ) { - strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size"); - return UNWIND_X86_64_MODE_DWARF; - } - encoding = UNWIND_X86_64_MODE_STACK_IND; - } - - - // validate that saved registers are all within 6 slots abutting return address - int registers[6]; - for (int i=0; i < 6;++i) - registers[i] = 0; - if ( r15Saved ) { - if ( cfaOffsetR15 < -56 ) { - strcpy(warningBuffer, "r15 is saved too far from return address"); - return UNWIND_X86_64_MODE_DWARF; - } - registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15; - } - if ( r14Saved ) { - if ( cfaOffsetR14 < -56 ) { - strcpy(warningBuffer, "r14 is saved too far from return address"); - return UNWIND_X86_64_MODE_DWARF; - } - registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14; - } - if ( r13Saved ) { - if ( cfaOffsetR13 < -56 ) { - strcpy(warningBuffer, "r13 is saved too far from return address"); - return UNWIND_X86_64_MODE_DWARF; - } - registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13; - } - if ( r12Saved ) { - if ( cfaOffsetR12 < -56 ) { - strcpy(warningBuffer, "r12 is saved too far from return address"); - return UNWIND_X86_64_MODE_DWARF; - } - registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12; - } - if ( rbxSaved ) { - if ( cfaOffsetRBX < -56 ) { - strcpy(warningBuffer, "rbx is saved too far from return address"); - return UNWIND_X86_64_MODE_DWARF; - } - registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX; - } - if ( rbpSaved ) { - if ( cfaOffsetRBP < -56 ) { - strcpy(warningBuffer, "rbp is saved too far from return address"); - return UNWIND_X86_64_MODE_DWARF; - } - registers[(cfaOffsetRBP+56)/8] = UNWIND_X86_64_REG_RBP; - } - - // validate that saved registers are contiguous and abut return address on stack - for (int i=0; i < saveRegisterCount; ++i) { - if ( registers[5-i] == 0 ) { - strcpy(warningBuffer, "registers not save contiguously in stack"); - return UNWIND_X86_64_MODE_DWARF; - } - } - - // encode register permutation - // the 10-bits are encoded differently depending on the number of registers saved - int renumregs[6]; - for (int i=6-saveRegisterCount; i < 6; ++i) { - int countless = 0; - for (int j=6-saveRegisterCount; j < i; ++j) { - if ( registers[j] < registers[i] ) - ++countless; - } - renumregs[i] = registers[i] - countless -1; - } - uint32_t permutationEncoding = 0; - switch ( saveRegisterCount ) { - case 6: - permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]); - break; - case 5: - permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]); - break; - case 4: - permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]); - break; - case 3: - permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]); - break; - case 2: - permutationEncoding |= (5*renumregs[4] + renumregs[5]); - break; - case 1: - permutationEncoding |= (renumregs[5]); - break; - } - - encoding |= (stackValue << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE)); - encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST)); - encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT)); - encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION)); - return encoding; - } -} - - - - -// -// x86 specific functions -// -template <typename A, typename R> -int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86&) -{ - COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_RET_ADDR ); - return DW_X86_RET_ADDR; -} - -template <typename A, typename R> -bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86&) -{ - return (regNum == DW_X86_RET_ADDR); -} - -template <typename A, typename R> -typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, - const Registers_x86& registers) -{ - if ( prolog.cfaRegister != 0 ) - return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset; - else if ( prolog.cfaExpression != 0 ) - return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0); - else - ABORT("getCFA(): unknown location for x86 cfa"); -} - - - - - -template <typename A, typename R> -uint32_t DwarfInstructions<A,R>::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure) -{ - if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 16) ) { - failure = true; - return 0; - } - unsigned int slotIndex = regOffsetFromBaseOffset/4; - - switch ( reg ) { - case UNW_X86_EBX: - return UNWIND_X86_REG_EBX << (slotIndex*3); - case UNW_X86_ECX: - return UNWIND_X86_REG_ECX << (slotIndex*3); - case UNW_X86_EDX: - return UNWIND_X86_REG_EDX << (slotIndex*3); - case UNW_X86_EDI: - return UNWIND_X86_REG_EDI << (slotIndex*3); - case UNW_X86_ESI: - return UNWIND_X86_REG_ESI << (slotIndex*3); - } - - // invalid register - failure = true; - return 0; -} - -template <typename A, typename R> -compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, - const Registers_x86& r, const typename CFI_Parser<A>::PrologInfo& prolog, - char warningBuffer[1024]) -{ - warningBuffer[0] = '\0'; - - // don't create compact unwind info for unsupported dwarf kinds - if ( prolog.registerSavedMoreThanOnce ) { - strcpy(warningBuffer, "register saved more than once (might be shrink wrap)"); - return UNWIND_X86_MODE_DWARF; - } - if ( prolog.spExtraArgSize != 0 ) { - strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size"); - return UNWIND_X86_MODE_DWARF; - } - - // figure out which kind of frame this function uses - bool standardEBPframe = ( - (prolog.cfaRegister == UNW_X86_EBP) - && (prolog.cfaRegisterOffset == 8) - && (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser<A>::kRegisterInCFA) - && (prolog.savedRegisters[UNW_X86_EBP].value == -8) ); - bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP); - if ( !standardEBPframe && !standardESPframe ) { - // no compact encoding for this - strcpy(warningBuffer, "does not use EBP or ESP based frame"); - return UNWIND_X86_MODE_DWARF; - } - - // scan which registers are saved - int saveRegisterCount = 0; - bool ebxSaved = false; - bool ecxSaved = false; - bool edxSaved = false; - bool esiSaved = false; - bool ediSaved = false; - bool ebpSaved = false; - for (int i=0; i < 64; ++i) { - if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) { - if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) { - sprintf(warningBuffer, "register %d saved somewhere other that in frame", i); - return UNWIND_X86_MODE_DWARF; - } - switch (i) { - case UNW_X86_EBX: - ebxSaved = true; - ++saveRegisterCount; - break; - case UNW_X86_ECX: - ecxSaved = true; - ++saveRegisterCount; - break; - case UNW_X86_EDX: - edxSaved = true; - ++saveRegisterCount; - break; - case UNW_X86_ESI: - esiSaved = true; - ++saveRegisterCount; - break; - case UNW_X86_EDI: - ediSaved = true; - ++saveRegisterCount; - break; - case UNW_X86_EBP: - ebpSaved = true; - ++saveRegisterCount; - break; - case DW_X86_RET_ADDR: - break; - default: - sprintf(warningBuffer, "non-standard register %d being saved in prolog", i); - return UNWIND_X86_MODE_DWARF; - } - } - } - const int32_t cfaOffsetEBX = prolog.savedRegisters[UNW_X86_EBX].value; - const int32_t cfaOffsetECX = prolog.savedRegisters[UNW_X86_ECX].value; - const int32_t cfaOffsetEDX = prolog.savedRegisters[UNW_X86_EDX].value; - const int32_t cfaOffsetEDI = prolog.savedRegisters[UNW_X86_EDI].value; - const int32_t cfaOffsetESI = prolog.savedRegisters[UNW_X86_ESI].value; - const int32_t cfaOffsetEBP = prolog.savedRegisters[UNW_X86_EBP].value; - - // encode standard RBP frames - compact_unwind_encoding_t encoding = 0; - if ( standardEBPframe ) { - // | | - // +--------------+ <- CFA - // | ret addr | - // +--------------+ - // | ebp | - // +--------------+ <- ebp - // ~ ~ - // +--------------+ - // | saved reg3 | - // +--------------+ <- CFA - offset+8 - // | saved reg2 | - // +--------------+ <- CFA - offset+e - // | saved reg1 | - // +--------------+ <- CFA - offset - // | | - // +--------------+ - // | | - // <- esp - // - encoding = UNWIND_X86_MODE_EBP_FRAME; - - // find save location of farthest register from ebp - int furthestCfaOffset = 0; - if ( ebxSaved & (cfaOffsetEBX < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetEBX; - if ( ecxSaved & (cfaOffsetECX < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetECX; - if ( edxSaved & (cfaOffsetEDX < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetEDX; - if ( ediSaved & (cfaOffsetEDI < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetEDI; - if ( esiSaved & (cfaOffsetESI < furthestCfaOffset) ) - furthestCfaOffset = cfaOffsetESI; - - if ( furthestCfaOffset == 0 ) { - // no registers saved, nothing more to encode - return encoding; - } - - // add stack offset to encoding - int ebpOffset = furthestCfaOffset + 8; - int encodedOffset = ebpOffset/(-4); - if ( encodedOffset > 255 ) { - strcpy(warningBuffer, "offset of saved registers too far to encode"); - return UNWIND_X86_MODE_DWARF; - } - encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_EBP_FRAME_OFFSET)); - - // add register saved from each stack location - bool encodingFailure = false; - if ( ebxSaved ) - encoding |= getEBPEncodedRegister(UNW_X86_EBX, cfaOffsetEBX - furthestCfaOffset, encodingFailure); - if ( ecxSaved ) - encoding |= getEBPEncodedRegister(UNW_X86_ECX, cfaOffsetECX - furthestCfaOffset, encodingFailure); - if ( edxSaved ) - encoding |= getEBPEncodedRegister(UNW_X86_EDX, cfaOffsetEDX - furthestCfaOffset, encodingFailure); - if ( ediSaved ) - encoding |= getEBPEncodedRegister(UNW_X86_EDI, cfaOffsetEDI - furthestCfaOffset, encodingFailure); - if ( esiSaved ) - encoding |= getEBPEncodedRegister(UNW_X86_ESI, cfaOffsetESI - furthestCfaOffset, encodingFailure); - - if ( encodingFailure ){ - strcpy(warningBuffer, "saved registers not contiguous"); - return UNWIND_X86_MODE_DWARF; - } - - return encoding; - } - else { - // | | - // +--------------+ <- CFA - // | ret addr | - // +--------------+ - // | saved reg1 | - // +--------------+ <- CFA - 8 - // | saved reg2 | - // +--------------+ <- CFA - 12 - // | saved reg3 | - // +--------------+ <- CFA - 16 - // | saved reg4 | - // +--------------+ <- CFA - 20 - // | saved reg5 | - // +--------------+ <- CFA - 24 - // | saved reg6 | - // +--------------+ <- CFA - 28 - // | | - // <- esp - // - - // for ESP based frames we need to encode stack size in unwind info - encoding = UNWIND_X86_MODE_STACK_IMMD; - uint64_t stackValue = prolog.cfaRegisterOffset / 4; - uint32_t stackAdjust = 0; - bool immedStackSize = true; - const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_FRAMELESS_STACK_SIZE); - if ( stackValue > stackMaxImmedValue ) { - // stack size is too big to fit as an immediate value, so encode offset of subq instruction in function - pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4; - uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns); - stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/4; - stackValue = functionContentAdjustStackIns - funcAddr; - immedStackSize = false; - if ( stackAdjust > 7 ) { - strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size"); - return UNWIND_X86_MODE_DWARF; - } - encoding = UNWIND_X86_MODE_STACK_IND; - } - - - // validate that saved registers are all within 6 slots abutting return address - int registers[6]; - for (int i=0; i < 6;++i) - registers[i] = 0; - if ( ebxSaved ) { - if ( cfaOffsetEBX < -28 ) { - strcpy(warningBuffer, "ebx is saved too far from return address"); - return UNWIND_X86_MODE_DWARF; - } - registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX; - } - if ( ecxSaved ) { - if ( cfaOffsetECX < -28 ) { - strcpy(warningBuffer, "ecx is saved too far from return address"); - return UNWIND_X86_MODE_DWARF; - } - registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX; - } - if ( edxSaved ) { - if ( cfaOffsetEDX < -28 ) { - strcpy(warningBuffer, "edx is saved too far from return address"); - return UNWIND_X86_MODE_DWARF; - } - registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX; - } - if ( ediSaved ) { - if ( cfaOffsetEDI < -28 ) { - strcpy(warningBuffer, "edi is saved too far from return address"); - return UNWIND_X86_MODE_DWARF; - } - registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI; - } - if ( esiSaved ) { - if ( cfaOffsetESI < -28 ) { - strcpy(warningBuffer, "esi is saved too far from return address"); - return UNWIND_X86_MODE_DWARF; - } - registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI; - } - if ( ebpSaved ) { - if ( cfaOffsetEBP < -28 ) { - strcpy(warningBuffer, "ebp is saved too far from return address"); - return UNWIND_X86_MODE_DWARF; - } - registers[(cfaOffsetEBP+28)/4] = UNWIND_X86_REG_EBP; - } - - // validate that saved registers are contiguous and abut return address on stack - for (int i=0; i < saveRegisterCount; ++i) { - if ( registers[5-i] == 0 ) { - strcpy(warningBuffer, "registers not save contiguously in stack"); - return UNWIND_X86_MODE_DWARF; - } - } - - // encode register permutation - // the 10-bits are encoded differently depending on the number of registers saved - int renumregs[6]; - for (int i=6-saveRegisterCount; i < 6; ++i) { - int countless = 0; - for (int j=6-saveRegisterCount; j < i; ++j) { - if ( registers[j] < registers[i] ) - ++countless; - } - renumregs[i] = registers[i] - countless -1; - } - uint32_t permutationEncoding = 0; - switch ( saveRegisterCount ) { - case 6: - permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]); - break; - case 5: - permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]); - break; - case 4: - permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]); - break; - case 3: - permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]); - break; - case 2: - permutationEncoding |= (5*renumregs[4] + renumregs[5]); - break; - case 1: - permutationEncoding |= (renumregs[5]); - break; - } - - encoding |= (stackValue << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE)); - encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST)); - encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT)); - encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION)); - return encoding; - } -} - - - - - -} // namespace lldb_private - - -#endif // __DWARF_INSTRUCTIONS_HPP__ - - - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/DwarfParser.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/DwarfParser.hpp deleted file mode 100644 index df6db3047b8..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/DwarfParser.hpp +++ /dev/null @@ -1,869 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- DwarfParser.hpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// -// processor specific parsing of dwarf unwind instructions -// - -#ifndef __DWARF_PARSER_HPP__ -#define __DWARF_PARSER_HPP__ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include <vector> - -#include "libunwind.h" -#include "dwarf2.h" - -#include "AddressSpace.hpp" -#include "RemoteUnwindProfile.h" - -namespace lldb_private { - - -/// -/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. -/// See Dwarf Spec for details: -/// http://www.linux-foundation.org/spec/booksets/LSB-Core-generic/LSB-Core-generic/ehframechpt.html -/// -template <typename A> -class CFI_Parser -{ -public: - typedef typename A::pint_t pint_t; - - /// - /// Information encoded in a CIE (Common Information Entry) - /// - struct CIE_Info { - pint_t cieStart; - pint_t cieLength; - pint_t cieInstructions; - uint8_t pointerEncoding; - uint8_t lsdaEncoding; - uint8_t personalityEncoding; - uint8_t personalityOffsetInCIE; - pint_t personality; - int codeAlignFactor; - int dataAlignFactor; - bool isSignalFrame; - bool fdesHaveAugmentationData; - }; - - /// - /// Information about an FDE (Frame Description Entry) - /// - struct FDE_Info { - pint_t fdeStart; - pint_t fdeLength; - pint_t fdeInstructions; - pint_t pcStart; - pint_t pcEnd; - pint_t lsda; - }; - - /// - /// Used by linker when parsing __eh_frame section - /// - struct FDE_Reference { - pint_t address; - uint32_t offsetInFDE; - uint8_t encodingOfAddress; - }; - struct FDE_Atom_Info { - pint_t fdeAddress; - FDE_Reference function; - FDE_Reference cie; - FDE_Reference lsda; - }; - struct CIE_Atom_Info { - pint_t cieAddress; - FDE_Reference personality; - }; - - - /// - /// Information about a frame layout and registers saved determined - /// by "running" the dwarf FDE "instructions" - /// - enum { kMaxRegisterNumber = 120 }; - enum RegisterSavedWhere { kRegisterUnused, kRegisterInCFA, kRegisterOffsetFromCFA, - kRegisterInRegister, kRegisterAtExpression, kRegisterIsExpression } ; - struct RegisterLocation { - RegisterSavedWhere location; - int64_t value; - }; - struct PrologInfo { - uint32_t cfaRegister; - int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset - int64_t cfaExpression; // CFA = expression - bool registersInOtherRegisters; - bool registerSavedMoreThanOnce; - bool cfaOffsetWasNegative; - uint32_t spExtraArgSize; - uint32_t codeOffsetAtStackDecrement; - - RegisterLocation savedRegisters[kMaxRegisterNumber]; // from where to restore registers - }; - - struct PrologInfoStackEntry { - PrologInfoStackEntry(PrologInfoStackEntry* n, const PrologInfo& i) - : next(n), info(i) {} - PrologInfoStackEntry* next; - PrologInfo info; - }; - - static bool findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo); - -#if defined (SUPPORT_REMOTE_UNWINDING) - static bool functionFuncBoundsViaFDE(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, std::vector<FuncBounds> &funcbounds); -#endif - - static const char* decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo); - static bool parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results); - static const char* getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, - std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies); - static uint32_t getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength); - - static const char* parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo); - -private: - static bool parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo, - pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results); - -}; - - -/// -/// Parse a FDE into a CIE_Info and an FDE_Info -/// -template <typename A> -const char* CFI_Parser<A>::decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo) -{ - pint_t p = fdeStart; - uint64_t cfiLength = addressSpace.get32(p); - p += 4; - if ( cfiLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cfiLength = addressSpace.get64(p); - p += 8; - } - if ( cfiLength == 0 ) - return "FDE has zero length"; // end marker - uint32_t ciePointer = addressSpace.get32(p); - if ( ciePointer == 0 ) - return "FDE is really a CIE"; // this is a CIE not an FDE - pint_t nextCFI = p + cfiLength; - pint_t cieStart = p-ciePointer; - const char* err = parseCIE(addressSpace, cieStart, cieInfo); - if (err != NULL) - return err; - p += 4; - // parse pc begin and range - pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // parse rest of info - fdeInfo->lsda = 0; - // check for augmentation length - if ( cieInfo->fdesHaveAugmentationData ) { - uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if ( cieInfo->lsdaEncoding != 0 ) { - // peek at value (without indirection). Zero means no lsda - pint_t lsdaStart = p; - if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) { - // reset pointer and re-parse lsda address - p = lsdaStart; - fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = fdeStart; - fdeInfo->fdeLength = nextCFI - fdeStart; - fdeInfo->fdeInstructions = p; - fdeInfo->pcStart = pcStart; - fdeInfo->pcEnd = pcStart+pcRange; - return NULL; // success -} - - -/// -/// Scan an eh_frame section to find an FDE for a pc -/// -template <typename A> -bool CFI_Parser<A>::findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo) -{ - //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); - pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; - const pint_t ehSectionEnd = p + sectionLength; - while ( p < ehSectionEnd ) { - pint_t currentCFI = p; - //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); - uint64_t cfiLength = addressSpace.get32(p); - p += 4; - if ( cfiLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cfiLength = addressSpace.get64(p); - p += 8; - } - if ( cfiLength == 0 ) - return false; // end marker - uint32_t id = addressSpace.get32(p); - if ( id == 0 ) { - // skip over CIEs - p += cfiLength; - } - else { - // process FDE to see if it covers pc - pint_t nextCFI = p + cfiLength; - uint32_t ciePointer = addressSpace.get32(p); - pint_t cieStart = p-ciePointer; - // validate pointer to CIE is within section - if ( (ehSectionStart <= cieStart) && (cieStart < ehSectionEnd) ) { - if ( parseCIE(addressSpace, cieStart, cieInfo) == NULL ) { - p += 4; - // parse pc begin and range - pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); - //fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); - // test if pc is within the function this FDE covers - if ( (pcStart < pc) && (pc <= pcStart+pcRange) ) { - // parse rest of info - fdeInfo->lsda = 0; - // check for augmentation length - if ( cieInfo->fdesHaveAugmentationData ) { - uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if ( cieInfo->lsdaEncoding != 0 ) { - // peek at value (without indirection). Zero means no lsda - pint_t lsdaStart = p; - if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) { - // reset pointer and re-parse lsda address - p = lsdaStart; - fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = currentCFI; - fdeInfo->fdeLength = nextCFI - currentCFI; - fdeInfo->fdeInstructions = p; - fdeInfo->pcStart = pcStart; - fdeInfo->pcEnd = pcStart+pcRange; - //fprintf(stderr, "findFDE(pc=0x%llX) found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); - return true; - } - else { - //fprintf(stderr, "findFDE(pc=0x%llX) not found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); - // pc is not in begin/range, skip this FDE - } - } - else { - // malformed CIE, now augmentation describing pc range encoding - //fprintf(stderr, "malformed CIE\n"); - } - } - else { - // malformed FDE. CIE is bad - //fprintf(stderr, "malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n", - // (uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd); - } - p = nextCFI; - } - } - //fprintf(stderr, "findFDE(pc=0x%llX) not found\n",(uint64_t)pc); - return false; -} - -#if defined (SUPPORT_REMOTE_UNWINDING) -/// Scan an eh_frame section to find all the function start addresses -/// This is only made for working with libunwind-remote. It copies -/// the eh_frame section into local memory and steps through it quickly -/// to find the start addresses of the CFIs. -/// -template <typename A> -bool CFI_Parser<A>::functionFuncBoundsViaFDE(A& addressSpace, pint_t ehSectionStart, - uint32_t sectionLength, std::vector<FuncBounds> &funcbounds) -{ - //fprintf(stderr, "functionFuncBoundsViaFDE(0x%llX)\n", (long long)pc); - pint_t p = ehSectionStart; - const pint_t ehSectionEnd = p + sectionLength; - pint_t lastCieSeen = (pint_t) -1; - CIE_Info cieInfo; - while ( p < ehSectionEnd ) { - //fprintf(stderr, "functionFuncBoundsViaFDE() CFI at 0x%llX\n", (long long)p); - uint64_t cfiLength = addressSpace.get32(p); - p += 4; - if ( cfiLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cfiLength = addressSpace.get64(p); - p += 8; - } - if ( cfiLength == 0 ) - return false; // end marker - uint32_t id = addressSpace.get32(p); - if ( id == 0 ) { - // skip over CIEs - p += cfiLength; - } - else { - // process FDE to see if it covers pc - pint_t nextCFI = p + cfiLength; - uint32_t ciePointer = addressSpace.get32(p); - pint_t cieStart = p-ciePointer; - // validate pointer to CIE is within section - if ( (ehSectionStart <= cieStart) && (cieStart < ehSectionEnd) ) { - const char *errmsg; - // don't re-parse the cie if this fde is pointing to one we already parsed - if (cieStart == lastCieSeen) { - errmsg = NULL; - } - else { - errmsg = parseCIE(addressSpace, cieStart, &cieInfo); - if (errmsg == NULL) - lastCieSeen = cieStart; - } - if ( errmsg == NULL ) { - p += 4; - // parse pc begin and range - pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F); - //fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); - funcbounds.push_back(FuncBounds(pcStart, pcStart + pcRange)); - } - else { - // malformed CIE, now augmentation describing pc range encoding - //fprintf(stderr, "malformed CIE\n"); - return false; - } - } - else { - // malformed FDE. CIE is bad - //fprintf(stderr, "malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n", - // (uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd); - return false; - } - p = nextCFI; - } - } - return true; -} -#endif // SUPPORT_REMOTE_UNWINDING - - - -/// -/// Extract info from a CIE -/// -template <typename A> -const char* CFI_Parser<A>::parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo) -{ - //fprintf(stderr, "parseCIE(0x%llX)\n", (long long)cie); - cieInfo->pointerEncoding = 0; - cieInfo->lsdaEncoding = 0; - cieInfo->personalityEncoding = 0; - cieInfo->personalityOffsetInCIE = 0; - cieInfo->personality = 0; - cieInfo->codeAlignFactor = 0; - cieInfo->dataAlignFactor = 0; - cieInfo->isSignalFrame = false; - cieInfo->fdesHaveAugmentationData = false; - cieInfo->cieStart = cie; - pint_t p = cie; - uint64_t cieLength = addressSpace.get32(p); - p += 4; - pint_t cieContentEnd = p + cieLength; - if ( cieLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cieLength = addressSpace.get64(p); - p += 8; - cieContentEnd = p + cieLength; - } - if ( cieLength == 0 ) - return NULL; - // CIE ID is always 0 - if ( addressSpace.get32(p) != 0 ) - return "CIE ID is not zero"; - p += 4; - // Version is always 1 or 3 - uint8_t version = addressSpace.get8(p); - if ( (version != 1) && (version != 3) ) - return "CIE version is not 1 or 3"; - ++p; - // save start of augmentation string and find end - pint_t strStart = p; - while ( addressSpace.get8(p) != 0 ) - ++p; - ++p; - // parse code aligment factor - cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd); - // parse data alignment factor - cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd); - // parse return address register - addressSpace.getULEB128(p, cieContentEnd); - // parse augmentation data based on augmentation string - const char* result = NULL; - if ( addressSpace.get8(strStart) == 'z' ) { - // parse augmentation data length - addressSpace.getULEB128(p, cieContentEnd); - for (pint_t s=strStart; addressSpace.get8(s) != '\0'; ++s) { - switch ( addressSpace.get8(s) ) { - case 'z': - cieInfo->fdesHaveAugmentationData = true; - break; - case 'P': - cieInfo->personalityEncoding = addressSpace.get8(p); - ++p; - cieInfo->personalityOffsetInCIE = p-cie; - cieInfo->personality = addressSpace.getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); - break; - case 'L': - cieInfo->lsdaEncoding = addressSpace.get8(p); - ++p; - break; - case 'R': - cieInfo->pointerEncoding = addressSpace.get8(p); - ++p; - break; - case 'S': - cieInfo->isSignalFrame = true; - break; - default: - // ignore unknown letters - break; - } - } - } - cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; - cieInfo->cieInstructions = p; - return result; -} - - -template <typename A> -uint32_t CFI_Parser<A>::getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength) -{ - uint32_t count = 0; - const pint_t ehSectionEnd = ehSectionStart + sectionLength; - for (pint_t p=ehSectionStart; p < ehSectionEnd; ) { - uint64_t cfiLength = addressSpace.get32(p); - p += 4; - if ( cfiLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cfiLength = addressSpace.get64(p); - p += 8; - } - if ( cfiLength == 0 ) - return count; // end marker - ++count; - p += cfiLength; - } - return count; -} - - - -template <typename A> -const char* CFI_Parser<A>::getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, - std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies) -{ - const pint_t ehSectionEnd = ehSectionStart + sectionLength; - for (pint_t p=ehSectionStart; p < ehSectionEnd; ) { - pint_t currentCFI = p; - uint64_t cfiLength = addressSpace.get32(p); - p += 4; - if ( cfiLength == 0xffffffff ) { - // 0xffffffff means length is really next 8 bytes - cfiLength = addressSpace.get64(p); - p += 8; - } - if ( cfiLength == 0 ) - return NULL; // end marker - uint32_t id = addressSpace.get32(p); - if ( id == 0 ) { - // is CIE - CIE_Info cieInfo; - const char* err = parseCIE(addressSpace, currentCFI, &cieInfo); - if ( err != NULL ) - return err; - CIE_Atom_Info entry; - entry.cieAddress = currentCFI; - entry.personality.address = cieInfo.personality; - entry.personality.offsetInFDE = cieInfo.personalityOffsetInCIE; - entry.personality.encodingOfAddress = cieInfo.personalityEncoding; - cies.push_back(entry); - p += cfiLength; - } - else { - // is FDE - FDE_Atom_Info entry; - entry.fdeAddress = currentCFI; - entry.function.address = 0; - entry.cie.address = 0; - entry.lsda.address = 0; - pint_t nextCFI = p + cfiLength; - uint32_t ciePointer = addressSpace.get32(p); - pint_t cieStart = p-ciePointer; - // validate pointer to CIE is within section - if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) ) - return "FDE points to CIE outside __eh_frame section"; - CIE_Info cieInfo; - const char* err = parseCIE(addressSpace, cieStart, &cieInfo); - if ( err != NULL ) - return err; - entry.cie.address = cieStart; - entry.cie.offsetInFDE = p-currentCFI; - entry.cie.encodingOfAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; - p += 4; - // parse pc begin and range - pint_t offsetOfFunctionAddress = p-currentCFI; - pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F); - //fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); - // test if pc is within the function this FDE covers - entry.function.address = pcStart; - entry.function.offsetInFDE = offsetOfFunctionAddress; - entry.function.encodingOfAddress = cieInfo.pointerEncoding; - // skip over augmentation length - if ( cieInfo.fdesHaveAugmentationData ) { - uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if ( (cieInfo.lsdaEncoding != 0) && (addressSpace.getP(p) != 0) ) { - pint_t offsetOfLSDAAddress = p-currentCFI; - entry.lsda.address = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding); - entry.lsda.offsetInFDE = offsetOfLSDAAddress; - entry.lsda.encodingOfAddress = cieInfo.lsdaEncoding; - } - p = endOfAug; - } - fdes.push_back(entry); - p = nextCFI; - } - } - return NULL; // success -} - - - -/// -/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE -/// -template <typename A> -bool CFI_Parser<A>::parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results) -{ - // clear results - bzero(results, sizeof(PrologInfo)); - PrologInfoStackEntry* rememberStack = NULL; - - // parse CIE then FDE instructions - return parseInstructions(addressSpace, cieInfo.cieInstructions, cieInfo.cieStart+cieInfo.cieLength, - cieInfo, (pint_t)(-1), rememberStack, results) - && parseInstructions(addressSpace, fdeInfo.fdeInstructions, fdeInfo.fdeStart+fdeInfo.fdeLength, - cieInfo, upToPC-fdeInfo.pcStart, rememberStack, results); -} - - -/// -/// "run" the dwarf instructions -/// -template <typename A> -bool CFI_Parser<A>::parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo, - pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results) -{ - const bool logDwarf = false; - pint_t p = instructions; - uint32_t codeOffset = 0; - PrologInfo initialState = *results; - - // see Dwarf Spec, section 6.4.2 for details on unwind opcodes - while ( (p < instructionsEnd) && (codeOffset < pcoffset) ) { - uint64_t reg; - uint64_t reg2; - int64_t offset; - uint64_t length; - uint8_t opcode = addressSpace.get8(p); - uint8_t operand; - PrologInfoStackEntry* entry; - ++p; - switch (opcode) { - case DW_CFA_nop: - if ( logDwarf ) fprintf(stderr, "DW_CFA_nop\n"); - break; - case DW_CFA_set_loc: - codeOffset = addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); - if ( logDwarf ) fprintf(stderr, "DW_CFA_set_loc\n"); - break; - case DW_CFA_advance_loc1: - codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); - p += 1; - if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc1: new offset=%u\n", codeOffset); - break; - case DW_CFA_advance_loc2: - codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); - p += 2; - if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc2: new offset=%u\n", codeOffset); - break; - case DW_CFA_advance_loc4: - codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); - p += 4; - if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc4: new offset=%u\n", codeOffset); - break; - case DW_CFA_offset_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n"); - return false; - } - if ( results->savedRegisters[reg].location != kRegisterUnused ) - results->registerSavedMoreThanOnce = true; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg, offset); - break; - case DW_CFA_restore_extended: - reg = addressSpace.getULEB128(p, instructionsEnd);; - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg] = initialState.savedRegisters[reg]; - if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg); - break; - case DW_CFA_undefined: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_undefined dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterUnused; - if ( logDwarf ) fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg); - break; - case DW_CFA_same_value: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_same_value dwarf unwind, reg too big\n"); - return false; - } - if ( logDwarf ) fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg); - break; - case DW_CFA_register: - reg = addressSpace.getULEB128(p, instructionsEnd); - reg2 = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg too big\n"); - return false; - } - if ( reg2 > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg2 too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterInRegister; - results->savedRegisters[reg].value = reg2; - results->registersInOtherRegisters = true; - if ( logDwarf ) fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2); - break; - case DW_CFA_remember_state: - // avoid operator new, because that would be an upward dependency - entry = (PrologInfoStackEntry*)malloc(sizeof(PrologInfoStackEntry)); - if ( entry != NULL ) { - entry->next = rememberStack; - entry->info = *results; - rememberStack = entry; - } - else { - return false; - } - if ( logDwarf ) fprintf(stderr, "DW_CFA_remember_state\n"); - break; - case DW_CFA_restore_state: - if ( rememberStack != NULL ) { - PrologInfoStackEntry* top = rememberStack; - *results = top->info; - rememberStack = top->next; - free((char*)top); - } - else { - return false; - } - if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_state\n"); - break; - case DW_CFA_def_cfa: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n"); - return false; - } - results->cfaRegister = reg; - results->cfaRegisterOffset = offset; - if ( offset > 0x80000000 ) - results->cfaOffsetWasNegative = true; - if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset); - break; - case DW_CFA_def_cfa_register: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n"); - return false; - } - results->cfaRegister = reg; - if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg); - break; - case DW_CFA_def_cfa_offset: - results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd); - results->codeOffsetAtStackDecrement = codeOffset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n", results->cfaRegisterOffset); - break; - case DW_CFA_def_cfa_expression: - results->cfaRegister = 0; - results->cfaExpression = p; - length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n", - results->cfaExpression, length); - break; - case DW_CFA_expression: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_expression dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterAtExpression; - results->savedRegisters[reg].value = p; - length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if ( logDwarf ) fprintf(stderr, "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n", - reg, results->savedRegisters[reg].value, length); - break; - case DW_CFA_offset_extended_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n"); - return false; - } - offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if ( results->savedRegisters[reg].location != kRegisterUnused ) - results->registerSavedMoreThanOnce = true; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n", reg, offset); - break; - case DW_CFA_def_cfa_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n"); - return false; - } - results->cfaRegister = reg; - results->cfaRegisterOffset = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg, offset); - break; - case DW_CFA_def_cfa_offset_sf: - results->cfaRegisterOffset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->codeOffsetAtStackDecrement = codeOffset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n", results->cfaRegisterOffset); - break; - case DW_CFA_val_offset: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg, offset); - break; - case DW_CFA_val_offset_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n"); - return false; - } - offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg, offset); - break; - case DW_CFA_val_expression: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_val_expression dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterIsExpression; - results->savedRegisters[reg].value = p; - length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if ( logDwarf ) fprintf(stderr, "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n", - reg, results->savedRegisters[reg].value, length); - break; - case DW_CFA_GNU_args_size: - offset = addressSpace.getULEB128(p, instructionsEnd); - results->spExtraArgSize = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", offset); - break; - case DW_CFA_GNU_negative_offset_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - if ( reg > kMaxRegisterNumber ) { - fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf unwind, reg too big\n"); - return false; - } - offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if ( results->savedRegisters[reg].location != kRegisterUnused ) - results->registerSavedMoreThanOnce = true; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = -offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset); - break; - default: - operand = opcode & 0x3F; - switch ( opcode & 0xC0 ) { - case DW_CFA_offset: - reg = operand; - offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if ( results->savedRegisters[reg].location != kRegisterUnused ) - results->registerSavedMoreThanOnce = true; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - if ( logDwarf ) fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand, offset); - break; - case DW_CFA_advance_loc: - codeOffset += operand * cieInfo.codeAlignFactor; - if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc: new offset=%u\n", codeOffset); - break; - case DW_CFA_restore: - // <rdar://problem/7503075> Python crashes when handling an exception thrown by an obj-c object - // libffi uses DW_CFA_restore in the middle of some custom dward, so it is not a good epilog flag - //return true; // gcc-4.5 starts the epilog with this - reg = operand; - results->savedRegisters[reg] = initialState.savedRegisters[reg]; - if ( logDwarf ) fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg); - break; - default: - if ( logDwarf ) fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode); - return false; - } - } - } - - return true; -} - - -} // namespace lldb_private - - -#endif // __DWARF_PARSER_HPP__ - - - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/FileAbstraction.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/FileAbstraction.hpp deleted file mode 100644 index a4af02051a5..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/FileAbstraction.hpp +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- FileAbstraction.hpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __FILE_ABSTRACTION__ -#define __FILE_ABSTRACTION__ - - -#include <stdint.h> -#include <string.h> -#include <libkern/OSByteOrder.h> - -#ifdef __OPTIMIZE__ -#define INLINE __attribute__((always_inline)) -#else -#define INLINE -#endif - -// -// This abstraction layer is for use with file formats that have 64-bit/32-bit and Big-Endian/Little-Endian variants -// -// For example: to make a utility that handles 32-bit little enidan files use: Pointer32<LittleEndian> -// -// -// get16() read a 16-bit number from an E endian struct -// set16() write a 16-bit number to an E endian struct -// get32() read a 32-bit number from an E endian struct -// set32() write a 32-bit number to an E endian struct -// get64() read a 64-bit number from an E endian struct -// set64() write a 64-bit number to an E endian struct -// -// getBits() read a bit field from an E endian struct (bitCount=number of bits in field, firstBit=bit index of field) -// setBits() write a bit field to an E endian struct (bitCount=number of bits in field, firstBit=bit index of field) -// -// getBitsRaw() read a bit field from a struct with native endianness -// setBitsRaw() write a bit field from a struct with native endianness -// - -class BigEndian -{ -public: - static uint16_t get16(const uint16_t& from) INLINE { return OSReadBigInt16(&from, 0); } - static void set16(uint16_t& into, uint16_t value) INLINE { OSWriteBigInt16(&into, 0, value); } - - static uint32_t get32(const uint32_t& from) INLINE { return OSReadBigInt32(&from, 0); } - static void set32(uint32_t& into, uint32_t value) INLINE { OSWriteBigInt32(&into, 0, value); } - - static uint64_t get64(const uint64_t& from) INLINE { return OSReadBigInt64(&from, 0); } - static void set64(uint64_t& into, uint64_t value) INLINE { OSWriteBigInt64(&into, 0, value); } - - static uint32_t getBits(const uint32_t& from, - uint8_t firstBit, uint8_t bitCount) INLINE { return getBitsRaw(get32(from), firstBit, bitCount); } - static void setBits(uint32_t& into, uint32_t value, - uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); } - - static uint32_t getBitsRaw(const uint32_t& from, - uint8_t firstBit, uint8_t bitCount) INLINE { return ((from >> (32-firstBit-bitCount)) & ((1<<bitCount)-1)); } - static void setBitsRaw(uint32_t& into, uint32_t value, - uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = into; - const uint32_t mask = ((1<<bitCount)-1); - temp &= ~(mask << (32-firstBit-bitCount)); - temp |= ((value & mask) << (32-firstBit-bitCount)); - into = temp; } - enum { little_endian = 0 }; -}; - - -class LittleEndian -{ -public: - static uint16_t get16(const uint16_t& from) INLINE { return OSReadLittleInt16(&from, 0); } - static void set16(uint16_t& into, uint16_t value) INLINE { OSWriteLittleInt16(&into, 0, value); } - - static uint32_t get32(const uint32_t& from) INLINE { return OSReadLittleInt32(&from, 0); } - static void set32(uint32_t& into, uint32_t value) INLINE { OSWriteLittleInt32(&into, 0, value); } - - static uint64_t get64(const uint64_t& from) INLINE { return OSReadLittleInt64(&from, 0); } - static void set64(uint64_t& into, uint64_t value) INLINE { OSWriteLittleInt64(&into, 0, value); } - - static uint32_t getBits(const uint32_t& from, - uint8_t firstBit, uint8_t bitCount) INLINE { return getBitsRaw(get32(from), firstBit, bitCount); } - static void setBits(uint32_t& into, uint32_t value, - uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); } - - static uint32_t getBitsRaw(const uint32_t& from, - uint8_t firstBit, uint8_t bitCount) INLINE { return ((from >> firstBit) & ((1<<bitCount)-1)); } - static void setBitsRaw(uint32_t& into, uint32_t value, - uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = into; - const uint32_t mask = ((1<<bitCount)-1); - temp &= ~(mask << firstBit); - temp |= ((value & mask) << firstBit); - into = temp; } - enum { little_endian = 1 }; -}; - - -template <typename _E> -class Pointer32 -{ -public: - typedef uint32_t uint_t; - typedef int32_t int_t; - typedef _E E; - - static uint64_t getP(const uint_t& from) INLINE { return _E::get32(from); } - static void setP(uint_t& into, uint64_t value) INLINE { _E::set32(into, value); } -}; - - -template <typename _E> -class Pointer64 -{ -public: - typedef uint64_t uint_t; - typedef int64_t int_t; - typedef _E E; - - static uint64_t getP(const uint_t& from) INLINE { return _E::get64(from); } - static void setP(uint_t& into, uint64_t value) INLINE { _E::set64(into, value); } -}; - - - - - - -#endif // __FILE_ABSTRACTION__ - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/InternalMacros.h b/lldb/source/Plugins/Process/Utility/libunwind/src/InternalMacros.h deleted file mode 100644 index 40483900d38..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/InternalMacros.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- InternalMacros.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef INTERNAL_MACROS_H -#define INTERNAL_MACROS_H - -#include <assert.h> - -#ifdef __cplusplus -extern "C" { -#endif - extern void __assert_rtn(const char *, const char *, int, const char *) __attribute__((noreturn)); -#ifdef __cplusplus -} -#endif - -#define UNW_STEP_SUCCESS 1 -#define UNW_STEP_END 0 - - -struct v128 { unsigned int vec[4]; }; - - -#define EXPORT __attribute__((visibility("default"))) - -#define COMPILE_TIME_ASSERT( expr ) \ - extern int compile_time_assert_failed[ ( expr ) ? 1 : -1 ] __attribute__( ( unused ) ); - -#define ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg) - -#if NDEBUG - #define DEBUG_MESSAGE(msg, ...) - #define DEBUG_PRINT_API(msg, ...) - #define DEBUG_PRINT_UNWINDING_TEST 0 - #define DEBUG_PRINT_UNWINDING(msg, ...) - #define DEBUG_LOG_NON_ZERO(x) x; - #define INITIALIZE_DEBUG_PRINT_API - #define INITIALIZE_DEBUG_PRINT_UNWINDING -#else - #define DEBUG_MESSAGE(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__) - #ifdef __cplusplus - extern "C" { - #endif - extern bool logAPIs(); - extern bool logUnwinding(); - #ifdef __cplusplus - } - #endif - #define DEBUG_LOG_NON_ZERO(x) { int _err = x; if ( _err != 0 ) fprintf(stderr, "libuwind: " #x "=%d in %s", _err, __FUNCTION__); } - #define DEBUG_PRINT_API(msg, ...) do { if ( logAPIs() ) fprintf(stderr, msg, __VA_ARGS__); } while(0) - #define DEBUG_PRINT_UNWINDING(msg, ...) do { if ( logUnwinding() ) fprintf(stderr, msg, __VA_ARGS__); } while(0) - #define DEBUG_PRINT_UNWINDING_TEST logUnwinding() - #define INITIALIZE_DEBUG_PRINT_API bool logAPIs() { static bool log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); return log; } - #define INITIALIZE_DEBUG_PRINT_UNWINDING bool logUnwinding() { static bool log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); return log; } -#endif - - -// note hack for <rdar://problem/6175741> -// Once libgcc_s.dylib vectors to libSystem, then we can remove the $ld$hide$os10.6$ lines -#if __ppc__ - #define NOT_HERE_BEFORE_10_6(sym) \ - extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; - #define NEVER_HERE(sym) \ - extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \ - extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0; -#else - #define NOT_HERE_BEFORE_10_6(sym) \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; - #define NEVER_HERE(sym) \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \ - extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0; -#endif - - - -#endif // INTERNAL_MACROS_H diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/Registers.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/Registers.hpp deleted file mode 100644 index 89bd1ce4156..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/Registers.hpp +++ /dev/null @@ -1,456 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- Registers.hpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// -// C++ interface to lower levels of libuwind -// - -#ifndef __REGISTERS_HPP__ -#define __REGISTERS_HPP__ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> -#include <mach-o/loader.h> -#include <mach-o/getsect.h> -#include <mach/i386/thread_status.h> - -#include "libunwind.h" -#include "InternalMacros.h" - -namespace lldb_private { - - -/// -/// Registers_x86 holds the register state of a thread in a 32-bit intel process. -/// -class Registers_x86 -{ -public: - Registers_x86(); - Registers_x86(const void* registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int num) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const { return false; } - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - const char* getRegisterName(int num); - void jumpto() {} - - uint32_t getSP() const { return fRegisters.__esp; } - void setSP(uint32_t value) { fRegisters.__esp = value; } - uint32_t getIP() const { return fRegisters.__eip; } - void setIP(uint32_t value) { fRegisters.__eip = value; } - uint32_t getEBP() const { return fRegisters.__ebp; } - void setEBP(uint32_t value) { fRegisters.__ebp = value; } - uint32_t getEBX() const { return fRegisters.__ebx; } - void setEBX(uint32_t value) { fRegisters.__ebx = value; } - uint32_t getECX() const { return fRegisters.__ecx; } - void setECX(uint32_t value) { fRegisters.__ecx = value; } - uint32_t getEDX() const { return fRegisters.__edx; } - void setEDX(uint32_t value) { fRegisters.__edx = value; } - uint32_t getESI() const { return fRegisters.__esi; } - void setESI(uint32_t value) { fRegisters.__esi = value; } - uint32_t getEDI() const { return fRegisters.__edi; } - void setEDI(uint32_t value) { fRegisters.__edi = value; } - -private: - i386_thread_state_t fRegisters; -}; - -inline Registers_x86::Registers_x86(const void* registers) -{ - COMPILE_TIME_ASSERT( sizeof(Registers_x86) < sizeof(unw_context_t) ); - fRegisters = *((i386_thread_state_t*)registers); -} - -inline Registers_x86::Registers_x86() -{ - bzero(&fRegisters, sizeof(fRegisters)); -} - - -inline bool Registers_x86::validRegister(int regNum) const -{ - if ( regNum == UNW_REG_IP ) - return true; - if ( regNum == UNW_REG_SP ) - return true; - if ( regNum < 0 ) - return false; - if ( regNum > 7 ) - return false; - return true; -} - -inline uint32_t Registers_x86::getRegister(int regNum) const -{ - switch ( regNum ) { - case UNW_REG_IP: - return fRegisters.__eip; - case UNW_REG_SP: - return fRegisters.__esp; - case UNW_X86_EAX: - return fRegisters.__eax; - case UNW_X86_ECX: - return fRegisters.__ecx; - case UNW_X86_EDX: - return fRegisters.__edx; - case UNW_X86_EBX: - return fRegisters.__ebx; - case UNW_X86_EBP: - return fRegisters.__ebp; - case UNW_X86_ESP: - return fRegisters.__esp; - case UNW_X86_ESI: - return fRegisters.__esi; - case UNW_X86_EDI: - return fRegisters.__edi; - } - ABORT("unsupported x86 register"); -} - -inline void Registers_x86::setRegister(int regNum, uint32_t value) -{ - switch ( regNum ) { - case UNW_REG_IP: - fRegisters.__eip = value; - return; - case UNW_REG_SP: - fRegisters.__esp = value; - return; - case UNW_X86_EAX: - fRegisters.__eax = value; - return; - case UNW_X86_ECX: - fRegisters.__ecx = value; - return; - case UNW_X86_EDX: - fRegisters.__edx = value; - return; - case UNW_X86_EBX: - fRegisters.__ebx = value; - return; - case UNW_X86_EBP: - fRegisters.__ebp = value; - return; - case UNW_X86_ESP: - fRegisters.__esp = value; - return; - case UNW_X86_ESI: - fRegisters.__esi = value; - return; - case UNW_X86_EDI: - fRegisters.__edi = value; - return; - } - ABORT("unsupported x86 register"); -} - -inline const char* Registers_x86::getRegisterName(int regNum) -{ - switch ( regNum ) { - case UNW_REG_IP: - return "ip"; - case UNW_REG_SP: - return "esp"; - case UNW_X86_EAX: - return "eax"; - case UNW_X86_ECX: - return "ecx"; - case UNW_X86_EDX: - return "edx"; - case UNW_X86_EBX: - return "ebx"; - case UNW_X86_EBP: - return "ebp"; - case UNW_X86_ESP: - return "esp"; - case UNW_X86_ESI: - return "esi"; - case UNW_X86_EDI: - return "edi"; - default: - return "unknown register"; - } -} - -inline double Registers_x86::getFloatRegister(int num) const -{ - ABORT("no x86 float registers"); -} - -inline void Registers_x86::setFloatRegister(int num, double value) -{ - ABORT("no x86 float registers"); -} - -inline v128 Registers_x86::getVectorRegister(int num) const -{ - ABORT("no x86 vector registers"); -} - -inline void Registers_x86::setVectorRegister(int num, v128 value) -{ - ABORT("no x86 vector registers"); -} - - - - -/// -/// Registers_x86_64 holds the register state of a thread in a 64-bit intel process. -/// -class Registers_x86_64 -{ -public: - Registers_x86_64(); - Registers_x86_64(const void* registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int num) const{ return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const { return false; } - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - const char* getRegisterName(int num); - void jumpto() {} - uint64_t getSP() const { return fRegisters.__rsp; } - void setSP(uint64_t value) { fRegisters.__rsp = value; } - uint64_t getIP() const { return fRegisters.__rip; } - void setIP(uint64_t value) { fRegisters.__rip = value; } - uint64_t getRBP() const { return fRegisters.__rbp; } - void setRBP(uint64_t value) { fRegisters.__rbp = value; } - uint64_t getRBX() const { return fRegisters.__rbx; } - void setRBX(uint64_t value) { fRegisters.__rbx = value; } - uint64_t getR12() const { return fRegisters.__r12; } - void setR12(uint64_t value) { fRegisters.__r12 = value; } - uint64_t getR13() const { return fRegisters.__r13; } - void setR13(uint64_t value) { fRegisters.__r13 = value; } - uint64_t getR14() const { return fRegisters.__r14; } - void setR14(uint64_t value) { fRegisters.__r14 = value; } - uint64_t getR15() const { return fRegisters.__r15; } - void setR15(uint64_t value) { fRegisters.__r15 = value; } -private: - x86_thread_state64_t fRegisters; -}; - -inline Registers_x86_64::Registers_x86_64(const void* registers) -{ - COMPILE_TIME_ASSERT( sizeof(Registers_x86_64) < sizeof(unw_context_t) ); - fRegisters = *((x86_thread_state64_t*)registers); -} - -inline Registers_x86_64::Registers_x86_64() -{ - bzero(&fRegisters, sizeof(fRegisters)); -} - - -inline bool Registers_x86_64::validRegister(int regNum) const -{ - if ( regNum == UNW_REG_IP ) - return true; - if ( regNum == UNW_REG_SP ) - return true; - if ( regNum < 0 ) - return false; - if ( regNum > 15 ) - return false; - return true; -} - -inline uint64_t Registers_x86_64::getRegister(int regNum) const -{ - switch ( regNum ) { - case UNW_REG_IP: - return fRegisters.__rip; - case UNW_REG_SP: - return fRegisters.__rsp; - case UNW_X86_64_RAX: - return fRegisters.__rax; - case UNW_X86_64_RDX: - return fRegisters.__rdx; - case UNW_X86_64_RCX: - return fRegisters.__rcx; - case UNW_X86_64_RBX: - return fRegisters.__rbx; - case UNW_X86_64_RSI: - return fRegisters.__rsi; - case UNW_X86_64_RDI: - return fRegisters.__rdi; - case UNW_X86_64_RBP: - return fRegisters.__rbp; - case UNW_X86_64_RSP: - return fRegisters.__rsp; - case UNW_X86_64_R8: - return fRegisters.__r8; - case UNW_X86_64_R9: - return fRegisters.__r9; - case UNW_X86_64_R10: - return fRegisters.__r10; - case UNW_X86_64_R11: - return fRegisters.__r11; - case UNW_X86_64_R12: - return fRegisters.__r12; - case UNW_X86_64_R13: - return fRegisters.__r13; - case UNW_X86_64_R14: - return fRegisters.__r14; - case UNW_X86_64_R15: - return fRegisters.__r15; - } - ABORT("unsupported x86_64 register"); -} - -inline void Registers_x86_64::setRegister(int regNum, uint64_t value) -{ - switch ( regNum ) { - case UNW_REG_IP: - fRegisters.__rip = value; - return; - case UNW_REG_SP: - fRegisters.__rsp = value; - return; - case UNW_X86_64_RAX: - fRegisters.__rax = value; - return; - case UNW_X86_64_RDX: - fRegisters.__rdx = value; - return; - case UNW_X86_64_RCX: - fRegisters.__rcx = value; - return; - case UNW_X86_64_RBX: - fRegisters.__rbx = value; - return; - case UNW_X86_64_RSI: - fRegisters.__rsi = value; - return; - case UNW_X86_64_RDI: - fRegisters.__rdi = value; - return; - case UNW_X86_64_RBP: - fRegisters.__rbp = value; - return; - case UNW_X86_64_RSP: - fRegisters.__rsp = value; - return; - case UNW_X86_64_R8: - fRegisters.__r8 = value; - return; - case UNW_X86_64_R9: - fRegisters.__r9 = value; - return; - case UNW_X86_64_R10: - fRegisters.__r10 = value; - return; - case UNW_X86_64_R11: - fRegisters.__r11 = value; - return; - case UNW_X86_64_R12: - fRegisters.__r12 = value; - return; - case UNW_X86_64_R13: - fRegisters.__r13 = value; - return; - case UNW_X86_64_R14: - fRegisters.__r14 = value; - return; - case UNW_X86_64_R15: - fRegisters.__r15 = value; - return; - } - ABORT("unsupported x86_64 register"); -} - -inline const char* Registers_x86_64::getRegisterName(int regNum) -{ - switch ( regNum ) { - case UNW_REG_IP: - return "rip"; - case UNW_REG_SP: - return "rsp"; - case UNW_X86_64_RAX: - return "rax"; - case UNW_X86_64_RDX: - return "rdx"; - case UNW_X86_64_RCX: - return "rcx"; - case UNW_X86_64_RBX: - return "rbx"; - case UNW_X86_64_RSI: - return "rsi"; - case UNW_X86_64_RDI: - return "rdi"; - case UNW_X86_64_RBP: - return "rbp"; - case UNW_X86_64_RSP: - return "rsp"; - case UNW_X86_64_R8: - return "r8"; - case UNW_X86_64_R9: - return "r9"; - case UNW_X86_64_R10: - return "r10"; - case UNW_X86_64_R11: - return "r11"; - case UNW_X86_64_R12: - return "r12"; - case UNW_X86_64_R13: - return "r13"; - case UNW_X86_64_R14: - return "r14"; - case UNW_X86_64_R15: - return "r15"; - default: - return "unknown register"; - } -} - -double Registers_x86_64::getFloatRegister(int num) const -{ - ABORT("no x86_64 float registers"); -} - -void Registers_x86_64::setFloatRegister(int num, double value) -{ - ABORT("no x86_64 float registers"); -} - -inline v128 Registers_x86_64::getVectorRegister(int num) const -{ - ABORT("no x86_64 vector registers"); -} - -inline void Registers_x86_64::setVectorRegister(int num, v128 value) -{ - ABORT("no x86_64 vector registers"); -} - - -} // namespace lldb_private - - - -#endif // __REGISTERS_HPP__ - - - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/Registers.s b/lldb/source/Plugins/Process/Utility/libunwind/src/Registers.s deleted file mode 100644 index 45dae3bcbfc..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/Registers.s +++ /dev/null @@ -1,261 +0,0 @@ - - -#if __i386__ - .text - .globl __ZN12lldb_private13Registers_x866jumptoEv - .private_extern __ZN12lldb_private13Registers_x866jumptoEv -__ZN12lldb_private13Registers_x866jumptoEv: -# -# void lldb_private::Registers_x86::jumpto() -# -# On entry: -# + + -# +-----------------------+ -# + thread_state pointer + -# +-----------------------+ -# + return address + -# +-----------------------+ <-- SP -# + + - movl 4(%esp), %eax - # set up eax and ret on new stack location - movl 28(%eax), %edx # edx holds new stack pointer - subl $8,%edx - movl %edx, 28(%eax) - movl 0(%eax), %ebx - movl %ebx, 0(%edx) - movl 40(%eax), %ebx - movl %ebx, 4(%edx) - # we now have ret and eax pushed onto where new stack will be - # restore all registers - movl 4(%eax), %ebx - movl 8(%eax), %ecx - movl 12(%eax), %edx - movl 16(%eax), %edi - movl 20(%eax), %esi - movl 24(%eax), %ebp - movl 28(%eax), %esp - # skip ss - # skip eflags - pop %eax # eax was already pushed on new stack - ret # eip was already pushed on new stack - # skip cs - # skip ds - # skip es - # skip fs - # skip gs - -#elif __x86_64__ - - .text - .globl __ZN12lldb_private16Registers_x86_646jumptoEv - .private_extern __ZN12lldb_private16Registers_x86_646jumptoEv -__ZN12lldb_private16Registers_x86_646jumptoEv: -# -# void lldb_private::Registers_x86_64::jumpto() -# -# On entry, thread_state pointer is in rdi - - movq 56(%rdi), %rax # rax holds new stack pointer - subq $16, %rax - movq %rax, 56(%rdi) - movq 32(%rdi), %rbx # store new rdi on new stack - movq %rbx, 0(%rax) - movq 128(%rdi), %rbx # store new rip on new stack - movq %rbx, 8(%rax) - # restore all registers - movq 0(%rdi), %rax - movq 8(%rdi), %rbx - movq 16(%rdi), %rcx - movq 24(%rdi), %rdx - # restore rdi later - movq 40(%rdi), %rsi - movq 48(%rdi), %rbp - # restore rsp later - movq 64(%rdi), %r8 - movq 72(%rdi), %r9 - movq 80(%rdi), %r10 - movq 88(%rdi), %r11 - movq 96(%rdi), %r12 - movq 104(%rdi), %r13 - movq 112(%rdi), %r14 - movq 120(%rdi), %r15 - # skip rflags - # skip cs - # skip fs - # skip gs - movq 56(%rdi), %rsp # cut back rsp to new location - pop %rdi # rdi was saved here earlier - ret # rip was saved here - - -#elif __ppc__ - - .text - .globl __ZN12lldb_private13Registers_ppc6jumptoEv - .private_extern __ZN12lldb_private13Registers_ppc6jumptoEv -__ZN12lldb_private13Registers_ppc6jumptoEv: -; -; void lldb_private::Registers_ppc::jumpto() -; -; On entry: -; thread_state pointer is in r3 -; - - ; restore integral registerrs - ; skip r0 for now - ; skip r1 for now - lwz r2, 16(r3) - ; skip r3 for now - ; skip r4 for now - ; skip r5 for now - lwz r6, 32(r3) - lwz r7, 36(r3) - lwz r8, 40(r3) - lwz r9, 44(r3) - lwz r10, 48(r3) - lwz r11, 52(r3) - lwz r12, 56(r3) - lwz r13, 60(r3) - lwz r14, 64(r3) - lwz r15, 68(r3) - lwz r16, 72(r3) - lwz r17, 76(r3) - lwz r18, 80(r3) - lwz r19, 84(r3) - lwz r20, 88(r3) - lwz r21, 92(r3) - lwz r22, 96(r3) - lwz r23,100(r3) - lwz r24,104(r3) - lwz r25,108(r3) - lwz r26,112(r3) - lwz r27,116(r3) - lwz r28,120(r3) - lwz r29,124(r3) - lwz r30,128(r3) - lwz r31,132(r3) - - ; restore float registers - lfd f0, 160(r3) - lfd f1, 168(r3) - lfd f2, 176(r3) - lfd f3, 184(r3) - lfd f4, 192(r3) - lfd f5, 200(r3) - lfd f6, 208(r3) - lfd f7, 216(r3) - lfd f8, 224(r3) - lfd f9, 232(r3) - lfd f10,240(r3) - lfd f11,248(r3) - lfd f12,256(r3) - lfd f13,264(r3) - lfd f14,272(r3) - lfd f15,280(r3) - lfd f16,288(r3) - lfd f17,296(r3) - lfd f18,304(r3) - lfd f19,312(r3) - lfd f20,320(r3) - lfd f21,328(r3) - lfd f22,336(r3) - lfd f23,344(r3) - lfd f24,352(r3) - lfd f25,360(r3) - lfd f26,368(r3) - lfd f27,376(r3) - lfd f28,384(r3) - lfd f29,392(r3) - lfd f30,400(r3) - lfd f31,408(r3) - - ; restore vector registers if any are in use - lwz r5,156(r3) ; test VRsave - cmpwi r5,0 - beq Lnovec - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone - ; the fVectorRegisters may not be 16-byte aligned so copy via red zone temp buffer - - -#define LOAD_VECTOR_UNALIGNEDl(_index) \ - andis. r0,r5,(1<<(15-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ -Ldone ## _index: - -#define LOAD_VECTOR_UNALIGNEDh(_index) \ - andi. r0,r5,(1<<(31-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ - Ldone ## _index: - - - LOAD_VECTOR_UNALIGNEDl(0) - LOAD_VECTOR_UNALIGNEDl(1) - LOAD_VECTOR_UNALIGNEDl(2) - LOAD_VECTOR_UNALIGNEDl(3) - LOAD_VECTOR_UNALIGNEDl(4) - LOAD_VECTOR_UNALIGNEDl(5) - LOAD_VECTOR_UNALIGNEDl(6) - LOAD_VECTOR_UNALIGNEDl(7) - LOAD_VECTOR_UNALIGNEDl(8) - LOAD_VECTOR_UNALIGNEDl(9) - LOAD_VECTOR_UNALIGNEDl(10) - LOAD_VECTOR_UNALIGNEDl(11) - LOAD_VECTOR_UNALIGNEDl(12) - LOAD_VECTOR_UNALIGNEDl(13) - LOAD_VECTOR_UNALIGNEDl(14) - LOAD_VECTOR_UNALIGNEDl(15) - LOAD_VECTOR_UNALIGNEDh(16) - LOAD_VECTOR_UNALIGNEDh(17) - LOAD_VECTOR_UNALIGNEDh(18) - LOAD_VECTOR_UNALIGNEDh(19) - LOAD_VECTOR_UNALIGNEDh(20) - LOAD_VECTOR_UNALIGNEDh(21) - LOAD_VECTOR_UNALIGNEDh(22) - LOAD_VECTOR_UNALIGNEDh(23) - LOAD_VECTOR_UNALIGNEDh(24) - LOAD_VECTOR_UNALIGNEDh(25) - LOAD_VECTOR_UNALIGNEDh(26) - LOAD_VECTOR_UNALIGNEDh(27) - LOAD_VECTOR_UNALIGNEDh(28) - LOAD_VECTOR_UNALIGNEDh(29) - LOAD_VECTOR_UNALIGNEDh(30) - LOAD_VECTOR_UNALIGNEDh(31) - -Lnovec: - lwz r0, 136(r3) ; __cr - mtocrf 255,r0 - lwz r0, 148(r3) ; __ctr - mtctr r0 - lwz r0, 0(r3) ; __ssr0 - mtctr r0 - lwz r0, 8(r3) ; do r0 now - lwz r5,28(r3) ; do r5 now - lwz r4,24(r3) ; do r4 now - lwz r1,12(r3) ; do sp now - lwz r3,20(r3) ; do r3 last - bctr - - -#endif - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteDebuggerDummyUnwinder.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteDebuggerDummyUnwinder.hpp deleted file mode 100644 index b7e833eb871..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteDebuggerDummyUnwinder.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- RemoteDebuggerDummyUnwinder.hpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// Code to unwind past a debugger's dummy frame inserted when it does an -// inferior function call. -// In this case we'll need to get the saved register context from the debugger - -// it may be in the debugger's local memory or it may be saved in a nonstandard -// location in the inferior process' memory. - -#ifndef __REMOTE_DEBUGGER_DUMMY_UNWINDER_HPP__ -#define __REMOTE_DEBUGGER_DUMMY_UNWINDER_HPP__ - -#if defined (SUPPORT_REMOTE_UNWINDING) - -#include "libunwind.h" -#include "Registers.hpp" -#include "AddressSpace.hpp" -#include "RemoteRegisterMap.hpp" -#include "RemoteProcInfo.hpp" - -namespace lldb_private -{ - -template <typename A> -int stepOutOfDebuggerDummyFrame (A& addressSpace, Registers_x86_64& registers, - RemoteProcInfo *procinfo, uint64_t ip, - uint64_t sp, void* arg) -{ - Registers_x86_64 newRegisters(registers); - RemoteRegisterMap *rmap = addressSpace.getRemoteProcInfo()->getRegisterMap(); - unw_word_t regv; - for (int i = UNW_X86_64_RAX; i <= UNW_X86_64_R15; i++) { - int driver_regnum; - if (!rmap->unwind_regno_to_caller_regno (i, driver_regnum)) - continue; - if (addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, driver_regnum, ®v, 0, arg)) - newRegisters.setRegister(i, regv); - } - if (!addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, rmap->caller_regno_for_ip(), ®v, 0, arg)) - return UNW_EUNSPEC; - newRegisters.setIP (regv); - registers = newRegisters; - return UNW_STEP_SUCCESS; -} - -template <typename A> -int stepOutOfDebuggerDummyFrame (A& addressSpace, Registers_x86& registers, - RemoteProcInfo *procinfo, uint64_t ip, - uint64_t sp, void* arg) -{ - Registers_x86 newRegisters(registers); - RemoteRegisterMap *rmap = addressSpace.getRemoteProcInfo()->getRegisterMap(); - unw_word_t regv; - for (int i = UNW_X86_EAX; i <= UNW_X86_EDI; i++) { - int driver_regnum; - if (!rmap->unwind_regno_to_caller_regno (i, driver_regnum)) - continue; - if (addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, driver_regnum, ®v, 0, arg)) - newRegisters.setRegister(i, regv); - } - if (!addressSpace.accessors()->access_reg_inf_func_call (procinfo->wrap(), ip, sp, rmap->caller_regno_for_ip(), ®v, 0, arg)) - return UNW_EUNSPEC; - newRegisters.setIP (regv); - registers = newRegisters; - return UNW_STEP_SUCCESS; -} - -}; // namespace lldb_private - -#endif // SUPPORT_REMOTE_UNWINDING - -#endif // __REMOTE_DEBUGGER_DUMMY_UNWINDER_HPP__ - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteProcInfo.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteProcInfo.hpp deleted file mode 100644 index ee9901c6211..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteProcInfo.hpp +++ /dev/null @@ -1,984 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- RemoteProcInfo.hpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This file defines the primary object created when unw_create_addr_space() -// is called. This object tracks the list of known images in memory -// (dylibs, bundles, etc), it maintains a link to a RemoteRegisterMap for this -// architecture, it caches the remote process memory in a local store and all -// read/writes are filtered through its accessors which will use the memory -// caches. It maintains a logging level set by the driver program and puts -// timing/debug messages out on a FILE* provided to it. - -// RemoteProcInfo is not specific to any particular unwind so it does not -// maintain an "arg" argument (an opaque pointer that the driver program uses -// to track the process/thread being unwound). - -#ifndef __REMOTE_PROC_INFO_HPP__ -#define __REMOTE_PROC_INFO_HPP__ - -#if defined (SUPPORT_REMOTE_UNWINDING) - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <dlfcn.h> -#include <stdarg.h> -#include <sys/time.h> -#include <mach-o/loader.h> -#include <mach-o/getsect.h> -#include <mach/i386/thread_status.h> -#include <Availability.h> - -#include <map> -#include <vector> -#include <algorithm> - -#include "FileAbstraction.hpp" -#include "libunwind.h" -#include "InternalMacros.h" -#include "dwarf2.h" -#include "RemoteUnwindProfile.h" -#include "Registers.hpp" -#include "RemoteRegisterMap.hpp" - -namespace lldb_private -{ -class RemoteProcInfo; - -/// -/// unw_addr_space_remote is the concrete instance that a unw_addr_space_t points to when examining -/// a remote process. -/// -struct unw_addr_space_remote -{ - enum unw_as_type type; // should always be UNW_REMOTE - RemoteProcInfo* ras; -}; - -class RemoteMemoryBlob -{ -public: - typedef void (*free_callback_with_arg)(void *, void*); - typedef void (*free_callback)(void *); - - /* This object is constructed with a callback to free the memory; - that callback takes a pointer to the memory region and optionally - takes an additional argument -- the "void* arg" passed around for - remote unwinds, in case the driver program allocated this e.g. with - mach_vm_read, and needs the token to vm_deallocate it. */ - - RemoteMemoryBlob (uint8_t *buf, free_callback_with_arg to_free, - uint64_t startaddr, uint64_t len, uint64_t mh, void *arg) : - fBuf(buf), fToFree(NULL), fToFreeWithArg(to_free), - fStartAddr(startaddr), fLen(len), fMachHeader(mh), - fArg(arg) { } - RemoteMemoryBlob (uint8_t *buf, free_callback to_free, uint64_t startaddr, - uint64_t len, uint64_t mh, void *arg) : - fBuf(buf), fToFree(to_free), fToFreeWithArg(NULL), - fStartAddr(startaddr), fLen(len), fMachHeader(mh), - fArg(NULL) { } - - // the following is to create a dummy RMB object for lower_bound's use in - // searching. - RemoteMemoryBlob (uint64_t startaddr) : fBuf(NULL), fToFree(NULL), - fToFreeWithArg(NULL), fStartAddr(startaddr), fLen(0), - fMachHeader(-1), fArg(NULL) { } - ~RemoteMemoryBlob () { - if (fToFreeWithArg) - fToFreeWithArg(fBuf, fArg); - else if (fToFree) - fToFree(fBuf); - } - bool contains_addr (uint64_t addr) { - if (fStartAddr <= addr && addr < fStartAddr + fLen) - return true; - else - return false; - } - uint8_t *get_blob_range (uint64_t remote_process_addr, int len) { - if (this->contains_addr (remote_process_addr) == false) - return NULL; - if (this->contains_addr (remote_process_addr + len) == false) - return NULL; - return fBuf + (remote_process_addr - fStartAddr); - } - uint64_t getMh () const { return fMachHeader; } - uint64_t getStartAddr() const { return fStartAddr; } - uint64_t getLength() const { return fLen; } -private: - uint8_t *fBuf; - free_callback fToFree; - free_callback_with_arg fToFreeWithArg; - uint64_t fStartAddr; - uint64_t fLen; - uint64_t fMachHeader; - void *fArg; -}; - -inline bool operator<(const RemoteMemoryBlob &b1, const RemoteMemoryBlob &b2) { - if (b1.getStartAddr() < b2.getStartAddr()) - return true; - else - return false; -} - -// One of these for each image in memory (executable, dylib, bundle, etc) - -struct RemoteImageEntry -{ - RemoteImageEntry () : mach_header(0), text_start(0), text_end(0), eh_frame_start(0), eh_frame_len(0), compact_unwind_info_start(0), compact_unwind_info_len(0) { } - ~RemoteImageEntry () { - std::map<uint64_t, RemoteUnwindProfile *>::iterator i; - for (i = profiles.begin(); i != profiles.end(); ++i) - delete i->second; - } - uint64_t mach_header; - uint64_t text_start; - uint64_t text_end; - uint64_t eh_frame_start; - uint64_t eh_frame_len; - uint64_t compact_unwind_info_start; - uint64_t compact_unwind_info_len; - - // unwind profiles created for thsi binary image so far, - // key is the start address of the profile. - std::map<uint64_t, RemoteUnwindProfile *> profiles; - - // a list of function address bounds for this binary image - - // end addresses should be accurate and not inferred from potentially - // incomplete start-address data (e.g. nlist records). - std::vector<FuncBounds> func_bounds; -}; - -class RemoteImages -{ -public: - RemoteImages (unw_targettype_t targarch) : fTargetArch(targarch) { } - ~RemoteImages (); - void removeAllImageProfiles(); - void removeOneImageProfiles(uint64_t mh); - RemoteImageEntry *remoteEntryForTextAddr (uint64_t pc); - bool addFuncBounds (uint64_t mh, std::vector<FuncBounds> &startAddrs); - bool haveFuncBounds (uint64_t mh); - bool findFuncBounds (uint32_t pc, uint32_t &startAddr, uint32_t &endAddr); - bool findFuncBounds (uint64_t pc, uint64_t &startAddr, uint64_t &endAddr); - void addImage (uint64_t mh, uint64_t text_start, uint64_t text_end, uint64_t eh_frame, uint64_t eh_frame_len, uint64_t compact_unwind_start, uint64_t compact_unwind_len); - bool addProfile (RemoteProcInfo* procinfo, unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, void *arg); - RemoteUnwindProfile* findProfileByTextAddr (uint64_t pc); - bool addMemBlob (RemoteMemoryBlob *blob); - uint8_t *getMemBlobMemory (uint64_t addr, int len); -private: - RemoteImages(); - std::map<uint64_t, RemoteImageEntry> fImages; - std::vector<RemoteMemoryBlob *> fMemBlobs; - unw_targettype_t fTargetArch; -}; - -RemoteImages::~RemoteImages () { - std::map<uint64_t, std::vector<RemoteMemoryBlob *> >::iterator i; - std::vector<RemoteMemoryBlob *>::iterator j; - for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) { - delete *j; - } - fMemBlobs.erase(fMemBlobs.begin(), fMemBlobs.end()); -} - -void RemoteImages::removeAllImageProfiles() { - fImages.erase(fImages.begin(), fImages.end()); - std::vector<RemoteMemoryBlob *>::iterator j; - for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) - delete *j; - fMemBlobs.erase(fMemBlobs.begin(), fMemBlobs.end()); -} - -void RemoteImages::removeOneImageProfiles(uint64_t mh) { - std::map<uint64_t, RemoteImageEntry>::iterator i; - i = fImages.find(mh); - if (i != fImages.end()) - fImages.erase(i); - - std::vector<RemoteMemoryBlob *>::iterator j; - for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) { - if ((*j)->getMh() == mh) { - delete *j; - break; - } - } - if (j != fMemBlobs.end()) - fMemBlobs.erase(j); -} - -RemoteImageEntry *RemoteImages::remoteEntryForTextAddr (uint64_t pc) { - std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (pc); - if (i == fImages.begin() && i == fImages.end()) - return NULL; - if (i == fImages.end()) { - --i; - } else { - if (i != fImages.begin() && i->first != pc) - --i; - } - if (i->second.text_start <= pc && i->second.text_end > pc) - { - return &(i->second); - } - else - { - return NULL; - } -} - -bool RemoteImages::addFuncBounds (uint64_t mh, std::vector<FuncBounds> &startAddrs) { - RemoteImageEntry *img = NULL; - std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.find (mh); - if (i == fImages.end()) - return false; - img = &i->second; - img->func_bounds = startAddrs; - std::sort(img->func_bounds.begin(), img->func_bounds.end()); - return true; -} - -bool RemoteImages::haveFuncBounds (uint64_t mh) { - RemoteImageEntry *img = NULL; - std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.find (mh); - if (i == fImages.end()) - return false; - img = &i->second; - if (img->func_bounds.size() > 0) - return true; - return false; -} - -bool RemoteImages::findFuncBounds (uint64_t pc, uint64_t &startAddr, uint64_t &endAddr) { - RemoteImageEntry *img = NULL; - startAddr = endAddr = 0; - std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (pc); - if (i == fImages.begin() && i == fImages.end()) - return false; - if (i == fImages.end()) { - --i; - } else { - if (i != fImages.begin() && i->first != pc) - --i; - } - if (i->second.text_start <= pc && i->second.text_end > pc) - { - img = &i->second; - } - else - return false; - std::vector<FuncBounds>::iterator j; - j = std::lower_bound(img->func_bounds.begin(), img->func_bounds.end(), FuncBounds (pc, pc)); - if (j == img->func_bounds.begin() && j == img->func_bounds.end()) - return false; - if (j == img->func_bounds.end()) { - --j; - } else { - if (j != img->func_bounds.begin() && j->fStart != pc) - --j; - } - if (j->fStart <= pc && j->fEnd > pc) { - startAddr = j->fStart; - endAddr = j->fEnd; - return true; - } - return false; -} - -// Add 32-bit version of findFuncBounds so we can avoid templatizing all of these functions -// just to handle 64 and 32 bit unwinds. - -bool RemoteImages::findFuncBounds (uint32_t pc, uint32_t &startAddr, uint32_t &endAddr) { - uint64_t big_startAddr = startAddr; - uint64_t big_endAddr = endAddr; - bool ret; - ret = findFuncBounds (pc, big_startAddr, big_endAddr); - startAddr = (uint32_t) big_startAddr & 0xffffffff; - endAddr = (uint32_t) big_endAddr & 0xffffffff; - return ret; -} - -// Make sure we don't cache the same memory range more than once -// I'm not checking the length of the blobs to check for overlap - -// as this is used today, the only duplication will be with the same -// start address. - -bool -RemoteImages::addMemBlob (RemoteMemoryBlob *blob) { - - if (fMemBlobs.empty()) - { - fMemBlobs.push_back(blob); - } - else - { - std::vector<RemoteMemoryBlob *>::iterator pos; - - pos = std::lower_bound (fMemBlobs.begin(), fMemBlobs.end(), blob); - - if (pos != fMemBlobs.end() && (*pos)->getStartAddr() == blob->getStartAddr()) - return false; - - fMemBlobs.insert (pos, blob); - } - return true; -} - -uint8_t *RemoteImages::getMemBlobMemory (uint64_t addr, int len) { - uint8_t *res = NULL; - std::vector<RemoteMemoryBlob *>::iterator j; - RemoteMemoryBlob *searchobj = new RemoteMemoryBlob(addr); - j = std::lower_bound (fMemBlobs.begin(), fMemBlobs.end(), searchobj); - delete searchobj; - if (j == fMemBlobs.end() && j == fMemBlobs.begin()) - return NULL; - if (j == fMemBlobs.end()) { - --j; - } else { - if (j != fMemBlobs.begin() && (*j)->getStartAddr() != addr) - --j; - } - res = (*j)->get_blob_range (addr, len); - if (res != NULL) - return res; - for (j = fMemBlobs.begin(); j != fMemBlobs.end(); ++j) { - res = (*j)->get_blob_range (addr, len); - if (res != NULL) - break; - } - return res; -} - -void RemoteImages::addImage (uint64_t mh, uint64_t text_start, - uint64_t text_end, uint64_t eh_frame, - uint64_t eh_frame_len, - uint64_t compact_unwind_start, - uint64_t compact_unwind_len) { - struct RemoteImageEntry img; - img.mach_header = mh; - img.text_start = text_start; - img.text_end = text_end; - img.eh_frame_start = eh_frame; - img.eh_frame_len = eh_frame_len; - img.compact_unwind_info_start = compact_unwind_start; - img.compact_unwind_info_len = compact_unwind_len; - fImages[mh] = img; -} - -// The binary image for this start/end address must already be present -bool RemoteImages::addProfile (RemoteProcInfo* procinfo, unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, void *arg) { - RemoteImageEntry *img = NULL; - std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (start); - if (i == fImages.begin() && i == fImages.end()) - return false; - if (i == fImages.end()) { - --i; - } else { - if (i != fImages.begin() && i->first != start) { - --i; - } - } - if (i->second.text_start <= start && i->second.text_end > start) - { - img = &i->second; - } - else - return false; - RemoteUnwindProfile* profile = new RemoteUnwindProfile; - if (AssemblyParse (procinfo, acc, as, start, end, *profile, arg)) { - img->profiles[start] = profile; - return true; - } - return false; -} - -RemoteUnwindProfile* RemoteImages::findProfileByTextAddr (uint64_t pc) { - RemoteImageEntry *img = NULL; - std::map<uint64_t, RemoteImageEntry>::iterator i = fImages.lower_bound (pc); - if (i == fImages.begin() && i == fImages.end()) - return NULL; - if (i == fImages.end()) { - --i; - } else { - if (i != fImages.begin() && i->first != pc) - --i; - } - if (i->second.text_start <= pc && i->second.text_end > pc) - { - img = &i->second; - } - else - return NULL; - std::map<uint64_t, RemoteUnwindProfile *>::iterator j; - j = img->profiles.lower_bound (pc); - if (j == img->profiles.begin() && j == img->profiles.end()) - return NULL; - if (j == img->profiles.end()) { - --j; - } else { - if (j != img->profiles.begin() && j->first != pc) - --j; - } - if (j->second->fStart <= pc && j->second->fEnd > pc) - { - return j->second; - } - return NULL; -} - -/// -/// RemoteProcInfo is used as a template parameter to UnwindCursor when -/// unwinding a thread that has a custom set of accessors. It calls the -/// custom accessors for all data. -/// -class RemoteProcInfo -{ -public: - -// libunwind documentation specifies that unw_create_addr_space defaults to -// UNW_CACHE_NONE but that's going to work very poorly for us so we're -// defaulting to UNW_CACHE_GLOBAL. - - RemoteProcInfo(unw_accessors_t* accessors, unw_targettype_t targarch) : - fAccessors(*accessors), fCachingPolicy(UNW_CACHE_GLOBAL), - fTargetArch(targarch), fImages(targarch), fLogging(NULL), - fLogLevel(UNW_LOG_LEVEL_NONE) - { - fWrapper.type = UNW_REMOTE; - fWrapper.ras = this; - fRemoteRegisterMap = new RemoteRegisterMap(accessors, targarch); - if (fTargetArch == UNW_TARGET_X86_64 || fTargetArch == UNW_TARGET_I386 - || fTargetArch == UNW_TARGET_ARM) - fLittleEndian = true; - else - fLittleEndian = false; - } - - ~RemoteProcInfo () { - delete fRemoteRegisterMap; - } - - bool haveProfile (uint64_t pc) { - if (fImages.findProfileByTextAddr (pc)) - return true; - else - return false; - } - - // returns NULL if profile does not yet exist. - RemoteUnwindProfile* findProfile (uint64_t pc) { - return fImages.findProfileByTextAddr (pc); - } - - // returns NULL if the binary image is not yet added. - bool addProfile (unw_accessors_t *acc, unw_addr_space_t as, uint64_t start, uint64_t end, void *arg) { - if (fImages.addProfile (this, acc, as, start, end, arg)) - return true; - else - return false; - } - - bool haveImageEntry (uint64_t pc, void *arg); - - bool getImageAddresses (uint64_t pc, uint64_t &mh, uint64_t &text_start, uint64_t &text_end, - uint64_t &eh_frame_start, uint64_t &eh_frame_len, uint64_t &compact_unwind_start, - void *arg); - bool getImageAddresses (uint64_t pc, uint32_t &mh, uint32_t &text_start, uint32_t &text_end, - uint32_t &eh_frame_start, uint32_t &eh_frame_len, uint32_t &compact_unwind_start, - void *arg); - - bool addFuncBounds (uint64_t mh, std::vector<FuncBounds> &startAddrs) { return fImages.addFuncBounds (mh, startAddrs); } - bool haveFuncBounds (uint64_t mh) { return fImages.haveFuncBounds (mh); } - bool findStartAddr (uint64_t pc, uint32_t &startAddr, uint32_t &endAddr) { return fImages.findFuncBounds (pc, startAddr, endAddr); } - bool findStartAddr (uint64_t pc, uint64_t &startAddr, uint64_t &endAddr) { return fImages.findFuncBounds (pc, startAddr, endAddr); } - uint8_t *getMemBlobMemory (uint64_t addr, int len) { return fImages.getMemBlobMemory (addr, len); } - - - // Functions to pull memory from the target into the debugger. - - int getBytes(uint64_t addr, uint64_t extent, uint8_t* buf, void* arg) - { - int err = readRaw(addr, extent, buf, arg); - - if(err) - return 0; - - return 1; - } - -#define DECLARE_INT_ACCESSOR(bits) \ - uint##bits##_t get##bits(uint64_t addr, void* arg) \ - { \ - uint##bits##_t ret; \ - int err = readRaw(addr, (unw_word_t)(bits / 8), (uint8_t*)&ret, arg); \ - \ - if(err) \ - ABORT("Invalid memory access in the target"); \ - \ - return ret; \ - } - DECLARE_INT_ACCESSOR(8) - DECLARE_INT_ACCESSOR(16) - DECLARE_INT_ACCESSOR(32) - DECLARE_INT_ACCESSOR(64) -#undef DECLARE_INT_ACCESSOR - -// 'err' is set to 0 if there were no errors reading this -// memory. Non-zero values indicate that the memory was not -// read successfully. This method should be preferred over the -// method above which asserts on failure. - -#define DECLARE_INT_ACCESSOR_ERR(bits) \ - uint##bits##_t get##bits(uint64_t addr, int &err, void* arg) \ - { \ - uint##bits##_t ret; \ - err = readRaw(addr, (unw_word_t)(bits / 8), (uint8_t*)&ret, arg); \ - \ - return ret; \ - } - DECLARE_INT_ACCESSOR_ERR(8) - DECLARE_INT_ACCESSOR_ERR(16) - DECLARE_INT_ACCESSOR_ERR(32) - DECLARE_INT_ACCESSOR_ERR(64) -#undef DECLARE_INT_ACCESSOR_ERR - - double getDouble(uint64_t addr, void* arg) - { - double ret; - int err = readRaw(addr, (unw_word_t)(sizeof(ret) / 8), (uint8_t*)&ret, arg); - if(err) - ABORT("Invalid memory access in the target"); - return ret; - } - - v128 getVector(uint64_t addr, void* arg) - { - v128 ret; - int err = readRaw(addr, (unw_word_t)(sizeof(ret) / 8), (uint8_t*)&ret, arg); - if(err) - ABORT("Invalid memory access in the target"); - return ret; - } - - // Pull an unsigned LEB128 from the target into the debugger as a uint64_t. - uint64_t getULEB128(uint64_t& addr, uint64_t end, void* arg) - { - uint64_t lAddr = addr; - uint64_t ret = 0; - uint8_t shift = 0; - uint64_t byte; - do { - if(lAddr == end) - ABORT("Truncated LEB128 number in the target"); - - byte = (uint64_t)get8(lAddr, arg); - lAddr++; - - if(((shift == 63) && (byte > 0x01)) || (shift > 63)) - ABORT("LEB128 number is larger than is locally representible"); - - ret |= ((byte & 0x7f) << shift); - shift += 7; - } while((byte & 0x80) == 0x80); - addr = lAddr; - return ret; - } - - // Pull an unsigned LEB128 from the target into the debugger as a uint64_t. - uint64_t getULEB128(uint32_t& addr, uint32_t end, void* arg) - { - uint32_t lAddr = addr; - uint64_t ret = 0; - uint8_t shift = 0; - uint64_t byte; - do { - if(lAddr == end) - ABORT("Truncated LEB128 number in the target"); - - byte = (uint64_t)get8(lAddr, arg); - lAddr++; - - if(((shift == 63) && (byte > 0x01)) || (shift > 63)) - ABORT("LEB128 number is larger than is locally representible"); - - ret |= ((byte & 0x7f) << shift); - shift += 7; - } while((byte & 0x80) == 0x80); - addr = lAddr; - return ret; - } - - - // Pull a signed LEB128 from the target into the debugger as a uint64_t. - int64_t getSLEB128(uint64_t& addr, uint64_t end, void* arg) - { - uint64_t lAddr = addr; - uint64_t ret = 0; - uint8_t shift = 0; - uint64_t byte; - do { - if(lAddr == end) - ABORT("Truncated LEB128 number in the target"); - byte = (uint64_t)get8(lAddr, arg); - lAddr++; - if(((shift == 63) && (byte > 0x01)) || (shift > 63)) - ABORT("LEB128 number is larger than is locally representible"); - ret |= ((byte & 0x7f) << shift); - shift += 7; - } while((byte & 0x80) == 0x80); - // Sign-extend - if((shift < (sizeof(int64_t) * 8)) && (byte & 0x40)) - ret |= -(1 << shift); - addr = lAddr; - return ret; - } - - // Pull a signed LEB128 from the target into the debugger as a uint64_t. - int64_t getSLEB128(uint32_t& addr, uint32_t end, void* arg) - { - uint32_t lAddr = addr; - uint64_t ret = 0; - uint8_t shift = 0; - uint64_t byte; - do { - if(lAddr == end) - ABORT("Truncated LEB128 number in the target"); - byte = (uint64_t)get8(lAddr, arg); - lAddr++; - if(((shift == 63) && (byte > 0x01)) || (shift > 63)) - ABORT("LEB128 number is larger than is locally representible"); - ret |= ((byte & 0x7f) << shift); - shift += 7; - } while((byte & 0x80) == 0x80); - // Sign-extend - if((shift < (sizeof(int64_t) * 8)) && (byte & 0x40)) - ret |= -(1 << shift); - addr = lAddr; - return ret; - } - - - uint64_t getP (uint64_t addr, void *arg) { - switch (fTargetArch) { - case UNW_TARGET_X86_64: - return get64(addr, arg); - break; - case UNW_TARGET_I386: - return get32(addr, arg); - break; - } - ABORT("Unknown target architecture."); - return 0; - } - - uint64_t getP (uint64_t addr, int& err, void *arg) { - switch (fTargetArch) { - case UNW_TARGET_X86_64: - return get64(addr, err, arg); - break; - case UNW_TARGET_I386: - return get32(addr, err, arg); - break; - } - ABORT("Unknown target architecture."); - return 0; - } - - bool findFunctionName(uint64_t addr, char *buf, size_t bufLen, unw_word_t *offset, void* arg); - bool findFunctionBounds(uint64_t addr, uint64_t& low, uint64_t& high, void* arg); - int setCachingPolicy(unw_caching_policy_t policy); - - void setLoggingLevel(FILE *f, unw_log_level_t level); - void logInfo(const char *fmt, ...); - void logAPI(const char *fmt, ...); - void logVerbose(const char *fmt, ...); - void logDebug(const char *fmt, ...); - struct timeval *timestamp_start (); - void timestamp_stop (struct timeval *tstart, const char *fmt, ...); - - void flushAllCaches() { fImages.removeAllImageProfiles(); } - void flushCacheByMachHeader(uint64_t mh) { fImages.removeOneImageProfiles(mh); } - unw_targettype_t getTargetArch() { return fTargetArch; } - unw_accessors_t* getAccessors () { return &fAccessors; } - RemoteRegisterMap* getRegisterMap() { return fRemoteRegisterMap; } - unw_addr_space_t wrap () { return (unw_addr_space_t) &fWrapper; } - bool remoteIsLittleEndian () { return fLittleEndian; } - unw_log_level_t getDebugLoggingLevel() { return fLogLevel; } - bool addMemBlob (RemoteMemoryBlob *blob) { return fImages.addMemBlob(blob); } - unw_caching_policy_t getCachingPolicy() { return fCachingPolicy; } - -private: - int readRaw(uint64_t addr, uint64_t extent, uint8_t *valp, void* arg) - { - uint8_t *t = this->getMemBlobMemory (addr, extent); - if (t) { - memcpy (valp, t, extent); - return 0; - } - return fAccessors.access_raw((unw_addr_space_t)this, addr, extent, valp, 0, arg); - } - - struct unw_addr_space_remote fWrapper; - unw_accessors_t fAccessors; - unw_caching_policy_t fCachingPolicy; - unw_targettype_t fTargetArch; - unw_addr_space_t fAddrSpace; - RemoteImages fImages; - RemoteRegisterMap *fRemoteRegisterMap; - FILE *fLogging; - unw_log_level_t fLogLevel; - bool fLittleEndian; -}; - -// Find an image containing the given pc, returns false if absent and -// we can't add it via the accessors. -bool RemoteProcInfo::haveImageEntry (uint64_t pc, void *arg) { - if (fImages.remoteEntryForTextAddr (pc) == NULL) { - unw_word_t mh, text_start, text_end, eh_frame, eh_frame_len, compact_unwind, compact_unwind_len; - if (fAccessors.find_image_info (wrap(), pc, &mh, &text_start, - &text_end, &eh_frame, &eh_frame_len, &compact_unwind, &compact_unwind_len, arg) == UNW_ESUCCESS) { - fImages.addImage (mh, text_start, text_end, eh_frame, eh_frame_len, compact_unwind, compact_unwind_len); - if (fCachingPolicy != UNW_CACHE_NONE) { - if (compact_unwind_len != 0) { - logVerbose ("Creating RemoteMemoryBlob of compact unwind info image at mh 0x%llx, %lld bytes", mh, (uint64_t) compact_unwind_len); - uint8_t *buf = (uint8_t*) malloc (compact_unwind_len); - if (this->getBytes (compact_unwind, compact_unwind_len, buf, arg)) { - RemoteMemoryBlob *b = new RemoteMemoryBlob(buf, free, compact_unwind, compact_unwind_len, mh, NULL); - if (fImages.addMemBlob (b) == false) - delete b; - } - } else if (eh_frame_len != 0) { - logVerbose ("Creating RemoteMemoryBlob of eh_frame for image at mh 0x%llx, %lld bytes", mh, (uint64_t) compact_unwind_len); - uint8_t *buf = (uint8_t*) malloc (eh_frame_len); - if (this->getBytes (eh_frame, eh_frame_len, buf, arg)) { - RemoteMemoryBlob *b = new RemoteMemoryBlob(buf, free, eh_frame, eh_frame_len, mh, NULL); - if (fImages.addMemBlob (b) == false) - delete b; - } - } - } - } else { - return false; /// find_image_info failed - } - } else { - return true; - } - return true; -} - -bool RemoteProcInfo::getImageAddresses (uint64_t pc, uint64_t &mh, uint64_t &text_start, uint64_t &text_end, - uint64_t &eh_frame_start, uint64_t &eh_frame_len, uint64_t &compact_unwind_start, - void *arg) { - // Make sure we have this RemoteImageEntry already - fetch it now if needed. - if (haveImageEntry (pc, arg) == false) { - return false; - } - RemoteImageEntry *r = fImages.remoteEntryForTextAddr (pc); - if (r) { - mh = r->mach_header; - text_start = r->text_start; - text_end = r->text_end; - eh_frame_start = r->eh_frame_start; - eh_frame_len = r->eh_frame_len; - compact_unwind_start = r->compact_unwind_info_start; - return true; - } - return false; -} - - -bool RemoteProcInfo::findFunctionName(uint64_t addr, char *buf, size_t bufLen, unw_word_t *offset, void* arg) -{ - if(fAccessors.get_proc_name(wrap(), addr, buf, bufLen, offset, arg) == UNW_ESUCCESS) - return true; - else - return false; -} - -bool RemoteProcInfo::findFunctionBounds(uint64_t addr, uint64_t& low, uint64_t& high, void* arg) -{ - if (fAccessors.get_proc_bounds(wrap(), addr, &low, &high, arg) == UNW_ESUCCESS - && high != 0) - return true; - else - return false; -} - -int RemoteProcInfo::setCachingPolicy(unw_caching_policy_t policy) -{ - if(policy == UNW_CACHE_NONE && fCachingPolicy != UNW_CACHE_NONE) - { - flushAllCaches(); - } - - if(!(policy == UNW_CACHE_NONE || policy == UNW_CACHE_GLOBAL || policy == UNW_CACHE_PER_THREAD)) - return UNW_EINVAL; - - fCachingPolicy = policy; - - return UNW_ESUCCESS; -} - -void RemoteProcInfo::setLoggingLevel(FILE *f, unw_log_level_t level) -{ - fLogLevel = level; - fLogging = f; -} - -void RemoteProcInfo::logInfo(const char *fmt, ...) -{ - if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE) - return; - if (fLogLevel & UNW_LOG_LEVEL_INFO) { - va_list ap; - va_start (ap, fmt); - vfprintf (fLogging, fmt, ap); - fputs ("\n", fLogging); - va_end (ap); - } -} - -void RemoteProcInfo::logAPI(const char *fmt, ...) -{ - if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE) - return; - if (fLogLevel & UNW_LOG_LEVEL_API) { - va_list ap; - va_start (ap, fmt); - vfprintf (fLogging, fmt, ap); - fputs ("\n", fLogging); - va_end (ap); - } -} - -void RemoteProcInfo::logVerbose(const char *fmt, ...) -{ - if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE) - return; - if (fLogLevel & UNW_LOG_LEVEL_VERBOSE) { - va_list ap; - va_start (ap, fmt); - vfprintf (fLogging, fmt, ap); - fputs ("\n", fLogging); - va_end (ap); - } -} - -void RemoteProcInfo::logDebug(const char *fmt, ...) -{ - if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE) - return; - if (fLogLevel & UNW_LOG_LEVEL_DEBUG) { - va_list ap; - va_start (ap, fmt); - vfprintf (fLogging, fmt, ap); - fputs ("\n", fLogging); - va_end (ap); - } -} - -struct timeval *RemoteProcInfo::timestamp_start () -{ - if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE) - return NULL; - if (fLogLevel & UNW_LOG_LEVEL_TIMINGS) { - struct timeval *t = (struct timeval *) malloc (sizeof (struct timeval)); - if (gettimeofday (t, NULL) != 0) { - free (t); - return NULL; - } - return t; - } - return NULL; -} - -void RemoteProcInfo::timestamp_stop (struct timeval *tstart, const char *fmt, ...) -{ - if (fLogging == NULL || fLogLevel == UNW_LOG_LEVEL_NONE || tstart == NULL) - return; - if (fLogLevel & UNW_LOG_LEVEL_TIMINGS) { - struct timeval tend; - if (gettimeofday (&tend, NULL) != 0) { - free (tstart); - return; - } - struct timeval result; - timersub (&tend, tstart, &result); - va_list ap; - va_start (ap, fmt); - vprintf (fmt, ap); - printf (" duration %0.5fs\n", (double) ((result.tv_sec * 1000000) + result.tv_usec) / 1000000.0); - va_end (ap); - free (tstart); - } -} - - -// Initialize the register context at the start of a remote unwind. - -void getRemoteContext (RemoteProcInfo* procinfo, Registers_x86_64& r, void *arg) { - unw_accessors_t* accessors = procinfo->getAccessors(); - unw_addr_space_t addrSpace = procinfo->wrap(); - RemoteRegisterMap* regmap = procinfo->getRegisterMap(); - uint64_t rv; - - // now that we have a selected process/thread, ask about the valid registers. - regmap->scan_caller_regs (addrSpace, arg); - -#define FILLREG(reg) {int caller_reg; regmap->unwind_regno_to_caller_regno ((reg), caller_reg); accessors->access_reg (addrSpace, caller_reg, &rv, 0, arg); r.setRegister ((reg), rv);} - FILLREG (UNW_X86_64_RAX); - FILLREG (UNW_X86_64_RDX); - FILLREG (UNW_X86_64_RCX); - FILLREG (UNW_X86_64_RBX); - FILLREG (UNW_X86_64_RSI); - FILLREG (UNW_X86_64_RDI); - FILLREG (UNW_X86_64_RBP); - FILLREG (UNW_X86_64_RSP); - FILLREG (UNW_X86_64_R8); - FILLREG (UNW_X86_64_R9); - FILLREG (UNW_X86_64_R10); - FILLREG (UNW_X86_64_R11); - FILLREG (UNW_X86_64_R12); - FILLREG (UNW_X86_64_R13); - FILLREG (UNW_X86_64_R14); - FILLREG (UNW_X86_64_R15); - FILLREG (UNW_REG_IP); -#undef FILLREG -} - -void getRemoteContext (RemoteProcInfo* procinfo, Registers_x86& r, void *arg) { - unw_accessors_t* accessors = procinfo->getAccessors(); - unw_addr_space_t addrSpace = procinfo->wrap(); - RemoteRegisterMap* regmap = procinfo->getRegisterMap(); - uint64_t rv; - - // now that we have a selected process/thread, ask about the valid registers. - regmap->scan_caller_regs (addrSpace, arg); - -#define FILLREG(reg) {int caller_reg; regmap->unwind_regno_to_caller_regno ((reg), caller_reg); accessors->access_reg (addrSpace, caller_reg, &rv, 0, arg); r.setRegister ((reg), rv);} - FILLREG (UNW_X86_EAX); - FILLREG (UNW_X86_ECX); - FILLREG (UNW_X86_EDX); - FILLREG (UNW_X86_EBX); - FILLREG (UNW_X86_EBP); - FILLREG (UNW_X86_ESP); - FILLREG (UNW_X86_ESI); - FILLREG (UNW_X86_EDI); - FILLREG (UNW_REG_IP); -#undef FILLREG -} - -}; // namespace lldb_private - - - -#endif // SUPPORT_REMOTE_UNWINDING -#endif // __REMOTE_PROC_INFO_HPP__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteRegisterMap.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteRegisterMap.hpp deleted file mode 100644 index 86da827370a..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteRegisterMap.hpp +++ /dev/null @@ -1,405 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- RemoteRegisterMap.hpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// Provide conversions between reigster names, the libunwind internal enums, -// and the register numbers the program calling libunwind are using. - -#ifndef __REMOTE_REGISTER_MAP_HPP__ -#define __REMOTE_REGISTER_MAP_HPP__ - -#if defined (SUPPORT_REMOTE_UNWINDING) - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_CONSTANT_MACROS -#define __STDC_CONSTANT_MACROS -#endif - -#include "libunwind.h" -#include <vector> - -namespace lldb_private -{ -class RemoteRegisterMap { -public: - RemoteRegisterMap (unw_accessors_t *accessors, unw_targettype_t target); - ~RemoteRegisterMap (); - void initialize_x86_64 (); - void initialize_i386 (); - bool name_to_caller_regno (const char *name, int& callerr); - bool name_to_unwind_regno (const char *name, int& unwindr); - bool unwind_regno_to_caller_regno (int unwindr, int& callerr); - bool nonvolatile_reg_p (int unwind_regno); - bool argument_regnum_p (int unwind_regno); - const char *ip_register_name(); - const char *sp_register_name(); - int caller_regno_for_ip (); - int caller_regno_for_sp (); - int unwind_regno_for_frame_pointer (); - int unwind_regno_for_stack_pointer (); - int wordsize () { return fWordSize; } - void scan_caller_regs (unw_addr_space_t as, void *arg); - - bool unwind_regno_to_machine_regno (int unwindr, int& machiner); - bool machine_regno_to_unwind_regno (int machr, int& unwindr); - bool caller_regno_to_unwind_regno (int callerr, int& unwindr); - const char* unwind_regno_to_name (int unwindr); - int byte_size_for_regtype (unw_regtype_t type); - -private: - - // A structure that collects everything we need to know about a - // given register in one place. - struct reg { - int unwind_regno; // What libunwind-remote uses internally - int caller_regno; // What the libunwind-remote driver program uses - int eh_frame_regno; // What the eh_frame section uses - int machine_regno; // What the actual bits/bytes are in instructions - char *name; - unw_regtype_t type; - reg () : unwind_regno(-1), caller_regno(-1), eh_frame_regno(-1), - machine_regno(-1), name(NULL), type(UNW_NOT_A_REG) { } - }; - - unw_accessors_t fAccessors; - unw_targettype_t fTarget; - std::vector<RemoteRegisterMap::reg> fRegMap; - int fWordSize; -}; - -void RemoteRegisterMap::initialize_x86_64 () { -#define DEFREG(ureg, ehno, machno, regn) {RemoteRegisterMap::reg r; r.unwind_regno = ureg; r.name = regn; r.eh_frame_regno = ehno; r.machine_regno = machno; r.type = UNW_INTEGER_REG; fRegMap.push_back(r); } - DEFREG (UNW_X86_64_RAX, 0, 0, strdup ("rax")); - DEFREG (UNW_X86_64_RDX, 1, 2, strdup ("rdx")); - DEFREG (UNW_X86_64_RCX, 2, 1, strdup ("rcx")); - DEFREG (UNW_X86_64_RBX, 3, 3, strdup ("rbx")); - DEFREG (UNW_X86_64_RSI, 4, 6, strdup ("rsi")); - DEFREG (UNW_X86_64_RDI, 5, 7, strdup ("rdi")); - DEFREG (UNW_X86_64_RBP, 6, 5, strdup ("rbp")); - DEFREG (UNW_X86_64_RSP, 7, 4, strdup ("rsp")); - DEFREG (UNW_X86_64_R8, 8, 8, strdup ("r8")); - DEFREG (UNW_X86_64_R9, 9, 9, strdup ("r9")); - DEFREG (UNW_X86_64_R10, 10, 10, strdup ("r10")); - DEFREG (UNW_X86_64_R11, 11, 11, strdup ("r11")); - DEFREG (UNW_X86_64_R12, 12, 12, strdup ("r12")); - DEFREG (UNW_X86_64_R13, 13, 13, strdup ("r13")); - DEFREG (UNW_X86_64_R14, 14, 14, strdup ("r14")); - DEFREG (UNW_X86_64_R15, 15, 15, strdup ("r15")); -#undef DEFREG - RemoteRegisterMap::reg r; - r.name = strdup ("rip"); - r.type = UNW_INTEGER_REG; - r.eh_frame_regno = 16; - fRegMap.push_back(r); -} - -void RemoteRegisterMap::initialize_i386 () { -#define DEFREG(ureg, ehno, machno, regn) {RemoteRegisterMap::reg r; r.unwind_regno = ureg; r.name = regn; r.eh_frame_regno = ehno; r.machine_regno = machno; r.type = UNW_INTEGER_REG; fRegMap.push_back(r); } - DEFREG (UNW_X86_EAX, 0, 0, strdup ("eax")); - DEFREG (UNW_X86_ECX, 1, 1, strdup ("ecx")); - DEFREG (UNW_X86_EDX, 2, 2, strdup ("edx")); - DEFREG (UNW_X86_EBX, 3, 3, strdup ("ebx")); - // i386 EH frame info has the next two swapped, - // v. gcc/config/i386/darwin.h:DWARF2_FRAME_REG_OUT. - DEFREG (UNW_X86_EBP, 4, 5, strdup ("ebp")); - DEFREG (UNW_X86_ESP, 5, 4, strdup ("esp")); - DEFREG (UNW_X86_ESI, 6, 6, strdup ("esi")); - DEFREG (UNW_X86_EDI, 7, 7, strdup ("edi")); -#undef DEFREG - RemoteRegisterMap::reg r; - r.name = strdup ("eip"); - r.type = UNW_INTEGER_REG; - r.eh_frame_regno = 8; - fRegMap.push_back(r); -} - - -RemoteRegisterMap::RemoteRegisterMap (unw_accessors_t *accessors, unw_targettype_t target) { - fAccessors = *accessors; - fTarget = target; - switch (target) { - case UNW_TARGET_X86_64: - this->initialize_x86_64(); - fWordSize = 8; - break; - case UNW_TARGET_I386: - this->initialize_i386(); - fWordSize = 4; - break; - default: - ABORT("RemoteRegisterMap called with unknown target"); - } -} - -RemoteRegisterMap::~RemoteRegisterMap () { - std::vector<RemoteRegisterMap::reg>::iterator j; - for (j = fRegMap.begin(); j != fRegMap.end(); ++j) - free (j->name); -} - -bool RemoteRegisterMap::name_to_caller_regno (const char *name, int& callerr) { - if (name == NULL) - return false; - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (strcasecmp (j->name, name) == 0) { - callerr = j->caller_regno; - return true; - } - return false; -} - -bool RemoteRegisterMap::unwind_regno_to_caller_regno (int unwindr, int& callerr) { - if (unwindr == UNW_REG_IP) { - callerr = this->caller_regno_for_ip (); - return true; - } - if (unwindr == UNW_REG_SP) { - callerr = this->caller_regno_for_sp (); - return true; - } - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (j->unwind_regno == unwindr && j->caller_regno != -1) { - callerr = j->caller_regno; - return true; - } - return false; -} - -bool RemoteRegisterMap::nonvolatile_reg_p (int unwind_regno) { - if (fTarget == UNW_TARGET_X86_64) { - switch (unwind_regno) { - case UNW_X86_64_RBX: - case UNW_X86_64_RSP: - case UNW_X86_64_RBP: // not actually a nonvolatile but often treated as such by convention - case UNW_X86_64_R12: - case UNW_X86_64_R13: - case UNW_X86_64_R14: - case UNW_X86_64_R15: - case UNW_REG_IP: - case UNW_REG_SP: - return true; - break; - default: - return false; - } - } - if (fTarget == UNW_TARGET_I386) { - switch (unwind_regno) { - case UNW_X86_EBX: - case UNW_X86_EBP: // not actually a nonvolatile but often treated as such by convention - case UNW_X86_ESI: - case UNW_X86_EDI: - case UNW_X86_ESP: - case UNW_REG_IP: - case UNW_REG_SP: - return true; - break; - default: - return false; - } - } - return false; -} - - -bool RemoteRegisterMap::argument_regnum_p (int unwind_regno) { - if (fTarget == UNW_TARGET_X86_64) { - switch (unwind_regno) { - case UNW_X86_64_RDI: /* arg 1 */ - case UNW_X86_64_RSI: /* arg 2 */ - case UNW_X86_64_RDX: /* arg 3 */ - case UNW_X86_64_RCX: /* arg 4 */ - case UNW_X86_64_R8: /* arg 5 */ - case UNW_X86_64_R9: /* arg 6 */ - return true; - break; - default: - return false; - } - } - return false; -} - -const char *RemoteRegisterMap::ip_register_name () { - switch (fTarget) { - case UNW_TARGET_X86_64: - return "rip"; - case UNW_TARGET_I386: - return "eip"; - default: - ABORT("unsupported architecture"); - } - return NULL; -} - -const char *RemoteRegisterMap::sp_register_name () { - switch (fTarget) { - case UNW_TARGET_X86_64: - return "rsp"; - case UNW_TARGET_I386: - return "esp"; - default: - ABORT("unsupported architecture"); - } - return NULL; -} - -int RemoteRegisterMap::caller_regno_for_ip () { - int callerr; - if (this->name_to_caller_regno (this->ip_register_name(), callerr)) - return callerr; - return -1; -} - -int RemoteRegisterMap::caller_regno_for_sp () { - int callerr; - if (this->name_to_caller_regno (this->sp_register_name(), callerr)) - return callerr; - return -1; -} - -int RemoteRegisterMap::unwind_regno_for_frame_pointer () { - switch (fTarget) { - case UNW_TARGET_X86_64: - return UNW_X86_64_RBP; - case UNW_TARGET_I386: - return UNW_X86_EBP; - default: - ABORT("cannot be reached"); - } - return -1; -} - -int RemoteRegisterMap::unwind_regno_for_stack_pointer () { - switch (fTarget) { - case UNW_TARGET_X86_64: - return UNW_X86_64_RSP; - case UNW_TARGET_I386: - return UNW_X86_ESP; - default: - ABORT("cannot be reached"); - } - return -1; -} - -// This call requires a "arg" which specifies a given process/thread to -// complete unlike the rest of the RegisterMap functions. Ideally this -// would be in the ctor but the register map is created when an -// AddressSpace is created and we don't have a process/thread yet. - -void RemoteRegisterMap::scan_caller_regs (unw_addr_space_t as, void *arg) { - for (int i = 0; i < 256; i++) { - unw_regtype_t type; - char namebuf[16]; - if (fAccessors.reg_info (as, i, &type, namebuf, sizeof (namebuf), arg) == UNW_ESUCCESS - && type != UNW_NOT_A_REG) { - std::vector<RemoteRegisterMap::reg>::iterator j; - for (j = fRegMap.begin(); j != fRegMap.end(); ++j) { - if (strcasecmp (j->name, namebuf) == 0) { - j->caller_regno = i; - // if we haven't picked up a reg type yet it will be UNW_NOT_A_REG via the ctor - if (j->type == UNW_NOT_A_REG) - j->type = type; - if (j->type != type) { - ABORT("Caller and libunwind disagree about type of register"); - break; - } - } - } - // caller knows about a register we don't have a libunwind entry for - if (j == fRegMap.end()) { - RemoteRegisterMap::reg r; - r.name = strdup (namebuf); - r.caller_regno = i; - r.type = type; - fRegMap.push_back(r); - } - } - } -} - - -bool RemoteRegisterMap::name_to_unwind_regno (const char *name, int& unwindr) { - if (name == NULL) - return false; - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (strcasecmp (j->name, name) == 0) { - unwindr = j->unwind_regno; - return true; - } - return false; -} - -bool RemoteRegisterMap::unwind_regno_to_machine_regno (int unwindr, int& machiner) { - if (unwindr == UNW_REG_IP) - unwindr = this->caller_regno_for_ip (); - if (unwindr == UNW_REG_SP) - unwindr = this->caller_regno_for_sp (); - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (j->unwind_regno == unwindr && j->machine_regno != -1) { - machiner = j->machine_regno; - return true; - } - return false; -} -bool RemoteRegisterMap::machine_regno_to_unwind_regno (int machr, int& unwindr) { - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (j->machine_regno == machr && j->unwind_regno != -1) { - unwindr = j->unwind_regno; - return true; - } - return false; -} -bool RemoteRegisterMap::caller_regno_to_unwind_regno (int callerr, int& unwindr) { - if (this->caller_regno_for_ip() == callerr) { - unwindr = UNW_REG_IP; - return true; - } - if (this->caller_regno_for_sp() == callerr) { - unwindr = UNW_REG_SP; - return true; - } - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (j->caller_regno == callerr && j->unwind_regno != -1) { - unwindr = j->unwind_regno; - return true; - } - return false; -} - -const char* RemoteRegisterMap::unwind_regno_to_name (int unwindr) { - for (std::vector<RemoteRegisterMap::reg>::iterator j = fRegMap.begin(); j != fRegMap.end(); ++j) - if (j->unwind_regno == unwindr && j->name != NULL) { - return j->name; - } - return NULL; -} - -int RemoteRegisterMap::byte_size_for_regtype (unw_regtype_t type) { - switch (type) { - case UNW_TARGET_X86_64: - case UNW_TARGET_I386: - if (type == UNW_INTEGER_REG) return fWordSize; - if (type == UNW_FLOATING_POINT_REG) return 8; - if (type == UNW_VECTOR_REG) return 16; - default: - ABORT("cannot be reached"); - } - return -1; -} - - -}; // namespace lldb_private - -#endif // SUPPORT_REMOTE_UNWINDING - -#endif // __REMOTE_REGISTER_MAP_HPP__ - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteUnwindProfile.h b/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteUnwindProfile.h deleted file mode 100644 index a23eb28a8ad..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/RemoteUnwindProfile.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- RemoteUnwindProfile.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __UNWIND_PROFILE_H__ -#define __UNWIND_PROFILE_H__ -#if defined (SUPPORT_REMOTE_UNWINDING) - -#include <vector> - -// The architecture-independent profile of a function's prologue - -namespace lldb_private -{ - -class RemoteUnwindProfile { -public: - RemoteUnwindProfile () : fRegistersSaved(32, 0), fRegSizes(10, 0) { } - struct CFALocation { - int regno; - int offset; - }; - enum RegisterSavedWhere { kRegisterOffsetFromCFA, kRegisterIsCFA }; - enum RegisterType { kGeneralPurposeRegister = 0, kFloatingPointRegister, kVectorRegister }; - struct SavedReg { - int regno; - RegisterSavedWhere location; - int64_t value; - int adj; // Used in kRegisterInRegister e.g. when we recover the caller's rsp by - // taking the contents of rbp and subtracting 16. - RegisterType type; - }; - // In the following maps the key is the address after which this change has effect. - // - // 0 push %rbp - // 1 mov %rsp, %rbp - // 2 sub $16, %rsp - // - // At saved_registers<2> we'll find the record stating that rsp is now stored in rbp. - - std::map<uint64_t, CFALocation> cfa; - std::map<uint64_t, std::vector<SavedReg> > saved_registers; - - struct CFALocation initial_cfa; // At entry to the function - - std::vector<uint8_t> fRegistersSaved; - std::vector<uint8_t> fRegSizes; - SavedReg returnAddress; - uint64_t fStart, fEnd; // low and high pc values for this function. - // END is the addr of the first insn outside the function. - uint64_t fFirstInsnPastPrologue; -}; - -class RemoteProcInfo; - -bool AssemblyParse (RemoteProcInfo *procinfo, unw_accessors_t *accessor, unw_addr_space_t as, uint64_t start, uint64_t end, RemoteUnwindProfile &profile, void *arg); - - -class FuncBounds { - public: - FuncBounds (uint64_t low, uint64_t high) : fStart(low), fEnd(high) { } - uint64_t fStart; - uint64_t fEnd; -}; - -inline bool operator<(const FuncBounds &ap1, const FuncBounds &ap2) { - if (ap1.fStart < ap2.fStart) - return true; - if (ap1.fStart == ap2.fStart && ap1.fEnd < ap2.fEnd) - return true; - return false; -} - - -}; -#endif - - -#endif // __UNWIND_PROFILE_H__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/Unwind-sjlj.c b/lldb/source/Plugins/Process/Utility/libunwind/src/Unwind-sjlj.c deleted file mode 100644 index 584528353a4..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/Unwind-sjlj.c +++ /dev/null @@ -1,466 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- Unwind-sjlj.c -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -/* - * - * Implements setjump-longjump based C++ exceptions - * - */ - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <pthread.h> -#include <setjmp.h> - -#include "unwind.h" -#include "InternalMacros.h" - -// -// ARM uses setjump/longjump based C++ exceptions. -// Other architectures use "zero cost" exceptions. -// -// With SJLJ based exceptions any function that has a catch clause or needs to do any clean up when -// an exception propagates through it, needs to call _Unwind_SjLj_Register() at the start of the -// function and _Unwind_SjLj_Unregister() at the end. The register function is called with the -// address of a block of memory in the function's stack frame. The runtime keeps a linked list -// (stack) of these blocks - one per thread. The calling function also sets the personality -// and lsda fields of the block. -// -// -#if __arm__ - -struct _Unwind_FunctionContext -{ - // next function in stack of handlers - struct _Unwind_FunctionContext* prev; - - // set by calling function before registering to be the landing pad - uintptr_t resumeLocation; - - // set by personality handler to be parameters passed to landing pad function - uintptr_t resumeParameters[4]; - - // set by calling function before registering - __personality_routine personality; // arm offset=24 - uintptr_t lsda; // arm offset=28 - - // variable length array, contains registers to restore - // 0 = r7, 1 = pc, 2 = sp - void* jbuf[]; -}; - - -#if FOR_DYLD - // implemented in dyld - extern struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack(); - extern void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc); -#else - static pthread_key_t sPerThreadTopOfFunctionStack = 0; - static pthread_once_t sOnceFlag = PTHREAD_ONCE_INIT; - - static void __Unwind_SjLj_MakeTopOfFunctionStackKey() - { - pthread_key_create(&sPerThreadTopOfFunctionStack, NULL); - } - - static struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack() - { - pthread_once(&sOnceFlag, __Unwind_SjLj_MakeTopOfFunctionStackKey); - return (struct _Unwind_FunctionContext*)pthread_getspecific(sPerThreadTopOfFunctionStack); - } - - static void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc) - { - pthread_once(&sOnceFlag, __Unwind_SjLj_MakeTopOfFunctionStackKey); - pthread_setspecific(sPerThreadTopOfFunctionStack, fc); - } -#endif - - -// -// Called at start of each function that catches exceptions -// -EXPORT void _Unwind_SjLj_Register(struct _Unwind_FunctionContext* fc) -{ - fc->prev = __Unwind_SjLj_GetTopOfFunctionStack(); - __Unwind_SjLj_SetTopOfFunctionStack(fc); -} - - -// -// Called at end of each function that catches exceptions -// -EXPORT void _Unwind_SjLj_Unregister(struct _Unwind_FunctionContext* fc) -{ - __Unwind_SjLj_SetTopOfFunctionStack(fc->prev); -} - - -static _Unwind_Reason_Code unwind_phase1(struct _Unwind_Exception* exception_object) -{ - _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - DEBUG_PRINT_UNWINDING("unwind_phase1: initial function-context=%p\n", c); - - // walk each frame looking for a place to stop - for (bool handlerNotFound = true; handlerNotFound; c = c->prev) { - - // check for no more frames - if ( c == NULL ) { - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): reached bottom => _URC_END_OF_STACK\n", exception_object); - return _URC_END_OF_STACK; - } - - DEBUG_PRINT_UNWINDING("unwind_phase1: function-context=%p\n", c); - // if there is a personality routine, ask it if it will want to stop at this frame - if ( c->personality != NULL ) { - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, c->personality); - _Unwind_Reason_Code personalityResult = (*c->personality)(1, _UA_SEARCH_PHASE, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)c); - switch ( personalityResult ) { - case _URC_HANDLER_FOUND: - // found a catch clause or locals that need destructing in this frame - // stop search and remember function context - handlerNotFound = false; - exception_object->private_2 = (uintptr_t)c; - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object); - return _URC_NO_REASON; - - case _URC_CONTINUE_UNWIND: - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object); - // continue unwinding - break; - - default: - // something went wrong - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - } - } - return _URC_NO_REASON; -} - - -static _Unwind_Reason_Code unwind_phase2(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); - - // walk each frame until we reach where search phase said to stop - _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - while ( true ) { - DEBUG_PRINT_UNWINDING("unwind_phase2s(ex_ojb=%p): function-context=%p\n", exception_object, c); - - // check for no more frames - if ( c == NULL ) { - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); - return _URC_END_OF_STACK; - } - - // if there is a personality routine, tell it we are unwinding - if ( c->personality != NULL ) { - _Unwind_Action action = _UA_CLEANUP_PHASE; - if ( (uintptr_t)c == exception_object->private_2 ) - action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1 - _Unwind_Reason_Code personalityResult = (*c->personality)(1, action, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)c); - switch ( personalityResult ) { - case _URC_CONTINUE_UNWIND: - // continue unwinding - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object); - if ( (uintptr_t)c == exception_object->private_2 ) { - // phase 1 said we would stop at this frame, but we did not... - ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here"); - } - break; - case _URC_INSTALL_CONTEXT: - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT, will resume at landing pad %p\n", exception_object, c->jbuf[1]); - // personality routine says to transfer control to landing pad - // we may get control back if landing pad calls _Unwind_Resume() - __Unwind_SjLj_SetTopOfFunctionStack(c); - __builtin_longjmp(c->jbuf, 1); - // unw_resume() only returns if there was an error - return _URC_FATAL_PHASE2_ERROR; - default: - // something went wrong - DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - c = c->prev; - } - - // clean up phase did not resume at the frame that the search phase said it would - return _URC_FATAL_PHASE2_ERROR; -} - - -static _Unwind_Reason_Code unwind_phase2_forced(struct _Unwind_Exception* exception_object, - _Unwind_Stop_Fn stop, void* stop_parameter) -{ - // walk each frame until we reach where search phase said to stop - _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - while ( true ) { - - // get next frame (skip over first which is _Unwind_RaiseException) - if ( c == NULL ) { - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); - return _URC_END_OF_STACK; - } - - // call stop function at each frame - _Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE); - _Unwind_Reason_Code stopResult = (*stop)(1, action, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)c, stop_parameter); - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult); - if ( stopResult != _URC_NO_REASON ) { - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // if there is a personality routine, tell it we are unwinding - if ( c->personality != NULL ) { - __personality_routine p = (__personality_routine)c->personality; - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p); - _Unwind_Reason_Code personalityResult = (*p)(1, action, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)c); - switch ( personalityResult ) { - case _URC_CONTINUE_UNWIND: - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object); - // destructors called, continue unwinding - break; - case _URC_INSTALL_CONTEXT: - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object); - // we may get control back if landing pad calls _Unwind_Resume() - __Unwind_SjLj_SetTopOfFunctionStack(c); - __builtin_longjmp(c->jbuf, 1); - break; - default: - // something went wrong - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n", - exception_object, personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - c = c->prev; - } - - // call stop function one last time and tell it we've reached the end of the stack - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object); - _Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK); - (*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)c, stop_parameter); - - // clean up phase did not resume at the frame that the search phase said it would - return _URC_FATAL_PHASE2_ERROR; -} - - -// -// Called by __cxa_throw. Only returns if there is a fatal error -// -EXPORT _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_SjLj_RaiseException(ex_obj=%p)\n", exception_object); - - // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right thing - exception_object->private_1 = 0; - exception_object->private_2 = 0; - - // phase 1: the search phase - _Unwind_Reason_Code phase1 = unwind_phase1(exception_object); - if ( phase1 != _URC_NO_REASON ) - return phase1; - - // phase 2: the clean up phase - return unwind_phase2(exception_object); -} - - -// -// When _Unwind_RaiseException() is in phase2, it hands control -// to the personality function at each frame. The personality -// may force a jump to a landing pad in that function, the landing -// pad code may then call _Unwind_Resume() to continue with the -// unwinding. Note: the call to _Unwind_Resume() is from compiler -// geneated user code. All other _Unwind_* routines are called -// by the C++ runtime __cxa_* routines. -// -// Re-throwing an exception is implemented by having the code call -// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow() -// -EXPORT void _Unwind_SjLj_Resume(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object); - - if ( exception_object->private_1 != 0 ) - unwind_phase2_forced(exception_object, (_Unwind_Stop_Fn)exception_object->private_1, (void*)exception_object->private_2); - else - unwind_phase2(exception_object); - - // clients assume _Unwind_Resume() does not return, so all we can do is abort. - ABORT("_Unwind_SjLj_Resume() can't return"); -} - - -// -// Called by __cxa_rethrow() -// -EXPORT _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", exception_object, exception_object->private_1); - // if this is non-forced and a stopping place was found, then this is a re-throw - // call _Unwind_RaiseException() as if this was a new exception - if ( exception_object->private_1 == 0 ) - _Unwind_SjLj_RaiseException(exception_object); - - // call through to _Unwind_Resume() which distiguishes between forced and regular exceptions - _Unwind_SjLj_Resume(exception_object); - ABORT("__Unwind_SjLj_Resume_or_Rethrow() called _Unwind_SjLj_Resume() which unexpectedly returned"); -} - - -// -// Called by personality handler during phase 2 to get LSDA for current frame -// -EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context) -{ - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - DEBUG_PRINT_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%0lX\n", context, ufc->lsda); - return ufc->lsda; -} - - -// -// Called by personality handler during phase 2 to get register values -// -EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index) -{ - DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d)\n", context, index); - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - return ufc->resumeParameters[index]; -} - - - -// -// Called by personality handler during phase 2 to alter register values -// -EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value) -{ - DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n", context, index, new_value); - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - ufc->resumeParameters[index] = new_value; -} - - -// -// Called by personality handler during phase 2 to get instruction pointer -// -EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context* context) -{ - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - DEBUG_PRINT_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context, ufc->resumeLocation+1); - return ufc->resumeLocation+1; -} - -// -// Called by personality handler during phase 2 to get instruction pointer -// ipBefore is a boolean that says if IP is already adjusted to be the call -// site address. Normally IP is the return address. -// -EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore) -{ - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - *ipBefore = 0; - DEBUG_PRINT_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n", context, ipBefore, ufc->resumeLocation+1); - return ufc->resumeLocation+1; -} - - -// -// Called by personality handler during phase 2 to alter instruction pointer -// -EXPORT void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value) -{ - DEBUG_PRINT_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n", context, new_value); - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - ufc->resumeLocation = new_value-1; -} - -// -// Called by personality handler during phase 2 to find the start of the function -// -EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context) -{ - // Not supported or needed for sjlj based unwinding - DEBUG_PRINT_API("_Unwind_GetRegionStart(context=%p)\n", context); - return 0; -} - -// -// Called by personality handler during phase 2 if a foreign exception is caught -// -EXPORT void _Unwind_DeleteException(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_DeleteException(ex_obj=%p)\n", exception_object); - if ( exception_object->exception_cleanup != NULL ) - (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); -} - - -// -// Called by personality handler during phase 2 to get base address for data relative encodings -// -EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context) -{ - // Not supported or needed for sjlj based unwinding - DEBUG_PRINT_API("_Unwind_GetDataRelBase(context=%p)\n", context); - ABORT("_Unwind_GetDataRelBase() not implemented"); -} - - -// -// Called by personality handler during phase 2 to get base address for text relative encodings -// -EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context) -{ - // Not supported or needed for sjlj based unwinding - DEBUG_PRINT_API("_Unwind_GetTextRelBase(context=%p)\n", context); - ABORT("_Unwind_GetTextRelBase() not implemented"); -} - - - -// -// Called by personality handler to get Call Frame Area for current frame -// -EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context* context) -{ - DEBUG_PRINT_API("_Unwind_GetCFA(context=%p)\n", context); - if ( context != NULL ) { - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context; - // setjmp/longjmp based exceptions don't have a true CFA - // the SP in the jmpbuf is the closest approximation - return (uintptr_t)ufc->jbuf[2]; - } - return 0; -} - - - - - -#endif // __arm__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindCursor.hpp b/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindCursor.hpp deleted file mode 100644 index 5e072b09c99..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindCursor.hpp +++ /dev/null @@ -1,1313 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- UnwindCursor.hpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// -// C++ interface to lower levels of libuwind -// - -#ifndef __UNWINDCURSOR_HPP__ -#define __UNWINDCURSOR_HPP__ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <stdarg.h> - -#include "libunwind.h" - -#include "AddressSpace.hpp" -#include "Registers.hpp" -#include "DwarfInstructions.hpp" - -#include "AssemblyParser.hpp" -#include "AssemblyInstructions.hpp" -#include "RemoteProcInfo.hpp" -#include "ArchDefaultUnwinder.hpp" -#include "RemoteDebuggerDummyUnwinder.hpp" - -#include "CompactUnwinder.hpp" -#include "InternalMacros.h" - -// private keymgr stuff -#define KEYMGR_GCC3_DW2_OBJ_LIST 302 -extern "C" { - extern void _keymgr_set_and_unlock_processwide_ptr(int key, void* ptr); - extern void* _keymgr_get_and_lock_processwide_ptr(int key); -}; - -// undocumented libgcc "struct object" -struct libgcc_object -{ - void* start; - void* unused1; - void* unused2; - void* fde; - unsigned long encoding; - void* fde_end; - libgcc_object* next; -}; - -// undocumented libgcc "struct km_object_info" referenced by KEYMGR_GCC3_DW2_OBJ_LIST -struct libgcc_object_info { - struct libgcc_object* seen_objects; - struct libgcc_object* unseen_objects; - unsigned spare[2]; -}; - - - - -namespace lldb_private { - -#if !FOR_DYLD -template <typename A> -class DwarfFDECache -{ -public: - typedef typename A::pint_t pint_t; - static pint_t findFDE(pint_t mh, pint_t pc); - static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); - static void removeAllIn(pint_t mh); - static void iterateCacheEntries(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)); -private: - static void dyldUnloadHook(const struct mach_header* mh, intptr_t vmaddr_slide); - - struct entry { pint_t mh; pint_t ip_start; pint_t ip_end; pint_t fde; }; - - // these fields are all static to avoid needing an initializer - // there is only one instance of this class per process - static pthread_rwlock_t fgLock; - static bool fgRegisteredForDyldUnloads; - // can't use std::vector<> here because this code must live in libSystem.dylib (which is below libstdc++.dylib) - static entry* fgBuffer; - static entry* fgBufferUsed; - static entry* fgBufferEnd; - static entry fgInitialBuffer[64]; -}; - -template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBuffer = fgInitialBuffer; -template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBufferUsed = fgInitialBuffer; -template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBufferEnd = &fgInitialBuffer[64]; -template <typename A> typename DwarfFDECache<A>::entry DwarfFDECache<A>::fgInitialBuffer[64]; - -template <typename A> -pthread_rwlock_t DwarfFDECache<A>::fgLock = PTHREAD_RWLOCK_INITIALIZER; - -template <typename A> -bool DwarfFDECache<A>::fgRegisteredForDyldUnloads = false; - - -template <typename A> -typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) -{ - pint_t result = NULL; - DEBUG_LOG_NON_ZERO(::pthread_rwlock_rdlock(&fgLock)); - for(entry* p=fgBuffer; p < fgBufferUsed; ++p) { - if ( (mh == p->mh) || (mh == 0) ) { - if ( (p->ip_start <= pc) && (pc < p->ip_end) ) { - result = p->fde; - break; - } - } - } - DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock)); - //fprintf(stderr, "DwarfFDECache::findFDE(mh=0x%llX, pc=0x%llX) => 0x%llX\n", (uint64_t)mh, (uint64_t)pc, (uint64_t)result); - return result; -} - -template <typename A> -void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde) -{ - //fprintf(stderr, "DwarfFDECache::add(mh=0x%llX, ip_start=0x%llX, ip_end=0x%llX, fde=0x%llX) pthread=%p\n", - // (uint64_t)mh, (uint64_t)ip_start, (uint64_t)ip_end, (uint64_t)fde, pthread_self()); - DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock)); - if ( fgBufferUsed >= fgBufferEnd ) { - int oldSize = fgBufferEnd - fgBuffer; - int newSize = oldSize*4; - entry* newBuffer = (entry*)malloc(newSize*sizeof(entry)); // can't use operator new in libSystem.dylib - memcpy(newBuffer, fgBuffer, oldSize*sizeof(entry)); - //fprintf(stderr, "DwarfFDECache::add() growing buffer to %d\n", newSize); - if ( fgBuffer != fgInitialBuffer ) - free(fgBuffer); - fgBuffer = newBuffer; - fgBufferUsed = &newBuffer[oldSize]; - fgBufferEnd = &newBuffer[newSize]; - } - fgBufferUsed->mh = mh; - fgBufferUsed->ip_start = ip_start; - fgBufferUsed->ip_end = ip_end; - fgBufferUsed->fde = fde; - ++fgBufferUsed; -#if !defined (SUPPORT_REMOTE_UNWINDING) - if ( !fgRegisteredForDyldUnloads ) { - _dyld_register_func_for_remove_image(&dyldUnloadHook); - fgRegisteredForDyldUnloads = true; - } -#endif - DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock)); -} - - - -template <typename A> -void DwarfFDECache<A>::removeAllIn(pint_t mh) -{ - DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock)); - entry* d=fgBuffer; - for(const entry* s=fgBuffer; s < fgBufferUsed; ++s) { - if ( s->mh != mh ) { - if ( d != s ) - *d = *s; - ++d; - } - } - fgBufferUsed = d; - DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock)); -} - - -template <typename A> -void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header* mh, intptr_t vmaddr_slide) -{ -#if !defined (SUPPORT_REMOTE_UNWINDING) - removeAllIn((pint_t)mh); -#endif -} - -template <typename A> -void DwarfFDECache<A>::iterateCacheEntries(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) -{ - DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock)); - for(entry* p=fgBuffer; p < fgBufferUsed; ++p) { - (*func)(p->ip_start, p->ip_end, p->fde, p->mh); - } - DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock)); -} -#endif // !FOR_DYLD - - - - -#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) - -template <typename A> -class UnwindSectionHeader { -public: - UnwindSectionHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t version() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, version)); } - uint32_t commonEncodingsArraySectionOffset() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, commonEncodingsArraySectionOffset)); } - uint32_t commonEncodingsArrayCount() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, commonEncodingsArrayCount)); } - uint32_t personalityArraySectionOffset() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, personalityArraySectionOffset)); } - uint32_t personalityArrayCount() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, personalityArrayCount)); } - uint32_t indexSectionOffset() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, indexSectionOffset)); } - uint32_t indexCount() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, indexCount)); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - -template <typename A> -class UnwindSectionIndexArray { -public: - UnwindSectionIndexArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t functionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, functionOffset)); } - uint32_t secondLevelPagesSectionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, secondLevelPagesSectionOffset)); } - uint32_t lsdaIndexArraySectionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, lsdaIndexArraySectionOffset)); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - - -template <typename A> -class UnwindSectionRegularPageHeader { -public: - UnwindSectionRegularPageHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t kind() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_regular_second_level_page_header, kind)); } - uint16_t entryPageOffset() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_regular_second_level_page_header, entryPageOffset)); } - uint16_t entryCount() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_regular_second_level_page_header, entryCount)); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - - -template <typename A> -class UnwindSectionRegularArray { -public: - UnwindSectionRegularArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t functionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_regular_second_level_entry, index, functionOffset)); } - uint32_t encoding(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - - -template <typename A> -class UnwindSectionCompressedPageHeader { -public: - UnwindSectionCompressedPageHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t kind() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_compressed_second_level_page_header, kind)); } - uint16_t entryPageOffset() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, entryPageOffset)); } - uint16_t entryCount() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, entryCount)); } - uint16_t encodingsPageOffset() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, encodingsPageOffset)); } - uint16_t encodingsCount() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, encodingsCount)); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - - -template <typename A> -class UnwindSectionCompressedArray { -public: - UnwindSectionCompressedArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t functionOffset(int index) const INLINE { return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( fAddressSpace.get32(fAddr + index*sizeof(uint32_t)) ); } - uint16_t encodingIndex(int index) const INLINE { return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( fAddressSpace.get32(fAddr + index*sizeof(uint32_t)) ); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - - -template <typename A> -class UnwindSectionLsdaArray { -public: - UnwindSectionLsdaArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {} - - uint32_t functionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, functionOffset)); } - int32_t lsdaOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, lsdaOffset)); } -private: - A& fAddressSpace; - typename A::pint_t fAddr; -}; - - -template <typename A, typename R> -class UnwindCursor -{ -public: - UnwindCursor(unw_context_t* context, A& as); - virtual ~UnwindCursor() {} - virtual bool validReg(int); - virtual uint64_t getReg(int); - virtual int getReg(int, uint64_t*); - virtual int setReg(int, uint64_t); - virtual bool validFloatReg(int); - virtual double getFloatReg(int); - virtual int getFloatReg(int, double*); - virtual int setFloatReg(int, double); - virtual int step(); - virtual void getInfo(unw_proc_info_t*); - virtual void jumpto(); - virtual const char* getRegisterName(int num); - virtual bool isSignalFrame(); - virtual bool getFunctionName(char* buf, size_t bufLen, unw_word_t* offset); - virtual void setInfoBasedOnIPRegister(bool isReturnAddress=false); - - void operator delete(void* p, size_t size) {} - -protected: - typedef typename A::pint_t pint_t; - typedef uint32_t EncodedUnwindInfo; - - virtual bool getInfoFromCompactEncodingSection(pint_t pc, pint_t mh, pint_t unwindSectionStart); - virtual bool getInfoFromDwarfSection(pint_t pc, pint_t mh, pint_t ehSectionStart, uint32_t sectionLength, uint32_t sectionOffsetOfFDE); - - virtual int stepWithDwarfFDE() - { return DwarfInstructions<A,R>::stepWithDwarf(fAddressSpace, this->getReg(UNW_REG_IP), fInfo.unwind_info, fRegisters); } - - virtual int stepWithCompactEncoding() { R dummy; return stepWithCompactEncoding(dummy); } - int stepWithCompactEncoding(Registers_x86_64&) - { return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(fInfo.format, fInfo.start_ip, fAddressSpace, fRegisters); } - int stepWithCompactEncoding(Registers_x86&) - { return CompactUnwinder_x86<A>::stepWithCompactEncoding(fInfo.format, fInfo.start_ip, fAddressSpace, fRegisters); } - -#if FOR_DYLD - #if __ppc__ - virtual bool mustUseDwarf() const { return true; } - #else - virtual bool mustUseDwarf() const { return false; } - #endif -#else - virtual bool mustUseDwarf() const { R dummy; uint32_t offset; return dwarfWithOffset(dummy, offset); } -#endif - - virtual bool dwarfWithOffset(uint32_t& offset) const { R dummy; return dwarfWithOffset(dummy, offset); } - virtual bool dwarfWithOffset(Registers_x86_64&, uint32_t& offset) const { - if ( (fInfo.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF ) { - offset = (fInfo.format & UNWIND_X86_64_DWARF_SECTION_OFFSET); - return true; - } -#if SUPPORT_OLD_BINARIES - if ( (fInfo.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_COMPATIBILITY ) { - if ( (fInfo.format & UNWIND_X86_64_CASE_MASK) == UNWIND_X86_64_UNWIND_REQUIRES_DWARF ) { - offset = 0; - return true; - } - } -#endif - return false; - } - virtual bool dwarfWithOffset(Registers_x86&, uint32_t& offset) const { - if ( (fInfo.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF ) { - offset = (fInfo.format & UNWIND_X86_DWARF_SECTION_OFFSET); - return true; - } -#if SUPPORT_OLD_BINARIES - if ( (fInfo.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_COMPATIBILITY ) { - if ( (fInfo.format & UNWIND_X86_CASE_MASK) == UNWIND_X86_UNWIND_REQUIRES_DWARF ) { - offset = 0; - return true; - } - } -#endif - return false; - } - - virtual compact_unwind_encoding_t dwarfEncoding() const { R dummy; return dwarfEncoding(dummy); } - virtual compact_unwind_encoding_t dwarfEncoding(Registers_x86_64&) const { return UNWIND_X86_64_MODE_DWARF; } - virtual compact_unwind_encoding_t dwarfEncoding(Registers_x86&) const { return UNWIND_X86_MODE_DWARF; } - - unw_proc_info_t fInfo; - R fRegisters; - A& fAddressSpace; - bool fUnwindInfoMissing; - bool fIsSignalFrame; -}; - -typedef UnwindCursor<LocalAddressSpace,Registers_x86> AbstractUnwindCursor; - -template <typename A, typename R> -UnwindCursor<A,R>::UnwindCursor(unw_context_t* context, A& as) - : fRegisters(context), fAddressSpace(as), fUnwindInfoMissing(false), fIsSignalFrame(false) -{ - COMPILE_TIME_ASSERT( sizeof(UnwindCursor<A,R>) < sizeof(unw_cursor_t) ); - - bzero(&fInfo, sizeof(fInfo)); -} - -template <typename A, typename R> -bool UnwindCursor<A,R>::validReg(int regNum) -{ - return fRegisters.validRegister(regNum); -} - -template <typename A, typename R> -uint64_t UnwindCursor<A,R>::getReg(int regNum) -{ - return fRegisters.getRegister(regNum); -} - -template <typename A, typename R> -int UnwindCursor<A,R>::getReg(int regNum, uint64_t *valp) -{ - *valp = fRegisters.getRegister(regNum); - return UNW_ESUCCESS; -} - -template <typename A, typename R> -int UnwindCursor<A,R>::setReg(int regNum, uint64_t value) -{ - fRegisters.setRegister(regNum, value); - return UNW_ESUCCESS; -} - -template <typename A, typename R> -bool UnwindCursor<A,R>::validFloatReg(int regNum) -{ - return fRegisters.validFloatRegister(regNum); -} - -template <typename A, typename R> -double UnwindCursor<A,R>::getFloatReg(int regNum) -{ - return fRegisters.getFloatRegister(regNum); -} - -template <typename A, typename R> -int UnwindCursor<A,R>::getFloatReg(int regNum, double *valp) -{ - *valp = fRegisters.getFloatRegister(regNum); - return UNW_ESUCCESS; -} - -template <typename A, typename R> -int UnwindCursor<A,R>::setFloatReg(int regNum, double value) -{ - fRegisters.setFloatRegister(regNum, value); - return UNW_ESUCCESS; -} - -template <typename A, typename R> -void UnwindCursor<A,R>::jumpto() -{ -#if !defined (SUPPORT_REMOTE_UNWINDING) - fRegisters.jumpto(); -#endif -} - -template <typename A, typename R> -const char* UnwindCursor<A,R>::getRegisterName(int regNum) -{ - return fRegisters.getRegisterName(regNum); -} - -template <typename A, typename R> -bool UnwindCursor<A,R>::isSignalFrame() -{ - return fIsSignalFrame; -} - - -template <typename A, typename R> -bool UnwindCursor<A,R>::getInfoFromDwarfSection(pint_t pc, pint_t mh, pint_t ehSectionStart, uint32_t sectionLength, uint32_t sectionOffsetOfFDE) -{ - typename CFI_Parser<A>::FDE_Info fdeInfo; - typename CFI_Parser<A>::CIE_Info cieInfo; - bool foundFDE = false; - bool foundInCache = false; - // if compact encoding table gave offset into dwarf section, go directly there - if ( sectionOffsetOfFDE != 0 ) { - foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, ehSectionStart+sectionOffsetOfFDE, &fdeInfo, &cieInfo); - } -#if !FOR_DYLD - if ( !foundFDE ) { - // otherwise, search cache of previously found FDEs - pint_t cachedFDE = DwarfFDECache<A>::findFDE(mh, pc); - //fprintf(stderr, "getInfoFromDwarfSection(pc=0x%llX) cachedFDE=0x%llX\n", (uint64_t)pc, (uint64_t)cachedFDE); - if ( cachedFDE != 0 ) { - foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, cachedFDE, &fdeInfo, &cieInfo); - foundInCache = foundFDE; - //fprintf(stderr, "cachedFDE=0x%llX, foundInCache=%d\n", (uint64_t)cachedFDE, foundInCache); - } - } -#endif - if ( !foundFDE ) { - // still not found, do full scan of __eh_frame section - foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, 0, &fdeInfo, &cieInfo); - } - if ( foundFDE ) { - typename CFI_Parser<A>::PrologInfo prolog; - if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) { - // save off parsed FDE info - fInfo.start_ip = fdeInfo.pcStart; - fInfo.end_ip = fdeInfo.pcEnd; - fInfo.lsda = fdeInfo.lsda; - fInfo.handler = cieInfo.personality; - fInfo.gp = prolog.spExtraArgSize; // some frameless functions need SP altered when resuming in function - fInfo.flags = 0; - fInfo.format = dwarfEncoding(); - fInfo.unwind_info = fdeInfo.fdeStart; - fInfo.unwind_info_size = fdeInfo.fdeLength; - fInfo.extra = (unw_word_t)mh; - if ( !foundInCache && (sectionOffsetOfFDE == 0) ) { - // don't add to cache entries the compact encoding table can find quickly - //fprintf(stderr, "getInfoFromDwarfSection(pc=0x%0llX), mh=0x%llX, start_ip=0x%0llX, fde=0x%0llX, personality=0x%0llX\n", - // (uint64_t)pc, (uint64_t)mh, fInfo.start_ip, fInfo.unwind_info, fInfo.handler); -#if !FOR_DYLD - DwarfFDECache<A>::add(mh, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart); -#endif - } - return true; - } - } - //DEBUG_MESSAGE("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc); - return false; -} - -template <typename A, typename R> -bool UnwindCursor<A,R>::getInfoFromCompactEncodingSection(pint_t pc, pint_t mh, pint_t unwindSectionStart) -{ - const bool log = false; - if ( log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", (uint64_t)pc, (uint64_t)mh); - - const UnwindSectionHeader<A> sectionHeader(fAddressSpace, unwindSectionStart); - if ( sectionHeader.version() != UNWIND_SECTION_VERSION ) - return false; - - // do a binary search of top level index to find page with unwind info - uint32_t targetFunctionOffset = pc - mh; - const UnwindSectionIndexArray<A> topIndex(fAddressSpace, unwindSectionStart + sectionHeader.indexSectionOffset()); - uint32_t low = 0; - uint32_t high = sectionHeader.indexCount(); - const uint32_t last_section_header = high - 1; - while ( low < high ) { - uint32_t mid = (low + high)/2; - //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", mid, low, high, topIndex.functionOffset(mid)); - if ( topIndex.functionOffset(mid) <= targetFunctionOffset ) { - if ( (mid == last_section_header) || (topIndex.functionOffset(mid+1) > targetFunctionOffset) ) { - low = mid; - break; - } - else { - low = mid+1; - } - } - else { - high = mid; - } - } - const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low); - const uint32_t firstLevelNextPageFunctionOffset = topIndex.functionOffset(low+1); - const pint_t secondLevelAddr = unwindSectionStart+topIndex.secondLevelPagesSectionOffset(low); - const pint_t lsdaArrayStartAddr = unwindSectionStart+topIndex.lsdaIndexArraySectionOffset(low); - const pint_t lsdaArrayEndAddr = unwindSectionStart+topIndex.lsdaIndexArraySectionOffset(low+1); - if ( log ) fprintf(stderr, "\tfirst level search for result index=%d to secondLevelAddr=0x%llX\n", - low, (uint64_t)secondLevelAddr); - // do a binary search of second level page index - uint32_t encoding = 0; - pint_t funcStart = 0; - pint_t funcEnd = 0; - pint_t lsda = 0; - pint_t personality = 0; - uint32_t pageKind = fAddressSpace.get32(secondLevelAddr); - if ( pageKind == UNWIND_SECOND_LEVEL_REGULAR ) { - // regular page - UnwindSectionRegularPageHeader<A> pageHeader(fAddressSpace, secondLevelAddr); - UnwindSectionRegularArray<A> pageIndex(fAddressSpace, secondLevelAddr + pageHeader.entryPageOffset()); - // binary search looks for entry with e where index[e].offset <= pc < index[e+1].offset - if ( log ) fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in regular page starting at secondLevelAddr=0x%llX\n", - (uint64_t)targetFunctionOffset, (uint64_t)secondLevelAddr); - low = 0; - high = pageHeader.entryCount(); - while ( low < high ) { - uint32_t mid = (low + high)/2; - if ( pageIndex.functionOffset(mid) <= targetFunctionOffset ) { - if ( mid == (uint32_t)(pageHeader.entryCount()-1) ) { - // at end of table - low = mid; - funcEnd = firstLevelNextPageFunctionOffset + mh; - break; - } - else if ( pageIndex.functionOffset(mid+1) > targetFunctionOffset ) { - // next is too big, so we found it - low = mid; - funcEnd = pageIndex.functionOffset(low+1) + mh; - break; - } - else { - low = mid+1; - } - } - else { - high = mid; - } - } - encoding = pageIndex.encoding(low); - funcStart = pageIndex.functionOffset(low) + mh; - if ( pc < funcStart ) { - if ( log ) fprintf(stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart, (uint64_t)funcEnd); - return false; - } - if ( pc > funcEnd ) { - if ( log ) fprintf(stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart, (uint64_t)funcEnd); - return false; - } - } - else if ( pageKind == UNWIND_SECOND_LEVEL_COMPRESSED ) { - // compressed page - UnwindSectionCompressedPageHeader<A> pageHeader(fAddressSpace, secondLevelAddr); - UnwindSectionCompressedArray<A> pageIndex(fAddressSpace, secondLevelAddr + pageHeader.entryPageOffset()); - const uint32_t targetFunctionPageOffset = targetFunctionOffset - firstLevelFunctionOffset; - // binary search looks for entry with e where index[e].offset <= pc < index[e+1].offset - if ( log ) fprintf(stderr, "\tbinary search of compressed page starting at secondLevelAddr=0x%llX\n", (uint64_t)secondLevelAddr); - low = 0; - const uint32_t last_page_header = pageHeader.entryCount() - 1; - high = pageHeader.entryCount(); - while ( low < high ) { - uint32_t mid = (low + high)/2; - if ( pageIndex.functionOffset(mid) <= targetFunctionPageOffset ) { - if ( (mid == last_page_header) || (pageIndex.functionOffset(mid+1) > targetFunctionPageOffset) ) { - low = mid; - break; - } - else { - low = mid+1; - } - } - else { - high = mid; - } - } - funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + mh; - if ( low < last_page_header ) - funcEnd = pageIndex.functionOffset(low+1) + firstLevelFunctionOffset + mh; - else - funcEnd = firstLevelNextPageFunctionOffset + mh; - if ( pc < funcStart ) { - DEBUG_MESSAGE("malformed __unwind_info, pc=0x%llX not in second level compressed unwind table. funcStart=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart); - return false; - } - if ( pc > funcEnd ) { - DEBUG_MESSAGE("malformed __unwind_info, pc=0x%llX not in second level compressed unwind table. funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcEnd); - return false; - } - uint16_t encodingIndex = pageIndex.encodingIndex(low); - if ( encodingIndex < sectionHeader.commonEncodingsArrayCount() ) { - // encoding is in common table in section header - encoding = fAddressSpace.get32(unwindSectionStart+sectionHeader.commonEncodingsArraySectionOffset()+encodingIndex*sizeof(uint32_t)); - } - else { - // encoding is in page specific table - uint16_t pageEncodingIndex = encodingIndex-sectionHeader.commonEncodingsArrayCount(); - encoding = fAddressSpace.get32(secondLevelAddr+pageHeader.encodingsPageOffset()+pageEncodingIndex*sizeof(uint32_t)); - } - } - else { - DEBUG_MESSAGE("malformed __unwind_info at 0x%0llX bad second level page\n", (uint64_t)unwindSectionStart); - return false; - } - - // look up LSDA, if encoding says function has one - if ( encoding & UNWIND_HAS_LSDA ) { - UnwindSectionLsdaArray<A> lsdaIndex(fAddressSpace, lsdaArrayStartAddr); - uint32_t funcStartOffset = funcStart - mh; - low = 0; - high = (lsdaArrayEndAddr-lsdaArrayStartAddr)/sizeof(unwind_info_section_header_lsda_index_entry); - // binary search looks for entry with exact match for functionOffset - if ( log ) fprintf(stderr, "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", funcStartOffset); - while ( low < high ) { - uint32_t mid = (low + high)/2; - if ( lsdaIndex.functionOffset(mid) == funcStartOffset ) { - lsda = lsdaIndex.lsdaOffset(mid) + mh; - break; - } - else if ( lsdaIndex.functionOffset(mid) < funcStartOffset ) { - low = mid+1; - } - else { - high = mid; - } - } - if ( lsda == 0 ) { - DEBUG_MESSAGE("found encoding 0x%08X with HAS_LSDA bit set for pc=0x%0llX, but lsda table has no entry\n", encoding, (uint64_t)pc); - return false; - } - } - - // extact personality routine, if encoding says function has one - uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> (__builtin_ctz(UNWIND_PERSONALITY_MASK)); - if ( personalityIndex != 0 ) { - --personalityIndex; // change 1-based to zero-based index - if ( personalityIndex > sectionHeader.personalityArrayCount() ) { - DEBUG_MESSAGE("found encoding 0x%08X with personality index %d, but personality table has only %d entires\n", - encoding, personalityIndex, sectionHeader.personalityArrayCount()); - return false; - } - int32_t personalityDelta = fAddressSpace.get32(unwindSectionStart+sectionHeader.personalityArraySectionOffset()+personalityIndex*sizeof(uint32_t)); - pint_t personalityPointer = personalityDelta + mh; - personality = fAddressSpace.getP(personalityPointer); - if (log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), personalityDelta=0x%08X, personality=0x%08llX\n", - (uint64_t)pc, personalityDelta, (uint64_t)personality); - } - - if (log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", - (uint64_t)pc, encoding, (uint64_t)lsda, (uint64_t)funcStart); - fInfo.start_ip = funcStart; - fInfo.end_ip = funcEnd; - fInfo.lsda = lsda; - fInfo.handler = personality; - fInfo.gp = 0; - fInfo.flags = 0; - fInfo.format = encoding; - fInfo.unwind_info = 0; - fInfo.unwind_info_size = 0; - fInfo.extra = mh; - return true; -} - -template <typename A, typename R> -void UnwindCursor<A,R>::setInfoBasedOnIPRegister(bool isReturnAddress) -{ - pint_t pc = this->getReg(UNW_REG_IP); - - // if the last line of a function is a "throw" the compile sometimes - // emits no instructions after the call to __cxa_throw. This means - // the return address is actually the start of the next function. - // To disambiguate this, back up the pc when we know it is a return - // address. - if ( isReturnAddress ) - --pc; - - // ask address space object to find unwind sections for this pc - pint_t mh; - pint_t dwarfStart; - pint_t dwarfLength; - pint_t compactStart; - if ( fAddressSpace.findUnwindSections(pc, mh, dwarfStart, dwarfLength, compactStart) ) { - // if there is a compact unwind encoding table, look there first - if ( compactStart != 0 ) { - if ( this->getInfoFromCompactEncodingSection(pc, mh, compactStart) ) { -#if !FOR_DYLD - // found info in table, done unless encoding says to use dwarf - uint32_t offsetInDwarfSection; - if ( (dwarfStart != 0) && dwarfWithOffset(offsetInDwarfSection) ) { - if ( this->getInfoFromDwarfSection(pc, mh, dwarfStart, dwarfLength, offsetInDwarfSection) ) { - // found info in dwarf, done - return; - } - } -#endif - // if unwind table has entry, but entry says there is no unwind info, note that - if ( fInfo.format == 0 ) - fUnwindInfoMissing = true; - - // old compact encoding - if ( !mustUseDwarf() ) { - return; - } - } - } -#if !FOR_DYLD || __ppc__ - // if there is dwarf unwind info, look there next - if ( dwarfStart != 0 ) { - if ( this->getInfoFromDwarfSection(pc, mh, dwarfStart, dwarfLength, 0) ) { - // found info in dwarf, done - return; - } - } -#endif - } - -#if !FOR_DYLD - // the PC is not in code loaded by dyld, look through __register_frame() registered FDEs - pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc); - if ( cachedFDE != 0 ) { - typename CFI_Parser<A>::FDE_Info fdeInfo; - typename CFI_Parser<A>::CIE_Info cieInfo; - const char* msg = CFI_Parser<A>::decodeFDE(fAddressSpace, cachedFDE, &fdeInfo, &cieInfo); - if ( msg == NULL ) { - typename CFI_Parser<A>::PrologInfo prolog; - if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) { - // save off parsed FDE info - fInfo.start_ip = fdeInfo.pcStart; - fInfo.end_ip = fdeInfo.pcEnd; - fInfo.lsda = fdeInfo.lsda; - fInfo.handler = cieInfo.personality; - fInfo.gp = prolog.spExtraArgSize; // some frameless functions need SP altered when resuming in function - fInfo.flags = 0; - fInfo.format = dwarfEncoding(); - fInfo.unwind_info = fdeInfo.fdeStart; - fInfo.unwind_info_size = fdeInfo.fdeLength; - fInfo.extra = 0; - return; - } - } - } - -#if !defined (SUPPORT_REMOTE_UNWINDING) - // lastly check for old style keymgr registration of dynamically generated FDEs - - // acquire exclusive access to libgcc_object_info - libgcc_object_info* head = (libgcc_object_info*)_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); - if ( head != NULL ) { - // look at each FDE in keymgr - for (libgcc_object* ob = head->unseen_objects; ob != NULL; ob = ob->next) { - typename CFI_Parser<A>::FDE_Info fdeInfo; - typename CFI_Parser<A>::CIE_Info cieInfo; - const char* msg = CFI_Parser<A>::decodeFDE(fAddressSpace, (pint_t)ob->fde, &fdeInfo, &cieInfo); - if ( msg == NULL ) { - // see if this FDE is for a function that includes the pc we are looking for - if ( (fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd) ) { - typename CFI_Parser<A>::PrologInfo prolog; - if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) { - // save off parsed FDE info - fInfo.start_ip = fdeInfo.pcStart; - fInfo.end_ip = fdeInfo.pcEnd; - fInfo.lsda = fdeInfo.lsda; - fInfo.handler = cieInfo.personality; - fInfo.gp = prolog.spExtraArgSize; // some frameless functions need SP altered when resuming in function - fInfo.flags = 0; - fInfo.format = dwarfEncoding(); - fInfo.unwind_info = fdeInfo.fdeStart; - fInfo.unwind_info_size = fdeInfo.fdeLength; - fInfo.extra = 0; - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head); - return; - } - } - } - } - } - // release libgcc_object_info - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head); -#endif // !SUPPORT_REMOTE_UNWINDING - -#endif // !FOR_DYLD - - // no unwind info, flag that we can't reliable unwind - fUnwindInfoMissing = true; -} - - -template <typename A, typename R> -int UnwindCursor<A,R>::step() -{ - // bottom of stack is defined as when no more unwind info - if ( fUnwindInfoMissing ) - return UNW_STEP_END; - - // apply unwinding to register set - int result; - if ( this->mustUseDwarf() ) - result = this->stepWithDwarfFDE(); - else - result = this->stepWithCompactEncoding(); - - // update info based on new PC - if ( result == UNW_STEP_SUCCESS ) { - this->setInfoBasedOnIPRegister(true); - if ( fUnwindInfoMissing ) - return UNW_STEP_END; - } - - return result; -} - - -template <typename A, typename R> -void UnwindCursor<A,R>::getInfo(unw_proc_info_t* info) -{ - *info = fInfo; -} - - -template <typename A, typename R> -bool UnwindCursor<A,R>::getFunctionName(char* buf, size_t bufLen, unw_word_t* offset) -{ - return fAddressSpace.findFunctionName(this->getReg(UNW_REG_IP), buf, bufLen, offset); -} - -#if defined (SUPPORT_REMOTE_UNWINDING) -template <typename A, typename R> -class RemoteUnwindCursor : UnwindCursor<A,R> -{ -public: - using UnwindCursor<A,R>::getReg; - using UnwindCursor<A,R>::getFloatReg; - - typedef typename A::pint_t pint_t; - RemoteUnwindCursor(A& as, unw_context_t* regs, void* arg); - virtual bool validReg(int); - virtual int getReg(int r, uint64_t*); - virtual int setReg(int, uint64_t); - virtual bool validFloatReg(int); - virtual int getFloatReg(int, double*); - virtual int setFloatReg(int, double); - virtual const char* getRegisterName(int); - virtual int step(); - virtual void setRemoteContext(void*); - virtual bool remoteUnwindCursor () const {return this->fAddressSpace.getRemoteProcInfo() != NULL; } - virtual int endOfPrologueInsns(unw_word_t, unw_word_t, unw_word_t*); - void operator delete(void* p, size_t size) {} -private: - virtual bool caller_regno_to_unwind_regno (int, int&); - - bool fIsLeafFrame; - bool fIsFirstFrame; - void* fArg; -}; - -typedef RemoteUnwindCursor<LocalAddressSpace,Registers_x86_64> AbstractRemoteUnwindCursor; - -template <typename A, typename R> -RemoteUnwindCursor<A,R>::RemoteUnwindCursor(A& as, unw_context_t* regs, void* arg) - : UnwindCursor<A,R>::UnwindCursor(regs, as), fIsLeafFrame(false), fIsFirstFrame (false), fArg(arg) -{ - COMPILE_TIME_ASSERT( sizeof(RemoteUnwindCursor<A,R>) < sizeof(unw_cursor_t) ); -} - -template <typename A, typename R> -bool RemoteUnwindCursor<A,R>::validReg(int r) -{ - int unwind_regno; - if (!caller_regno_to_unwind_regno(r, unwind_regno)) - return false; - return UnwindCursor<A,R>::fRegisters.validRegister(unwind_regno); -} - -template <typename A, typename R> -int RemoteUnwindCursor<A,R>::getReg(int regNum, uint64_t *valp) -{ - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo (); - if (procinfo == NULL) { - ABORT("getRemoteReg called with a local unwind, use getReg instead."); - } - - RemoteRegisterMap *regmap = procinfo->getRegisterMap (); - int unwind_regno; - if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false) - return UNW_EBADREG; - regNum = unwind_regno; - - // we always return nonvolatile registers. If we have the entire register state available - // for this frame then we can return any register requested. - if (regmap->nonvolatile_reg_p (regNum) == true || fIsLeafFrame == true) { - return this->UnwindCursor<A,R>::getReg (unwind_regno, valp); - } - return UNW_EREGUNAVAILABLE; -} - -template <typename A, typename R> -int RemoteUnwindCursor<A,R>::setReg(int regNum, uint64_t val) -{ - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo (); - if (procinfo == NULL) { - ABORT("setRemoteReg called with a local unwind, use setReg instead."); - } - - RemoteRegisterMap *regmap = procinfo->getRegisterMap (); - int unwind_regno; - if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false) - return UNW_EBADREG; - regNum = unwind_regno; - - // Only allow the registers to be set if the unwind cursor is pointing to the - // first frame. We need to track where registers were retrieved from in memory - // in every other frame. Until then, we prohibit register setting in all but - // the first frame. - if (fIsFirstFrame) { - return this->setReg(unwind_regno, val); - } - return UNW_EREGUNAVAILABLE; -} - -template <typename A, typename R> -bool RemoteUnwindCursor<A,R>::validFloatReg(int r) -{ - int unwind_regno; - if (!caller_regno_to_unwind_regno(r, unwind_regno)) - return false; - return UnwindCursor<A,R>::fRegisters.validFloatRegister(unwind_regno); -} - -template <typename A, typename R> -int RemoteUnwindCursor<A,R>::getFloatReg(int regNum, double *valp) -{ - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo (); - if (procinfo == NULL) { - ABORT("getRemoteReg called with a local unwind, use getReg instead."); - } - - RemoteRegisterMap *regmap = procinfo->getRegisterMap (); - int unwind_regno; - if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false) - return UNW_EBADREG; - regNum = unwind_regno; - - // we always return nonvolatile registers. If we have the entire register state available - // for this frame then we can return any register requested. - if (regmap->nonvolatile_reg_p (regNum) == true || fIsLeafFrame == true) { - return this->UnwindCursor<A,R>::getFloatReg (unwind_regno, valp); - } - return UNW_EREGUNAVAILABLE; -} - -template <typename A, typename R> -int RemoteUnwindCursor<A,R>::setFloatReg(int regNum, double val) -{ - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo (); - if (procinfo == NULL) { - ABORT("setRemoteReg called with a local unwind, use setReg instead."); - } - - RemoteRegisterMap *regmap = procinfo->getRegisterMap (); - int unwind_regno; - if (regmap->caller_regno_to_unwind_regno (regNum, unwind_regno) == false) - return UNW_EBADREG; - regNum = unwind_regno; - - // Only allow the registers to be set if the unwind cursor is pointing to the - // first frame. We need to track where registers were retrieved from in memory - // in every other frame. Until then, we prohibit register setting in all but - // the first frame. - if (fIsFirstFrame) { - return this->setFloatReg(unwind_regno, val); - } - return UNW_EREGUNAVAILABLE; -} - - -template <typename A, typename R> -const char* RemoteUnwindCursor<A,R>::getRegisterName(int r) -{ - int t; - if (!this->caller_regno_to_unwind_regno(r, t)) - return NULL; - r = t; - return this->UnwindCursor<A,R>::getRegisterName(r); -} - -template <typename A, typename R> -int RemoteUnwindCursor<A,R>::step() -{ - pint_t pc = this->UnwindCursor<A,R>::getReg(UNW_REG_IP); - pint_t sp = this->UnwindCursor<A,R>::getReg(UNW_REG_SP); - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo(); - bool frame_is_sigtramp = false; - bool frame_is_inferior_function_call_dummy = false; - - if (procinfo == NULL) { - ABORT("stepRemote called with local unwind, use step() instead."); - return UNW_EUNSPEC; - } - struct timeval *step_remote = procinfo->timestamp_start(); - procinfo->logVerbose ("stepRemote stepping out of frame with pc value 0x%llx", pc); - - // We'll be off of the first frame once we finish this step. - fIsFirstFrame = false; - - if (UnwindCursor<A,R>::fAddressSpace.accessors() - && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_sigtramp != NULL - && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_sigtramp (procinfo->wrap(), pc, fArg)) { - frame_is_sigtramp = true; - } - if (UnwindCursor<A,R>::fAddressSpace.accessors() - && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_inferior_function_call != NULL - && UnwindCursor<A,R>::fAddressSpace.accessors()->proc_is_inferior_function_call (procinfo->wrap(), pc, sp, fArg)) { - frame_is_inferior_function_call_dummy = true; - } - - // If the function we're unwinding can't be a leaf function, - // use the eh_frame or compact unwind info if possible. - // The caller should pass couldBeLeafFunc == 0 on the first step of a new context - // but we can't trust them in that. - - if ((fIsLeafFrame == false && frame_is_inferior_function_call_dummy == false) - || frame_is_sigtramp) { - R saved_registers(UnwindCursor<A,R>::fRegisters); - this->setInfoBasedOnIPRegister(true); - // bottom of stack is defined as when no more unwind info - if ( !UnwindCursor<A,R>::fUnwindInfoMissing ) { - int result; - const char *method; - if ( this->mustUseDwarf() ) { - result = this->stepWithDwarfFDE(); - method = "dwarf"; - } - else { - result = this->stepWithCompactEncoding(); - method = "compact unwind"; - } - if ( result == UNW_STEP_SUCCESS ) { - procinfo->logInfo ("Stepped via %s", method); - procinfo->timestamp_stop (step_remote, "stepRemote"); - if (frame_is_sigtramp) - fIsLeafFrame = true; - return result; - } - } - UnwindCursor<A,R>::fRegisters = saved_registers; - } - - if (frame_is_sigtramp || frame_is_inferior_function_call_dummy) - fIsLeafFrame = true; // this will be true once we complete this stepRemote() - else - fIsLeafFrame = false; - - if (frame_is_inferior_function_call_dummy) { - if (stepOutOfDebuggerDummyFrame (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, procinfo, pc, sp, fArg) == UNW_STEP_SUCCESS) { - procinfo->logInfo ("Stepped via stepOutOfDebuggerDummyFrame"); - procinfo->timestamp_stop (step_remote, "stepRemote"); - return UNW_STEP_SUCCESS; - } - } - - // If we haven't already seen this function we'll need to get the function bounds via - // eh frame info (if available) - it's the most accurate function bounds in a - // stripped binary. After that we'll ask the driver program (via the get_proc_bounds accessor). - - if (procinfo->haveProfile (pc) == false) { - - uint64_t text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, mh; - uint64_t start_addr, end_addr; - if (pc == 0) { - int ret = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc); - procinfo->logInfo ("Stepped via stepByArchitectureDefault"); - procinfo->timestamp_stop (step_remote, "stepRemote"); - return ret; - } - - // If the address is not contained in any image's address range either we've walked off - // the stack into random memory or we're backtracing through jit'ed code on the heap. - // Let's assume the latter and follow the architecture's default stack walking scheme. - - if (!procinfo->getImageAddresses (pc, mh, text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, fArg)) { - int ret = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc); - procinfo->logInfo ("Stepped via stepByArchitectureDefault"); - procinfo->timestamp_stop (step_remote, "stepRemote"); - return ret; - } - if (procinfo->haveFuncBounds (mh) == false) { - struct timeval *get_func_bounds = procinfo->timestamp_start(); - std::vector<FuncBounds> func_bounds; - // CFI entries are usually around 38 bytes but under-estimate a bit - // because we're not distinguishing between CIEs and FDEs. - if (eh_frame_len > 0) - func_bounds.reserve (eh_frame_len / 16); - if (procinfo->getCachingPolicy() != UNW_CACHE_NONE) { - // cache the entire eh frame section - we'll need to read the whole - // thing anyway so we might as well save it. - uint8_t *eh_buf = (uint8_t *)malloc (eh_frame_len); - if (UnwindCursor<A,R>::fAddressSpace.getBytes (eh_frame_start, eh_frame_len, eh_buf) == 0) - { - free (eh_buf); - return UNW_EUNSPEC; - } - RemoteMemoryBlob *ehmem = new RemoteMemoryBlob(eh_buf, free, eh_frame_start, eh_frame_len, mh, NULL); - if (procinfo->addMemBlob (ehmem) == false) - delete ehmem; - } - - if (CFI_Parser<A>::functionFuncBoundsViaFDE(UnwindCursor<A,R>::fAddressSpace, eh_frame_start, eh_frame_len, func_bounds)) { - procinfo->addFuncBounds(mh, func_bounds); - procinfo->logVerbose ("Added %d function bounds", (int) func_bounds.size()); - procinfo->timestamp_stop (get_func_bounds, "getting function bounds from EH frame FDEs"); - } - } - if (procinfo->findStartAddr (pc, start_addr, end_addr)) { - // If end_addr is 0, we might be looking at the final function in this binary image - if (start_addr != 0 && end_addr == 0) - end_addr = text_end; - procinfo->logVerbose ("Got function bounds from func bounds vector, 0x%llx-0x%llx", start_addr, end_addr); - } else { - if (UnwindCursor<A,R>::fAddressSpace.accessors()->get_proc_bounds (procinfo->wrap(), pc, &start_addr, &end_addr, fArg) != UNW_ESUCCESS) { - int ret = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc); - procinfo->logInfo ("Stepped via stepByArchitectureDefault"); - procinfo->timestamp_stop (step_remote, "stepRemote"); - return ret; - } - else { - procinfo->logVerbose ("Got function bounds from get_proc_bounds callback, 0x%llx-0x%llx", start_addr, end_addr); - } - } - if (start_addr != 0) { - procinfo->addProfile (UnwindCursor<A,R>::fAddressSpace.accessors(), UnwindCursor<A,R>::fAddressSpace.wrap(), start_addr, end_addr, fArg); - } - } - - RemoteUnwindProfile *profile = procinfo->findProfile (pc); - if (profile == NULL) - return UNW_ENOINFO; - - int retval = stepWithAssembly (UnwindCursor<A,R>::fAddressSpace, pc, profile, UnwindCursor<A,R>::fRegisters); - if (retval >= 0) { - procinfo->logInfo ("Stepped via stepWithAssembly"); - procinfo->timestamp_stop (step_remote, "stepRemote"); - return retval; - } - - retval = stepByArchitectureDefault (UnwindCursor<A,R>::fAddressSpace, UnwindCursor<A,R>::fRegisters, pc); - procinfo->logInfo ("Stepped via stepByArchitectureDefault"); - procinfo->timestamp_stop (step_remote, "stepRemote"); - return retval; -} - -template <typename A, typename R> -void RemoteUnwindCursor<A,R>::setRemoteContext(void *arg) -{ - // fill in the register state for the currently executing frame. - getRemoteContext (UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo(), UnwindCursor<A,R>::fRegisters, arg); - - // Flag that this unwind cursor is pointing at the zeroth frame. We don't - // want to use compact unwind info / eh frame info to unwind out of this - // frame. - - fIsLeafFrame = true; - fIsFirstFrame = true; -} - -// This needs to be done in many of the functions and in libuwind.cxx in one or two -// places so I'm defining a convenience method. -template <typename A, typename R> -bool RemoteUnwindCursor<A,R>::caller_regno_to_unwind_regno (int caller_regno, int& unwind_regno) -{ - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo (); - if (procinfo == NULL) { - unwind_regno = caller_regno; - return true; - } - if (procinfo->getRegisterMap()->caller_regno_to_unwind_regno (caller_regno, unwind_regno)) - return true; - return false; -} - -template <typename A, typename R> -int RemoteUnwindCursor<A,R>::endOfPrologueInsns (unw_word_t start, unw_word_t end, unw_word_t *endofprologue) -{ - RemoteProcInfo *procinfo = UnwindCursor<A,R>::fAddressSpace.getRemoteProcInfo(); - *endofprologue = start; - if (procinfo == NULL) { - ABORT("findEndOfPrologueSetup called with local unwind."); - return UNW_EUNSPEC; - } - if (procinfo->haveProfile (start) == false) { - uint64_t text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, mh; - if (!procinfo->getImageAddresses (start, mh, text_start, text_end, eh_frame_start, eh_frame_len, compact_unwind_start, fArg)) - return UNW_EUNSPEC; - if (end == 0) { - if (procinfo->haveFuncBounds (mh) == false) { - std::vector<FuncBounds> func_bounds; - // CFI entries are usually around 38 bytes but under-estimate a bit - // because we're not distinguishing between CIEs and FDEs. - if (eh_frame_len > 0) - func_bounds.reserve (eh_frame_len / 16); - if (procinfo->getCachingPolicy() != UNW_CACHE_NONE) { - // cache the entire eh frame section - we'll need to read the whole - // thing anyway so we might as well save it. - uint8_t *eh_buf = (uint8_t *)malloc (eh_frame_len); - if (UnwindCursor<A,R>::fAddressSpace.getBytes (eh_frame_start, eh_frame_len, eh_buf) == 0) - { - free (eh_buf); - return UNW_EUNSPEC; - } - RemoteMemoryBlob *ehmem = new RemoteMemoryBlob(eh_buf, free, eh_frame_start, eh_frame_len, mh, NULL); - if (procinfo->addMemBlob (ehmem) == false) - delete ehmem; - } - if (CFI_Parser<A>::functionFuncBoundsViaFDE(UnwindCursor<A,R>::fAddressSpace, eh_frame_start, eh_frame_len, func_bounds)) { - procinfo->addFuncBounds(mh, func_bounds); - } - } - uint64_t bounded_start, bounded_end; - if (procinfo->findStartAddr (start, bounded_start, bounded_end)) { - end = bounded_end; - } else { - if (UnwindCursor<A,R>::fAddressSpace.accessors()->get_proc_bounds (procinfo->wrap(), start, &bounded_start, &bounded_end, fArg) != UNW_ESUCCESS) - if (bounded_end != 0) - end = bounded_end; - } - } - if (procinfo->addProfile (UnwindCursor<A,R>::fAddressSpace.accessors(), UnwindCursor<A,R>::fAddressSpace.wrap(), start, end, fArg) == false) - return UNW_EUNSPEC; - } - RemoteUnwindProfile *profile = procinfo->findProfile (start); - if (profile == NULL) - return UNW_ENOINFO; - *endofprologue = profile->fFirstInsnPastPrologue; - return UNW_ESUCCESS; -} - -#endif // SUPPORT_REMOTE_UNWINDING - - -}; // namespace lldb_private - - -#endif // __UNWINDCURSOR_HPP__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1-gcc-ext.c b/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1-gcc-ext.c deleted file mode 100644 index 7103c719ba2..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1-gcc-ext.c +++ /dev/null @@ -1,282 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- UnwindLevel1-gcc-ext.c ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -/* - * Implements gcc extensions to the C++ ABI Exception Handling Level 1 as documented at: - * <http://www.codesourcery.com/cxx-abi/abi-eh.html> - * using libunwind - * - */ - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> - -#include "libunwind.h" -#include "unwind.h" -#include "libunwind_priv.h" -#include "InternalMacros.h" - - -#if __ppc__ || __i386__ || __x86_64__ - -// -// Called by __cxa_rethrow() -// -EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", exception_object, exception_object->private_1); - // if this is non-forced and a stopping place was found, then this is a re-throw - // call _Unwind_RaiseException() as if this was a new exception - if ( exception_object->private_1 == 0 ) - _Unwind_RaiseException(exception_object); - - // call through to _Unwind_Resume() which distiguishes between forced and regular exceptions - _Unwind_Resume(exception_object); - ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException() which unexpectedly returned"); -} - - - -// -// Called by personality handler during phase 2 to get base address for data relative encodings -// -EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context) -{ - DEBUG_PRINT_API("_Unwind_GetDataRelBase(context=%p)\n", context); - ABORT("_Unwind_GetDataRelBase() not implemented"); -} - -// -// Called by personality handler during phase 2 to get base address for text relative encodings -// -EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context) -{ - DEBUG_PRINT_API("_Unwind_GetTextRelBase(context=%p)\n", context); - ABORT("_Unwind_GetTextRelBase() not implemented"); -} - - - -// -// Scans unwind information to find the function that contains the -// specified code address "pc". -// -EXPORT void* _Unwind_FindEnclosingFunction(void* pc) -{ - DEBUG_PRINT_API("_Unwind_FindEnclosingFunction(pc=%p)\n", pc); - ABORT("_Unwind_FindEnclosingFunction() not implemented"); -} - - -// -// Walk every frame and call trace function at each one. If trace function -// returns anything other than _URC_NO_REASON, then walk is terminated. -// -EXPORT _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void* ref) -{ - unw_cursor_t cursor; - unw_context_t uc; - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - - DEBUG_PRINT_API("_Unwind_Backtrace(callback=%p)\n", callback); - - // walk each frame - while ( true ) { - - // ask libuwind to get next frame (skip over first frame which is _Unwind_Backtrace()) - if ( unw_step(&cursor) <= 0 ) { - DEBUG_PRINT_UNWINDING(" _backtrace: ended because cursor reached bottom of stack, returning %d\n", _URC_END_OF_STACK); - return _URC_END_OF_STACK; - } - - // debugging - if ( DEBUG_PRINT_UNWINDING_TEST ) { - char functionName[512]; - unw_proc_info_t frameInfo; - unw_word_t offset; - unw_get_proc_name(&cursor, functionName, 512, &offset); - unw_get_proc_info(&cursor, &frameInfo); - DEBUG_PRINT_UNWINDING(" _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n", - frameInfo.start_ip, functionName, frameInfo.lsda, &cursor); - } - - // call trace function with this frame - _Unwind_Reason_Code result = (*callback)((struct _Unwind_Context*)(&cursor), ref); - if ( result != _URC_NO_REASON ) { - DEBUG_PRINT_UNWINDING(" _backtrace: ended because callback returned %d\n", result); - return result; - } - } -} - - -// -// Find dwarf unwind info for an address 'pc' in some function. -// -EXPORT const void* _Unwind_Find_FDE(const void* pc, struct dwarf_eh_bases* bases) -{ - // This is slow, but works. - // We create an unwind cursor then alter the IP to be pc - unw_cursor_t cursor; - unw_context_t uc; - unw_proc_info_t info; - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long)pc); - unw_get_proc_info(&cursor, &info); - bases->tbase = info.extra; - bases->dbase = 0; // dbase not used on Mac OS X - bases->func = info.start_ip; - DEBUG_PRINT_API("_Unwind_Find_FDE(pc=%p) => %p\n", pc, (void*)(long)info.unwind_info); - return (void*)(long)info.unwind_info; -} - - - -EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context* context) -{ - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_word_t result; - unw_get_reg(cursor, UNW_REG_SP, &result); - DEBUG_PRINT_API("_Unwind_GetCFA(context=%p) => 0x%llX\n", context, (uint64_t)result); - return result; -} - - -// -// Called by personality handler during phase 2 to get instruction pointer. -// ipBefore is a boolean that says if IP is already adjusted to be the call -// site address. Normally IP is the return address. -// -EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore) -{ - DEBUG_PRINT_API("_Unwind_GetIPInfo(context=%p)\n", context); - *ipBefore = 0; - return _Unwind_GetIP(context); -} - - -// -// Called by programs with dynamic code generators that want -// to register a dynamically generated FDE. -// This function has existed on Mac OS X since 10.4, but -// never worked before. -// -EXPORT void __register_frame(const void* fde) -{ - DEBUG_PRINT_API("__register_frame(%p)\n", fde); - _unw_add_dynamic_fde((unw_word_t)(uintptr_t)fde); -} - - -// -// Called by programs with dynamic code generators that want -// to unregister a dynamically generated FDE. -// This function has existed on Mac OS X since 10.4, but -// never worked before. -// -EXPORT void __deregister_frame(const void* fde) -{ - DEBUG_PRINT_API("__deregister_frame(%p)\n", fde); - _unw_remove_dynamic_fde((unw_word_t)(uintptr_t)fde); -} - - - -// -// The following register/deregister functions are gcc extensions. -// They have existed on Mac OS X, but have never worked because Mac OS X -// before 10.6 used keymgr to track known FDEs, but these functions -// never got updated to use keymgr. -// For now, we implement these as do-nothing functions to keep any existing -// applications working. We also add the not in 10.6 symbol so that nwe -// application won't be able to use them. -// - -EXPORT void __register_frame_info_bases(const void* fde, void* ob, void* tb, void* db) -{ - DEBUG_PRINT_API("__register_frame_info_bases(%p,%p, %p, %p)\n", fde, ob, tb, db); - // do nothing, this function never worked in Mac OS X -} - -EXPORT void __register_frame_info(const void* fde, void* ob) -{ - DEBUG_PRINT_API("__register_frame_info(%p, %p)\n", fde, ob); - // do nothing, this function never worked in Mac OS X -} - - -EXPORT void __register_frame_info_table_bases(const void* fde, void* ob, void* tb, void* db) -{ - DEBUG_PRINT_API("__register_frame_info_table_bases(%p,%p, %p, %p)\n", fde, ob, tb, db); - // do nothing, this function never worked in Mac OS X -} - -EXPORT void __register_frame_info_table(const void* fde, void* ob) -{ - DEBUG_PRINT_API("__register_frame_info_table(%p, %p)\n", fde, ob); - // do nothing, this function never worked in Mac OS X -} - -EXPORT void __register_frame_table(const void* fde) -{ - DEBUG_PRINT_API("__register_frame_table(%p)\n", fde); - // do nothing, this function never worked in Mac OS X -} - -EXPORT void* __deregister_frame_info(const void* fde) -{ - DEBUG_PRINT_API("__deregister_frame_info(%p)\n", fde); - // do nothing, this function never worked in Mac OS X - return NULL; -} - -EXPORT void* __deregister_frame_info_bases(const void* fde) -{ - DEBUG_PRINT_API("__deregister_frame_info_bases(%p)\n", fde); - // do nothing, this function never worked in Mac OS X - return NULL; -} - - - - -// -// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in earlier versions -// -NOT_HERE_BEFORE_10_6(_Unwind_Backtrace) -NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction) -NOT_HERE_BEFORE_10_6(_Unwind_GetCFA) -NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase) -NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase) -NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow) -NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo) - -NOT_HERE_BEFORE_10_6(__register_frame) -NOT_HERE_BEFORE_10_6(__deregister_frame) - - -// -// symbols in libSystem.dylib for compatibility, but we don't want any new code using them -// -NEVER_HERE(__register_frame_info_bases) -NEVER_HERE(__register_frame_info) -NEVER_HERE(__register_frame_info_table_bases) -NEVER_HERE(__register_frame_info_table) -NEVER_HERE(__register_frame_table) -NEVER_HERE(__deregister_frame_info) -NEVER_HERE(__deregister_frame_info_bases) - - -#endif // __ppc__ || __i386__ || __x86_64__ - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1.c b/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1.c deleted file mode 100644 index 3aa2b6f552c..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/UnwindLevel1.c +++ /dev/null @@ -1,443 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- UnwindLevel1.c ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -/* - * - * Implements C++ ABI Exception Handling Level 1 as documented at: - * <http://www.codesourcery.com/cxx-abi/abi-eh.html> - * using libunwind - * - */ - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "libunwind.h" -#include "unwind.h" -#include "InternalMacros.h" - -#if __ppc__ || __i386__ || __x86_64__ - -static _Unwind_Reason_Code unwind_phase1(unw_context_t* uc, struct _Unwind_Exception* exception_object) -{ - unw_cursor_t cursor1; - unw_init_local(&cursor1, uc); - - // walk each frame looking for a place to stop - for (bool handlerNotFound = true; handlerNotFound; ) { - - // ask libuwind to get next frame (skip over first which is _Unwind_RaiseException) - int stepResult = unw_step(&cursor1); - if ( stepResult == 0 ) { - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); - return _URC_END_OF_STACK; - } - else if ( stepResult < 0 ) { - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - - // see if frame has code to run (has personality routine) - unw_proc_info_t frameInfo; - unw_word_t sp; - if ( unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS ) { - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - - // debugging - if ( DEBUG_PRINT_UNWINDING_TEST ) { - char functionName[512]; - unw_word_t offset; - if ( (unw_get_proc_name(&cursor1, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) ) - strcpy(functionName, ".anonymous."); - unw_word_t pc; - unw_get_reg(&cursor1, UNW_REG_IP, &pc); - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n", - exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); - } - - // if there is a personality routine, ask it if it will want to stop at this frame - if ( frameInfo.handler != 0 ) { - __personality_routine p = (__personality_routine)(long)(frameInfo.handler); - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, p); - _Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)(&cursor1)); - switch ( personalityResult ) { - case _URC_HANDLER_FOUND: - // found a catch clause or locals that need destructing in this frame - // stop search and remember stack pointer at the frame - handlerNotFound = false; - unw_get_reg(&cursor1, UNW_REG_SP, &sp); - exception_object->private_2 = sp; - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object); - return _URC_NO_REASON; - - case _URC_CONTINUE_UNWIND: - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object); - // continue unwinding - break; - - default: - // something went wrong - DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - } - } - return _URC_NO_REASON; -} - - -static _Unwind_Reason_Code unwind_phase2(unw_context_t* uc, struct _Unwind_Exception* exception_object) -{ - unw_cursor_t cursor2; - unw_init_local(&cursor2, uc); - - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); - - // walk each frame until we reach where search phase said to stop - while ( true ) { - - // ask libuwind to get next frame (skip over first which is _Unwind_RaiseException) - int stepResult = unw_step(&cursor2); - if ( stepResult == 0 ) { - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object); - return _URC_END_OF_STACK; - } - else if ( stepResult < 0 ) { - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // get info about this frame - unw_word_t sp; - unw_proc_info_t frameInfo; - unw_get_reg(&cursor2, UNW_REG_SP, &sp); - if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) { - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // debugging - if ( DEBUG_PRINT_UNWINDING_TEST ) { - char functionName[512]; - unw_word_t offset; - if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) ) - strcpy(functionName, ".anonymous."); - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, lsda=0x%llX, personality=0x%llX\n", - exception_object, frameInfo.start_ip, functionName, sp, frameInfo.lsda, frameInfo.handler); - } - - // if there is a personality routine, tell it we are unwinding - if ( frameInfo.handler != 0 ) { - __personality_routine p = (__personality_routine)(long)(frameInfo.handler); - _Unwind_Action action = _UA_CLEANUP_PHASE; - if ( sp == exception_object->private_2 ) - action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1 - _Unwind_Reason_Code personalityResult = (*p)(1, action, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)(&cursor2)); - switch ( personalityResult ) { - case _URC_CONTINUE_UNWIND: - // continue unwinding - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object); - if ( sp == exception_object->private_2 ) { - // phase 1 said we would stop at this frame, but we did not... - ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here"); - } - break; - case _URC_INSTALL_CONTEXT: - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", exception_object); - // personality routine says to transfer control to landing pad - // we may get control back if landing pad calls _Unwind_Resume() - if ( DEBUG_PRINT_UNWINDING_TEST ) { - unw_word_t pc; - unw_word_t sp; - unw_get_reg(&cursor2, UNW_REG_IP, &pc); - unw_get_reg(&cursor2, UNW_REG_SP, &sp); - DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering user code with ip=0x%llX, sp=0x%llX\n", exception_object, pc, sp); - } - unw_resume(&cursor2); - // unw_resume() only returns if there was an error - return _URC_FATAL_PHASE2_ERROR; - default: - // something went wrong - DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - } - - // clean up phase did not resume at the frame that the search phase said it would - return _URC_FATAL_PHASE2_ERROR; -} - - -static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t* uc, struct _Unwind_Exception* exception_object, - _Unwind_Stop_Fn stop, void* stop_parameter) -{ - unw_cursor_t cursor2; - unw_init_local(&cursor2, uc); - - // walk each frame until we reach where search phase said to stop - while ( unw_step(&cursor2) > 0 ) { - - // get info about this frame - unw_proc_info_t frameInfo; - if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) { - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step failed => _URC_END_OF_STACK\n", exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - - // debugging - if ( DEBUG_PRINT_UNWINDING_TEST ) { - char functionName[512]; - unw_word_t offset; - if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) ) - strcpy(functionName, ".anonymous."); - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n", - exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); - } - - // call stop function at each frame - _Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE); - _Unwind_Reason_Code stopResult = (*stop)(1, action, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)(&cursor2), stop_parameter); - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult); - if ( stopResult != _URC_NO_REASON ) { - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // if there is a personality routine, tell it we are unwinding - if ( frameInfo.handler != 0 ) { - __personality_routine p = (__personality_routine)(long)(frameInfo.handler); - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p); - _Unwind_Reason_Code personalityResult = (*p)(1, action, - exception_object->exception_class, exception_object, - (struct _Unwind_Context*)(&cursor2)); - switch ( personalityResult ) { - case _URC_CONTINUE_UNWIND: - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object); - // destructors called, continue unwinding - break; - case _URC_INSTALL_CONTEXT: - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object); - // we may get control back if landing pad calls _Unwind_Resume() - unw_resume(&cursor2); - break; - default: - // something went wrong - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n", - exception_object, personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - } - - // call stop function one last time and tell it we've reached the end of the stack - DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object); - _Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK); - (*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)(&cursor2), stop_parameter); - - // clean up phase did not resume at the frame that the search phase said it would - return _URC_FATAL_PHASE2_ERROR; -} - - -// -// Called by __cxa_throw. Only returns if there is a fatal error -// -EXPORT _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_RaiseException(ex_obj=%p)\n", exception_object); - unw_context_t uc; - unw_getcontext(&uc); - - // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right thing - exception_object->private_1 = 0; - exception_object->private_2 = 0; - - // phase 1: the search phase - _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object); - if ( phase1 != _URC_NO_REASON ) - return phase1; - - // phase 2: the clean up phase - return unwind_phase2(&uc, exception_object); -} - - -// -// When _Unwind_RaiseException() is in phase2, it hands control -// to the personality function at each frame. The personality -// may force a jump to a landing pad in that function, the landing -// pad code may then call _Unwind_Resume() to continue with the -// unwinding. Note: the call to _Unwind_Resume() is from compiler -// geneated user code. All other _Unwind_* routines are called -// by the C++ runtime __cxa_* routines. -// -// Re-throwing an exception is implemented by having the code call -// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow() -// -EXPORT void _Unwind_Resume(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_Resume(ex_obj=%p)\n", exception_object); - unw_context_t uc; - unw_getcontext(&uc); - - if ( exception_object->private_1 != 0 ) - unwind_phase2_forced(&uc, exception_object, (_Unwind_Stop_Fn)exception_object->private_1, (void*)exception_object->private_2); - else - unwind_phase2(&uc, exception_object); - - // clients assume _Unwind_Resume() does not return, so all we can do is abort. - ABORT("_Unwind_Resume() can't return"); -} - - - -// -// Not used by C++. -// Unwinds stack, calling "stop" function at each frame -// Could be used to implement longjmp(). -// -EXPORT _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter) -{ - DEBUG_PRINT_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", exception_object, stop); - unw_context_t uc; - unw_getcontext(&uc); - - // mark that this is a forced unwind, so _Unwind_Resume() can do the right thing - exception_object->private_1 = (uintptr_t)stop; - exception_object->private_2 = (uintptr_t)stop_parameter; - - // doit - return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter); -} - - -// -// Called by personality handler during phase 2 to get LSDA for current frame -// -EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context) -{ - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if ( unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS ) - result = frameInfo.lsda; - DEBUG_PRINT_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lX\n", context, result); - if ( result != 0 ) { - if ( *((uint8_t*)result) != 0xFF ) - DEBUG_MESSAGE("lsda at 0x%lX does not start with 0xFF\n", result); - } - return result; -} - - -// -// Called by personality handler during phase 2 to get register values -// -EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index) -{ - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_word_t result; - unw_get_reg(cursor, index, &result); - DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%llX\n", context, index, (uint64_t)result); - return result; -} - - -// -// Called by personality handler during phase 2 to alter register values -// -EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value) -{ - DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0llX)\n", context, index, (uint64_t)new_value); - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_set_reg(cursor, index, new_value); -} - - -// -// Called by personality handler during phase 2 to get instruction pointer -// -EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context* context) -{ - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_word_t result; - unw_get_reg(cursor, UNW_REG_IP, &result); - DEBUG_PRINT_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context, (uint64_t)result); - return result; -} - - -// -// Called by personality handler during phase 2 to alter instruction pointer -// -EXPORT void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value) -{ - DEBUG_PRINT_API("_Unwind_SetIP(context=%p, value=0x%0llX)\n", context, (uint64_t)new_value); - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_set_reg(cursor, UNW_REG_IP, new_value); -} - - -// -// Called by personality handler during phase 2 to find the start of the function -// -EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context) -{ - unw_cursor_t* cursor = (unw_cursor_t*)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if ( unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS ) - result = frameInfo.start_ip; - DEBUG_PRINT_API("_Unwind_GetRegionStart(context=%p) => 0x%lX\n", context, result); - return result; -} - - -// -// Called by personality handler during phase 2 if a foreign exception is caught -// -EXPORT void _Unwind_DeleteException(struct _Unwind_Exception* exception_object) -{ - DEBUG_PRINT_API("_Unwind_DeleteException(ex_obj=%p)\n", exception_object); - if ( exception_object->exception_cleanup != NULL ) - (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); -} - - - - -// -// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in earlier versions -// -NOT_HERE_BEFORE_10_6(_Unwind_DeleteException) -NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE) -NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind) -NOT_HERE_BEFORE_10_6(_Unwind_GetGR) -NOT_HERE_BEFORE_10_6(_Unwind_GetIP) -NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData) -NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart) -NOT_HERE_BEFORE_10_6(_Unwind_RaiseException) -NOT_HERE_BEFORE_10_6(_Unwind_Resume) -NOT_HERE_BEFORE_10_6(_Unwind_SetGR) -NOT_HERE_BEFORE_10_6(_Unwind_SetIP) - -#endif // __ppc__ || __i386__ || __x86_64__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/dwarf2.h b/lldb/source/Plugins/Process/Utility/libunwind/src/dwarf2.h deleted file mode 100644 index 83414332c5e..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/dwarf2.h +++ /dev/null @@ -1,245 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- dwarf2.h ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -/* These constants were taken from version 3 of the DWARF standard, - which is Copyright (c) 2005 Free Standards Group, and - Copyright (c) 1992, 1993 UNIX International, Inc. -*/ - - -#ifndef __DWARF2__ -#define __DWARF2__ - -namespace lldb_private { - -// dwarf unwind instructions -enum { - DW_CFA_nop = 0x0, - DW_CFA_set_loc = 0x1, - DW_CFA_advance_loc1 = 0x2, - DW_CFA_advance_loc2 = 0x3, - DW_CFA_advance_loc4 = 0x4, - DW_CFA_offset_extended = 0x5, - DW_CFA_restore_extended = 0x6, - DW_CFA_undefined = 0x7, - DW_CFA_same_value = 0x8, - DW_CFA_register = 0x9, - DW_CFA_remember_state = 0xA, - DW_CFA_restore_state = 0xB, - DW_CFA_def_cfa = 0xC, - DW_CFA_def_cfa_register = 0xD, - DW_CFA_def_cfa_offset = 0xE, - DW_CFA_def_cfa_expression = 0xF, - DW_CFA_expression = 0x10, - DW_CFA_offset_extended_sf = 0x11, - DW_CFA_def_cfa_sf = 0x12, - DW_CFA_def_cfa_offset_sf = 0x13, - DW_CFA_val_offset = 0x14, - DW_CFA_val_offset_sf = 0x15, - DW_CFA_val_expression = 0x16, - DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta - DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register - DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register - - // GNU extensions - DW_CFA_GNU_window_save = 0x2D, - DW_CFA_GNU_args_size = 0x2E, - DW_CFA_GNU_negative_offset_extended = 0x2F -}; - - -// FSF exception handling Pointer-Encoding constants -// Used in CFI augmentation by gcc compiler -enum { - DW_EH_PE_ptr = 0x00, - DW_EH_PE_uleb128 = 0x01, - DW_EH_PE_udata2 = 0x02, - DW_EH_PE_udata4 = 0x03, - DW_EH_PE_udata8 = 0x04, - DW_EH_PE_signed = 0x08, - DW_EH_PE_sleb128 = 0x09, - DW_EH_PE_sdata2 = 0x0A, - DW_EH_PE_sdata4 = 0x0B, - DW_EH_PE_sdata8 = 0x0C, - DW_EH_PE_absptr = 0x00, - DW_EH_PE_pcrel = 0x10, - DW_EH_PE_textrel = 0x20, - DW_EH_PE_datarel = 0x30, - DW_EH_PE_funcrel = 0x40, - DW_EH_PE_aligned = 0x50, - DW_EH_PE_indirect = 0x80, - DW_EH_PE_omit = 0xFF -}; - - -// DWARF expressions -enum { - DW_OP_addr = 0x03, // constant address (size target specific) - DW_OP_deref = 0x06, - DW_OP_const1u = 0x08, // 1-byte constant - DW_OP_const1s = 0x09, // 1-byte constant - DW_OP_const2u = 0x0A, // 2-byte constant - DW_OP_const2s = 0x0B, // 2-byte constant - DW_OP_const4u = 0x0C, // 4-byte constant - DW_OP_const4s = 0x0D, // 4-byte constant - DW_OP_const8u = 0x0E, // 8-byte constant - DW_OP_const8s = 0x0F, // 8-byte constant - DW_OP_constu = 0x10, // ULEB128 constant - DW_OP_consts = 0x11, // SLEB128 constant - DW_OP_dup = 0x12, - DW_OP_drop = 0x13, - DW_OP_over = 0x14, - DW_OP_pick = 0x15, // 1-byte stack index - DW_OP_swap = 0x16, - DW_OP_rot = 0x17, - DW_OP_xderef = 0x18, - DW_OP_abs = 0x19, - DW_OP_and = 0x1A, - DW_OP_div = 0x1B, - DW_OP_minus = 0x1C, - DW_OP_mod = 0x1D, - DW_OP_mul = 0x1E, - DW_OP_neg = 0x1F, - DW_OP_not = 0x20, - DW_OP_or = 0x21, - DW_OP_plus = 0x22, - DW_OP_plus_uconst = 0x23, // ULEB128 addend - DW_OP_shl = 0x24, - DW_OP_shr = 0x25, - DW_OP_shra = 0x26, - DW_OP_xor = 0x27, - DW_OP_skip = 0x2F, // signed 2-byte constant - DW_OP_bra = 0x28, // signed 2-byte constant - DW_OP_eq = 0x29, - DW_OP_ge = 0x2A, - DW_OP_gt = 0x2B, - DW_OP_le = 0x2C, - DW_OP_lt = 0x2D, - DW_OP_ne = 0x2E, - DW_OP_lit0 = 0x30, // Literal 0 - DW_OP_lit1 = 0x31, // Literal 1 - DW_OP_lit2 = 0x32, // Literal 2 - DW_OP_lit3 = 0x33, // Literal 3 - DW_OP_lit4 = 0x34, // Literal 4 - DW_OP_lit5 = 0x35, // Literal 5 - DW_OP_lit6 = 0x36, // Literal 6 - DW_OP_lit7 = 0x37, // Literal 7 - DW_OP_lit8 = 0x38, // Literal 8 - DW_OP_lit9 = 0x39, // Literal 9 - DW_OP_lit10 = 0x3A, // Literal 10 - DW_OP_lit11 = 0x3B, // Literal 11 - DW_OP_lit12 = 0x3C, // Literal 12 - DW_OP_lit13 = 0x3D, // Literal 13 - DW_OP_lit14 = 0x3E, // Literal 14 - DW_OP_lit15 = 0x3F, // Literal 15 - DW_OP_lit16 = 0x40, // Literal 16 - DW_OP_lit17 = 0x41, // Literal 17 - DW_OP_lit18 = 0x42, // Literal 18 - DW_OP_lit19 = 0x43, // Literal 19 - DW_OP_lit20 = 0x44, // Literal 20 - DW_OP_lit21 = 0x45, // Literal 21 - DW_OP_lit22 = 0x46, // Literal 22 - DW_OP_lit23 = 0x47, // Literal 23 - DW_OP_lit24 = 0x48, // Literal 24 - DW_OP_lit25 = 0x49, // Literal 25 - DW_OP_lit26 = 0x4A, // Literal 26 - DW_OP_lit27 = 0x4B, // Literal 27 - DW_OP_lit28 = 0x4C, // Literal 28 - DW_OP_lit29 = 0x4D, // Literal 29 - DW_OP_lit30 = 0x4E, // Literal 30 - DW_OP_lit31 = 0x4F, // Literal 31 - DW_OP_reg0 = 0x50, // Contents of reg0 - DW_OP_reg1 = 0x51, // Contents of reg1 - DW_OP_reg2 = 0x52, // Contents of reg2 - DW_OP_reg3 = 0x53, // Contents of reg3 - DW_OP_reg4 = 0x54, // Contents of reg4 - DW_OP_reg5 = 0x55, // Contents of reg5 - DW_OP_reg6 = 0x56, // Contents of reg6 - DW_OP_reg7 = 0x57, // Contents of reg7 - DW_OP_reg8 = 0x58, // Contents of reg8 - DW_OP_reg9 = 0x59, // Contents of reg9 - DW_OP_reg10 = 0x5A, // Contents of reg10 - DW_OP_reg11 = 0x5B, // Contents of reg11 - DW_OP_reg12 = 0x5C, // Contents of reg12 - DW_OP_reg13 = 0x5D, // Contents of reg13 - DW_OP_reg14 = 0x5E, // Contents of reg14 - DW_OP_reg15 = 0x5F, // Contents of reg15 - DW_OP_reg16 = 0x60, // Contents of reg16 - DW_OP_reg17 = 0x61, // Contents of reg17 - DW_OP_reg18 = 0x62, // Contents of reg18 - DW_OP_reg19 = 0x63, // Contents of reg19 - DW_OP_reg20 = 0x64, // Contents of reg20 - DW_OP_reg21 = 0x65, // Contents of reg21 - DW_OP_reg22 = 0x66, // Contents of reg22 - DW_OP_reg23 = 0x67, // Contents of reg23 - DW_OP_reg24 = 0x68, // Contents of reg24 - DW_OP_reg25 = 0x69, // Contents of reg25 - DW_OP_reg26 = 0x6A, // Contents of reg26 - DW_OP_reg27 = 0x6B, // Contents of reg27 - DW_OP_reg28 = 0x6C, // Contents of reg28 - DW_OP_reg29 = 0x6D, // Contents of reg29 - DW_OP_reg30 = 0x6E, // Contents of reg30 - DW_OP_reg31 = 0x6F, // Contents of reg31 - DW_OP_breg0 = 0x70, // base register 0 + SLEB128 offset - DW_OP_breg1 = 0x71, // base register 1 + SLEB128 offset - DW_OP_breg2 = 0x72, // base register 2 + SLEB128 offset - DW_OP_breg3 = 0x73, // base register 3 + SLEB128 offset - DW_OP_breg4 = 0x74, // base register 4 + SLEB128 offset - DW_OP_breg5 = 0x75, // base register 5 + SLEB128 offset - DW_OP_breg6 = 0x76, // base register 6 + SLEB128 offset - DW_OP_breg7 = 0x77, // base register 7 + SLEB128 offset - DW_OP_breg8 = 0x78, // base register 8 + SLEB128 offset - DW_OP_breg9 = 0x79, // base register 9 + SLEB128 offset - DW_OP_breg10 = 0x7A, // base register 10 + SLEB128 offset - DW_OP_breg11 = 0x7B, // base register 11 + SLEB128 offset - DW_OP_breg12 = 0x7C, // base register 12 + SLEB128 offset - DW_OP_breg13 = 0x7D, // base register 13 + SLEB128 offset - DW_OP_breg14 = 0x7E, // base register 14 + SLEB128 offset - DW_OP_breg15 = 0x7F, // base register 15 + SLEB128 offset - DW_OP_breg16 = 0x80, // base register 16 + SLEB128 offset - DW_OP_breg17 = 0x81, // base register 17 + SLEB128 offset - DW_OP_breg18 = 0x82, // base register 18 + SLEB128 offset - DW_OP_breg19 = 0x83, // base register 19 + SLEB128 offset - DW_OP_breg20 = 0x84, // base register 20 + SLEB128 offset - DW_OP_breg21 = 0x85, // base register 21 + SLEB128 offset - DW_OP_breg22 = 0x86, // base register 22 + SLEB128 offset - DW_OP_breg23 = 0x87, // base register 23 + SLEB128 offset - DW_OP_breg24 = 0x88, // base register 24 + SLEB128 offset - DW_OP_breg25 = 0x89, // base register 25 + SLEB128 offset - DW_OP_breg26 = 0x8A, // base register 26 + SLEB128 offset - DW_OP_breg27 = 0x8B, // base register 27 + SLEB128 offset - DW_OP_breg28 = 0x8C, // base register 28 + SLEB128 offset - DW_OP_breg29 = 0x8D, // base register 29 + SLEB128 offset - DW_OP_breg30 = 0x8E, // base register 30 + SLEB128 offset - DW_OP_breg31 = 0x8F, // base register 31 + SLEB128 offset - DW_OP_regx = 0x90, // ULEB128 register - DW_OP_fbreg = 0x91, // SLEB128 offset - DW_OP_bregx = 0x92, // ULEB128 register followed by SLEB128 offset - DW_OP_piece = 0x93, // ULEB128 size of piece addressed - DW_OP_deref_size = 0x94, // 1-byte size of data retrieved - DW_OP_xderef_size = 0x95, // 1-byte size of data retrieved - DW_OP_nop = 0x96, - DW_OP_push_object_addres = 0x97, - DW_OP_call2 = 0x98, // 2-byte offset of DIE - DW_OP_call4 = 0x99, // 4-byte offset of DIE - DW_OP_call_ref = 0x9A, // 4- or 8-byte offset of DIE - DW_OP_lo_user = 0xE0, - DW_OP_APPLE_uninit = 0xF0, - DW_OP_hi_user = 0xFF -}; - - -}; // namespace lldb_private - - -#endif - - - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/libunwind_priv.h b/lldb/source/Plugins/Process/Utility/libunwind/src/libunwind_priv.h deleted file mode 100644 index fe25780c538..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/libunwind_priv.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- libunwind_priv.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __LIBUNWIND_PRIV__ -#define __LIBUNWIND_PRIV__ - -namespace lldb_private { -#include "libunwind.h" - -#ifdef __cplusplus -extern "C" { -#endif - // SPI - extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)); - - // IPI - extern void _unw_add_dynamic_fde(unw_word_t fde); - extern void _unw_remove_dynamic_fde(unw_word_t fde); - -#ifdef __cplusplus -} -#endif - -}; // namespace lldb_private - - -#endif - diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/libuwind.cxx b/lldb/source/Plugins/Process/Utility/libunwind/src/libuwind.cxx deleted file mode 100644 index d841677db37..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/libuwind.cxx +++ /dev/null @@ -1,428 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 vi:set tabstop=4 expandtab: -*/ -//===-- libuwind.cxx --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if __ppc__ || __i386__ || __x86_64__ - -#include <mach/mach_types.h> -#include <mach/machine.h> -#include <new> - -#include "libunwind.h" -#include "libunwind_priv.h" - -#include "UnwindCursor.hpp" -#include "AddressSpace.hpp" - -#include "RemoteProcInfo.hpp" - -namespace lldb_private { - -// setup debug logging hooks -INITIALIZE_DEBUG_PRINT_API -INITIALIZE_DEBUG_PRINT_UNWINDING - -// internal object to represent this processes address space -static LocalAddressSpace sThisAddressSpace; - -#pragma mark Local API - -/// -/// record the registers and stack position of the caller -/// -extern int unw_getcontext(unw_context_t*); -// note: unw_getcontext() implemented in assembly - -/// -/// create a cursor of a thread in this process given 'context' recorded by unw_getcontext() -/// -EXPORT int unw_init_local(unw_cursor_t* cursor, unw_context_t* context) -{ - DEBUG_PRINT_API("unw_init_local(cursor=%p, context=%p)\n", cursor, context); - // use "placement new" to allocate UnwindCursor in the cursor buffer -#if __i386__ - new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_x86>(context, sThisAddressSpace); -#elif __x86_64__ - new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_x86_64>(context, sThisAddressSpace); -#elif __ppc__ - new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_ppc>(context, sThisAddressSpace); -#endif - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - co->setInfoBasedOnIPRegister(NULL); - - return UNW_ESUCCESS; -} - -/// -/// move cursor to next frame -/// -EXPORT int unw_step(unw_cursor_t* cursor) -{ - DEBUG_PRINT_API("unw_step(cursor=%p)\n", cursor); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - return co->step(); -} - -/// -/// get value of specified register at cursor position in stack frame -/// -EXPORT int unw_get_reg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_word_t* value) -{ - DEBUG_PRINT_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", cursor, regNum, value); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - - if (co->validReg(regNum) == 0) - return UNW_EBADREG; - return co->getReg(regNum, value); -} - -/// -/// get value of specified float register at cursor position in stack frame -/// -EXPORT int unw_get_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_fpreg_t* value) -{ - DEBUG_PRINT_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", cursor, regNum, value); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - - if ( co->validFloatReg(regNum) ) { - return co->getFloatReg(regNum, value); - } - return UNW_EBADREG; -} - -/// -/// set value of specified register at cursor position in stack frame -/// -EXPORT int unw_set_reg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_word_t value) -{ - DEBUG_PRINT_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", cursor, regNum, value); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - - if ( co->validReg(regNum) ) { - co->setReg(regNum, value); - // specical case altering IP to re-find info (being called by personality function) - if ( regNum == UNW_REG_IP ) { - unw_proc_info_t info; - co->getInfo(&info); - uint64_t orgArgSize = info.gp; - uint64_t orgFuncStart = info.start_ip; - co->setInfoBasedOnIPRegister(false); - // and adjust REG_SP if there was a DW_CFA_GNU_args_size - if ( (orgFuncStart == info.start_ip) && (orgArgSize != 0) ) - co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + orgArgSize); - } - return UNW_ESUCCESS; - } - return UNW_EBADREG; -} - -/// -/// set value of specified float register at cursor position in stack frame -/// -EXPORT int unw_set_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_fpreg_t value) -{ - DEBUG_PRINT_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", cursor, regNum, value); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - - if ( co->validFloatReg(regNum) ) { - return co->setFloatReg(regNum, value); - } - return UNW_EBADREG; -} - -/// -/// resume execution at cursor position (aka longjump) -/// -EXPORT int unw_resume(unw_cursor_t* cursor) -{ - DEBUG_PRINT_API("unw_resume(cursor=%p)\n", cursor); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - - co->jumpto(); - return UNW_EUNSPEC; -} - -/// -/// returns the name of a register -/// -EXPORT const char* unw_regname(unw_cursor_t* cursor, unw_regnum_t regNum) -{ - DEBUG_PRINT_API("unw_regname(cursor=%p, regNum=%d)\n", cursor, regNum); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - return co->getRegisterName(regNum); -} - -/// -/// get unwind info at cursor position in stack frame -/// -EXPORT int unw_get_proc_info(unw_cursor_t* cursor, unw_proc_info_t* info) -{ - DEBUG_PRINT_API("unw_get_proc_info(cursor=%p, &info=%p)\n", cursor, info); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - co->getInfo(info); - if ( info->end_ip == 0 ) - return UNW_ENOINFO; - else - return UNW_ESUCCESS; -} - -/// -/// checks if a register is a floating-point register -/// -EXPORT int unw_is_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum) -{ - DEBUG_PRINT_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", cursor, regNum); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - return co->validFloatReg(regNum); -} - -/// -/// checks if current frame is signal trampoline -/// -EXPORT int unw_is_signal_frame(unw_cursor_t* cursor) -{ - DEBUG_PRINT_API("unw_is_signal_frame(cursor=%p)\n", cursor); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - return co->isSignalFrame(); -} - -/// -/// get name of function at cursor position in stack frame -/// -EXPORT int unw_get_proc_name(unw_cursor_t* cursor, char* buf, size_t bufLen, unw_word_t* offset) -{ - DEBUG_PRINT_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%ld)\n", cursor, buf, bufLen); - AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor; - if ( co->getFunctionName(buf, bufLen, offset) ) - return UNW_ESUCCESS; - else - return UNW_EUNSPEC; -} - -#pragma mark Remote API - -#if defined (SUPPORT_REMOTE_UNWINDING) -EXPORT int unw_init_remote(unw_cursor_t *cursor, unw_addr_space_t as, void *arg) -{ - DEBUG_PRINT_API("init_remote(c=%p, as=%p, arg=%p)\n", cursor, as, arg); - - // API docs at http://www.nongnu.org/libunwind/docs.html say we should - // handle a local address space but we're not doing the "remote" unwinding - // with local process accessors so punt on that. - - if(as->type != UNW_REMOTE) - { - ABORT("unw_init_remote was passed a non-remote address space"); - return UNW_EINVAL; - } - - unw_accessors_t* acc = unw_get_accessors(as); - if(!acc) { - ABORT("unw_get_accessors returned NULL"); - return UNW_EINVAL; - } - - unw_addr_space_remote* remote = (unw_addr_space_remote*)as; - - // use "placement new" to allocate UnwindCursor in the cursor buffer - // It isn't really necessary to use placement new in the remote API but we'll stay consistent - // with the rest of the code here. - switch ( remote->ras->getTargetArch() ) { - case UNW_TARGET_I386: - { - Registers_x86 r; - // LEAK: "addrSpace" is being leaked every time here with no easy solution. - // The address space is in the cursor and the cursor may get - // duplicated, though if it does get duplicated, it will just be - // memcpy'ed since unw_cursor_t is just a bunch of uint64_t types... - OtherAddressSpace<Pointer32<LittleEndian> > *addrSpace = new OtherAddressSpace<Pointer32<LittleEndian> >(as, arg); - getRemoteContext (remote->ras, r, arg); - unw_context_t *context = (unw_context_t*) &r; - new ((void*)cursor) RemoteUnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >, Registers_x86>(*addrSpace, context, arg); - } - break; - case UNW_TARGET_X86_64: - { - Registers_x86_64 r; - // LEAK: "addrSpace" is being leaked every time here with no easy solution. - // The address space is in the cursor and the cursor may get - // duplicated, though if it does get duplicated, it will just be - // memcpy'ed since unw_cursor_t is just a bunch of uint64_t types... - OtherAddressSpace<Pointer64<LittleEndian> > *addrSpace = new OtherAddressSpace<Pointer64<LittleEndian> >(as, arg); - getRemoteContext (remote->ras, r, arg); - unw_context_t *context = (unw_context_t*) &r; - new ((void*)cursor) RemoteUnwindCursor<OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(*addrSpace, context, arg); - } - break; - - case UNW_TARGET_PPC: - ABORT("ppc not supported for remote unwinds"); - break; - - case UNW_TARGET_ARM: - ABORT("arm not supported for remote unwinds"); - break; - - default: - return UNW_EUNSPEC; - } - - AbstractRemoteUnwindCursor* co = (AbstractRemoteUnwindCursor*)cursor; - co->setRemoteContext(arg); - - return UNW_ESUCCESS; -} - -// The documentation disagrees about whether or not this returns a pointer. Now it does. -EXPORT unw_accessors_t* unw_get_accessors(unw_addr_space_t as) -{ - if(as->type != UNW_REMOTE) - { - ABORT("unw_get_accessors was passed a non-remote address space"); - return NULL; - } - unw_addr_space_remote* remote = (unw_addr_space_remote*)as; - - if(remote->type != UNW_REMOTE) - return NULL; - - return remote->ras->getAccessors(); -} - -EXPORT unw_addr_space_t unw_create_addr_space(unw_accessors_t *ap, unw_targettype_t targarch) -{ - unw_addr_space_remote* remote = (unw_addr_space_remote*)malloc(sizeof(unw_addr_space_remote)); - remote->type = UNW_REMOTE; - remote->ras = new RemoteProcInfo(ap, targarch); - return (unw_addr_space_t)remote; -} - -EXPORT void unw_flush_caches(unw_addr_space_t as) -{ - if(as->type != UNW_REMOTE) - { - ABORT("unw_flush_caches was passed a non-remote address space"); - return; - } - unw_addr_space_remote* remote = (unw_addr_space_remote*)as; - remote->ras->flushAllCaches(); - - return; -} - -EXPORT void unw_image_was_unloaded (unw_addr_space_t as, unw_word_t mh) -{ - if(as->type != UNW_REMOTE) - { - ABORT("unw_image_was_unloaded was passed a non-remote address space"); - return; - } - unw_addr_space_remote* remote = (unw_addr_space_remote*)as; - remote->ras->flushCacheByMachHeader(mh); - - return; -} - - -EXPORT int unw_set_caching_policy(unw_addr_space_t as, unw_caching_policy_t policy) -{ - if(as->type != UNW_REMOTE) - { - ABORT("unw_set_caching_policy was passed a non-remote address space"); - return UNW_EINVAL; - } - unw_addr_space_remote* remote = (unw_addr_space_remote*)as; - return remote->ras->setCachingPolicy(policy); -} - -EXPORT unw_addr_space_t unw_local_addr_space = (unw_addr_space_t)&sThisAddressSpace; - -/// -/// delete an address_space object -/// -EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) -{ - if(asp->type != UNW_REMOTE) { - ABORT("unw_destroy_addr_space was passed a non-remote address space"); - return; - } - - unw_addr_space_remote* remote = (unw_addr_space_remote*)asp; - delete remote->ras; -} - -EXPORT void unw_set_logging_level(unw_addr_space_t as, FILE *f, unw_log_level_t level) -{ - if (as->type != UNW_REMOTE) { - ABORT("unw_set_logging_level was passed a non-remote address space"); - return; - } - - unw_addr_space_remote* remote = (unw_addr_space_remote*)as; - return remote->ras->setLoggingLevel(f, level); -} - - -EXPORT int unw_end_of_prologue_setup(unw_cursor_t* cursor, unw_word_t start, unw_word_t end, unw_word_t *endofprologue) -{ - AbstractRemoteUnwindCursor* co = (AbstractRemoteUnwindCursor*)cursor; - if (!co->remoteUnwindCursor()) - ABORT("unw_end_of_prologue_setup called with a non-remote unwind cursor."); - - return co->endOfPrologueInsns (start, end, endofprologue); -} - - -#endif // SUPPORT_REMOTE_UNWINDING - -#pragma mark Dynamic unwinding API - -#if !FOR_DYLD -/// -/// SPI: walks cached dwarf entries -/// -EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) -{ - DEBUG_PRINT_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", func); - DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func); -} -#endif // !FOR_DYLD - -#if !FOR_DYLD -// -// IPI: for __register_frame() -// -void _unw_add_dynamic_fde(unw_word_t fde) -{ - CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; - CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; - const char* message = CFI_Parser<LocalAddressSpace>::decodeFDE(sThisAddressSpace, (LocalAddressSpace::pint_t)fde, & fdeInfo, &cieInfo); - if ( message == NULL ) { - // dynamically registered FDEs don't have a mach_header group they are in. Use fde as mh_group - unw_word_t mh_group = fdeInfo.fdeStart; - DwarfFDECache<LocalAddressSpace>::add(mh_group, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart); - } - else { - DEBUG_MESSAGE("_unw_add_dynamic_fde: bad fde: %s", message); - } -} - -// -// IPI: for __deregister_frame() -// -void _unw_remove_dynamic_fde(unw_word_t fde) -{ - // fde is own mh_group - DwarfFDECache<LocalAddressSpace>::removeAllIn(fde); -} -#endif - -}; // namespace lldb_private - -#endif // __ppc__ || __i386__ || __x86_64__ diff --git a/lldb/source/Plugins/Process/Utility/libunwind/src/unw_getcontext.s b/lldb/source/Plugins/Process/Utility/libunwind/src/unw_getcontext.s deleted file mode 100644 index 8d3a451fd92..00000000000 --- a/lldb/source/Plugins/Process/Utility/libunwind/src/unw_getcontext.s +++ /dev/null @@ -1,229 +0,0 @@ - -#if __i386__ || __x86_64__ || __ppc__ - - .text - .globl _unw_getcontext -_unw_getcontext: - -#endif // __i386__ || __x86_64__ || __ppc__ - - -#if __i386__ - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# + + -# +-----------------------+ -# + thread_state pointer + -# +-----------------------+ -# + return address + -# +-----------------------+ <-- SP -# + + -# - push %eax - movl 8(%esp), %eax - movl %ebx, 4(%eax) - movl %ecx, 8(%eax) - movl %edx, 12(%eax) - movl %edi, 16(%eax) - movl %esi, 20(%eax) - movl %ebp, 24(%eax) - movl %esp, %edx - addl $8, %edx - movl %edx, 28(%eax) # store what sp was at call site as esp - # skip ss - # skip eflags - movl 4(%esp), %edx - movl %edx, 40(%eax) # store return address as eip - # skip cs - # skip ds - # skip es - # skip fs - # skip gs - movl (%esp), %edx - movl %edx, (%eax) # store original eax - popl %eax - xorl %eax, %eax # return UNW_ESUCCESS - ret - -#elif __x86_64__ - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in rdi -# - movq %rax, (%rdi) - movq %rbx, 8(%rdi) - movq %rcx, 16(%rdi) - movq %rdx, 24(%rdi) - movq %rdi, 32(%rdi) - movq %rsi, 40(%rdi) - movq %rbp, 48(%rdi) - movq %rsp, 56(%rdi) - addq $8, 56(%rdi) - movq %r8, 64(%rdi) - movq %r9, 72(%rdi) - movq %r10, 80(%rdi) - movq %r11, 88(%rdi) - movq %r12, 96(%rdi) - movq %r13,104(%rdi) - movq %r14,112(%rdi) - movq %r15,120(%rdi) - movq (%rsp),%rsi - movq %rsi,128(%rdi) # store return address as rip - # skip rflags - # skip cs - # skip fs - # skip gs - xorl %eax, %eax # return UNW_ESUCCESS - ret - -#elif __ppc__ - -; -; extern int unw_getcontext(unw_context_t* thread_state) -; -; On entry: -; thread_state pointer is in r3 -; - stw r0, 8(r3) - mflr r0 - stw r0, 0(r3) ; store lr as ssr0 - stw r1, 12(r3) - stw r2, 16(r3) - stw r3, 20(r3) - stw r4, 24(r3) - stw r5, 28(r3) - stw r6, 32(r3) - stw r7, 36(r3) - stw r8, 40(r3) - stw r9, 44(r3) - stw r10, 48(r3) - stw r11, 52(r3) - stw r12, 56(r3) - stw r13, 60(r3) - stw r14, 64(r3) - stw r15, 68(r3) - stw r16, 72(r3) - stw r17, 76(r3) - stw r18, 80(r3) - stw r19, 84(r3) - stw r20, 88(r3) - stw r21, 92(r3) - stw r22, 96(r3) - stw r23,100(r3) - stw r24,104(r3) - stw r25,108(r3) - stw r26,112(r3) - stw r27,116(r3) - stw r28,120(r3) - stw r29,124(r3) - stw r30,128(r3) - stw r31,132(r3) - - ; save VRSave register - mfspr r0,256 - stw r0,156(r3) - ; save CR registers - mfcr r0 - stw r0,136(r3) - ; save CTR register - mfctr r0 - stw r0,148(r3) - - ; save float registers - stfd f0, 160(r3) - stfd f1, 168(r3) - stfd f2, 176(r3) - stfd f3, 184(r3) - stfd f4, 192(r3) - stfd f5, 200(r3) - stfd f6, 208(r3) - stfd f7, 216(r3) - stfd f8, 224(r3) - stfd f9, 232(r3) - stfd f10,240(r3) - stfd f11,248(r3) - stfd f12,256(r3) - stfd f13,264(r3) - stfd f14,272(r3) - stfd f15,280(r3) - stfd f16,288(r3) - stfd f17,296(r3) - stfd f18,304(r3) - stfd f19,312(r3) - stfd f20,320(r3) - stfd f21,328(r3) - stfd f22,336(r3) - stfd f23,344(r3) - stfd f24,352(r3) - stfd f25,360(r3) - stfd f26,368(r3) - stfd f27,376(r3) - stfd f28,384(r3) - stfd f29,392(r3) - stfd f30,400(r3) - stfd f31,408(r3) - - - ; save vector registers - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone - -#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ - stvx _vec,0,r4 @\ - lwz r5, 0(r4) @\ - stw r5, _offset(r3) @\ - lwz r5, 4(r4) @\ - stw r5, _offset+4(r3) @\ - lwz r5, 8(r4) @\ - stw r5, _offset+8(r3) @\ - lwz r5, 12(r4) @\ - stw r5, _offset+12(r3) - - SAVE_VECTOR_UNALIGNED( v0, 424+0x000) - SAVE_VECTOR_UNALIGNED( v1, 424+0x010) - SAVE_VECTOR_UNALIGNED( v2, 424+0x020) - SAVE_VECTOR_UNALIGNED( v3, 424+0x030) - SAVE_VECTOR_UNALIGNED( v4, 424+0x040) - SAVE_VECTOR_UNALIGNED( v5, 424+0x050) - SAVE_VECTOR_UNALIGNED( v6, 424+0x060) - SAVE_VECTOR_UNALIGNED( v7, 424+0x070) - SAVE_VECTOR_UNALIGNED( v8, 424+0x080) - SAVE_VECTOR_UNALIGNED( v9, 424+0x090) - SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0) - SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0) - SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0) - SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0) - SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0) - SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0) - SAVE_VECTOR_UNALIGNED(v16, 424+0x100) - SAVE_VECTOR_UNALIGNED(v17, 424+0x110) - SAVE_VECTOR_UNALIGNED(v18, 424+0x120) - SAVE_VECTOR_UNALIGNED(v19, 424+0x130) - SAVE_VECTOR_UNALIGNED(v20, 424+0x140) - SAVE_VECTOR_UNALIGNED(v21, 424+0x150) - SAVE_VECTOR_UNALIGNED(v22, 424+0x160) - SAVE_VECTOR_UNALIGNED(v23, 424+0x170) - SAVE_VECTOR_UNALIGNED(v24, 424+0x180) - SAVE_VECTOR_UNALIGNED(v25, 424+0x190) - SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0) - SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0) - SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0) - SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0) - SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0) - SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0) - - li r3, 0 ; return UNW_ESUCCESS - blr - - - -#endif - diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 1f0bc149833..934c00a3d1a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -45,7 +45,6 @@ #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "ThreadGDBRemote.h" -#include "MacOSXLibunwindCallbacks.h" #include "StopInfoMachException.h" @@ -119,8 +118,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS), m_packet_timeout (1), m_max_memory_size (512), - m_libunwind_target_type (UNW_TARGET_UNSPECIFIED), - m_libunwind_addr_space (NULL), m_waiting_for_attach (false), m_local_debugserver (true) { @@ -1615,7 +1612,6 @@ ProcessGDBRemote::Clear() Mutex::Locker locker(m_stdio_mutex); m_stdout_data.clear(); } - DestoryLibUnwindAddressSpace(); } Error @@ -2170,45 +2166,6 @@ ProcessGDBRemote::AsyncThread (void *arg) return NULL; } -lldb_private::unw_addr_space_t -ProcessGDBRemote::GetLibUnwindAddressSpace () -{ - unw_targettype_t target_type = UNW_TARGET_UNSPECIFIED; - - ArchSpec::CPU arch_cpu = m_target.GetArchitecture().GetGenericCPUType(); - if (arch_cpu == ArchSpec::eCPU_i386) - target_type = UNW_TARGET_I386; - else if (arch_cpu == ArchSpec::eCPU_x86_64) - target_type = UNW_TARGET_X86_64; - - if (m_libunwind_addr_space) - { - if (m_libunwind_target_type != target_type) - DestoryLibUnwindAddressSpace(); - else - return m_libunwind_addr_space; - } - unw_accessors_t callbacks = get_macosx_libunwind_callbacks (); - m_libunwind_addr_space = unw_create_addr_space (&callbacks, target_type); - if (m_libunwind_addr_space) - m_libunwind_target_type = target_type; - else - m_libunwind_target_type = UNW_TARGET_UNSPECIFIED; - return m_libunwind_addr_space; -} - -void -ProcessGDBRemote::DestoryLibUnwindAddressSpace () -{ - if (m_libunwind_addr_space) - { - unw_destroy_addr_space (m_libunwind_addr_space); - m_libunwind_addr_space = NULL; - } - m_libunwind_target_type = UNW_TARGET_UNSPECIFIED; -} - - const char * ProcessGDBRemote::GetDispatchQueueNameForThread ( diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index a2b5898b34e..74905d0e646 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -29,7 +29,6 @@ #include "GDBRemoteCommunication.h" #include "Utility/StringExtractor.h" #include "GDBRemoteRegisterContext.h" -#include "libunwind/include/libunwind.h" class ThreadGDBRemote; @@ -335,8 +334,6 @@ protected: lldb::addr_t m_dispatch_queue_offsets_addr; uint32_t m_packet_timeout; size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory - lldb_private::unw_targettype_t m_libunwind_target_type; - lldb_private::unw_addr_space_t m_libunwind_addr_space; // libunwind address space object for this process. bool m_waiting_for_attach; bool m_local_debugserver; // Is the debugserver process we are talking to local or on another machine. @@ -384,11 +381,6 @@ private: //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote); - lldb_private::unw_addr_space_t - GetLibUnwindAddressSpace (); - - void - DestoryLibUnwindAddressSpace (); }; #endif // liblldb_ProcessGDBRemote_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index c1b5fa47d93..f5491cb9202 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -20,11 +20,9 @@ #include "lldb/Target/Unwind.h" #include "lldb/Breakpoint/WatchpointLocation.h" -#include "LibUnwindRegisterContext.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" -#include "UnwindLibUnwind.h" #include "UnwindMacOSXFrameBackchain.h" #include "UnwindLLDB.h" diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index a6deead8f15..2b7344d128a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -14,7 +14,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" -#include "libunwind/include/libunwind.h" class StringExtractor; class ProcessGDBRemote; |