summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp')
-rw-r--r--lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp b/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp
new file mode 100644
index 00000000000..58a7ac043c5
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/MacOSXLibunwindCallbacks.cpp
@@ -0,0 +1,306 @@
+//===-- 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-enumerations.h"
+#include "libunwind.h"
+#include "llvm-c/EnhancedDisassembly.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 *th = (Thread *) arg;
+ Address addr;
+ if (!th->GetProcess().ResolveLoadAddress(ip, addr))
+ return -1;
+
+ SymbolContext sc;
+ if (!th->GetProcess().GetTarget().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(&th->GetProcess()) - sc.symbol->GetValue().GetLoadAddress(&th->GetProcess());
+ 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 *th = (Thread *) arg;
+ Address addr;
+ if (!th->GetProcess().ResolveLoadAddress(load_addr, addr))
+ return -1;
+
+ SymbolContext sc;
+ if (!th->GetProcess().GetTarget().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 (&th->GetProcess());
+ *text_start = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
+ *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 (&th->GetProcess());
+ *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 (&th->GetProcess());
+ *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 *th = (Thread *) arg;
+ Address addr;
+ if (!th->GetProcess().ResolveLoadAddress(ip, addr))
+ return -1;
+ SymbolContext sc;
+ if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction | eSymbolContextSymbol, sc))
+ return -1;
+ if (sc.function)
+ {
+ lldb::addr_t start, len;
+ start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(&th->GetProcess());
+ 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(&th->GetProcess());
+ 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 *th = (Thread *) arg;
+ const ArchSpec target_arch (th->GetProcess().GetTarget().GetArchitecture ());
+
+ if (target_arch.GetCPUType() == CPU_TYPE_I386)
+ {
+ if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
+ return -1;
+ }
+ else if (target_arch.GetCPUType() == CPU_TYPE_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_
OpenPOWER on IntegriCloud