blob: 7f6f1759bdbb70fdad854b0466afed58a99c8d9c [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- MacOSXLibunwindCallbacks.cpp ----------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef liblldb_MacOSXLibunwindCallbacks_cpp_
11#define liblldb_MacOSXLibunwindCallbacks_cpp_
12#if defined(__cplusplus)
13
14#include "lldb/Core/DataExtractor.h"
15#include "lldb/Core/FileSpec.h"
16#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Symbol/ObjectFile.h"
18#include "lldb/Symbol/SymbolContext.h"
19#include "lldb/Target/Process.h"
20#include "lldb/Target/RegisterContext.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/Thread.h"
23
Greg Clayton54e7afa2010-07-09 20:39:50 +000024#include "lldb/lldb-enumerations.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025#include "llvm-c/EnhancedDisassembly.h"
26
Greg Clayton54e7afa2010-07-09 20:39:50 +000027#include "libunwind/include/libunwind.h"
28
Chris Lattner24943d22010-06-08 16:52:24 +000029using namespace lldb;
30
31namespace lldb_private {
32
33/* Don't implement (libunwind does not use)
34 find_proc_info
35 put_unwind_info
36 get_dyn_info_list_addr
37 access_mem
38 resume
39*/
40/*
41 Should implement (not needed yet)
42 access_fpreg
43 access_vecreg
44 proc_is_sigtramp
45 proc_is_inferior_function_call
46 access_reg_inf_func_call
47*/
48
49static int
50access_reg (lldb_private::unw_addr_space_t as, lldb_private::unw_regnum_t regnum, lldb_private::unw_word_t *valp, int write, void *arg)
51{
52 if (arg == 0)
53 return -1;
54 Thread *th = (Thread *) arg;
55 /* FIXME Only support reading for now. */
56 if (write == 1)
57 return -1;
58 if (th->GetRegisterContext()->GetRegisterInfoAtIndex(regnum) == NULL)
59 return -1;
60 DataExtractor de;
61 if (!th->GetRegisterContext()->ReadRegisterBytes (regnum, de))
62 return -1;
63 memcpy (valp, de.GetDataStart(), de.GetByteSize());
64 return UNW_ESUCCESS;
65}
66
67static int
68get_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)
69{
70 if (arg == 0)
71 return -1;
Greg Claytoneea26402010-09-14 23:36:40 +000072 Thread *thread = (Thread *) arg;
73 Target &target = thread->GetProcess().GetTarget();
Chris Lattner24943d22010-06-08 16:52:24 +000074 Address addr;
Greg Claytoneea26402010-09-14 23:36:40 +000075 if (!target.GetSectionLoadList().ResolveLoadAddress(ip, addr))
Chris Lattner24943d22010-06-08 16:52:24 +000076 return -1;
77
78 SymbolContext sc;
Greg Claytoneea26402010-09-14 23:36:40 +000079 if (!target.GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction, sc))
Chris Lattner24943d22010-06-08 16:52:24 +000080 return -1;
81 if (!sc.symbol)
82 return -1;
83 strlcpy (bufp, sc.symbol->GetMangled().GetMangledName().AsCString(""), buf_len);
84 if (offp)
Greg Claytoneea26402010-09-14 23:36:40 +000085 *offp = addr.GetLoadAddress(&target) - sc.symbol->GetValue().GetLoadAddress(&target);
Chris Lattner24943d22010-06-08 16:52:24 +000086 return UNW_ESUCCESS;
87}
88
89static int
90find_image_info (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t load_addr, lldb_private::unw_word_t *mh,
91 lldb_private::unw_word_t *text_start, lldb_private::unw_word_t *text_end,
92 lldb_private::unw_word_t *eh_frame, lldb_private::unw_word_t *eh_frame_len,
93 lldb_private::unw_word_t *compact_unwind_start, lldb_private::unw_word_t *compact_unwind_len, void *arg)
94{
95 if (arg == 0)
96 return -1;
Greg Claytoneea26402010-09-14 23:36:40 +000097 Thread *thread = (Thread *) arg;
98 Target &target = thread->GetProcess().GetTarget();
Chris Lattner24943d22010-06-08 16:52:24 +000099 Address addr;
Greg Claytoneea26402010-09-14 23:36:40 +0000100 if (!target.GetSectionLoadList().ResolveLoadAddress(load_addr, addr))
Chris Lattner24943d22010-06-08 16:52:24 +0000101 return -1;
102
103 SymbolContext sc;
Greg Claytoneea26402010-09-14 23:36:40 +0000104 if (!target.GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextModule, sc))
Chris Lattner24943d22010-06-08 16:52:24 +0000105 return -1;
106
107 SectionList *sl = sc.module_sp->GetObjectFile()->GetSectionList();
108 static ConstString g_segment_name_TEXT("__TEXT");
109 SectionSP text_segment_sp(sl->FindSectionByName(g_segment_name_TEXT));
110 if (!text_segment_sp)
111 return -1;
112
Greg Claytoneea26402010-09-14 23:36:40 +0000113 *mh = text_segment_sp->GetLoadBaseAddress (&target);
114 *text_start = text_segment_sp->GetLoadBaseAddress (&target);
Chris Lattner24943d22010-06-08 16:52:24 +0000115 *text_end = *text_start + text_segment_sp->GetByteSize();
116
117 static ConstString g_section_name_eh_frame ("__eh_frame");
118 SectionSP eh_frame_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_eh_frame);
119 if (eh_frame_section_sp.get()) {
Greg Claytoneea26402010-09-14 23:36:40 +0000120 *eh_frame = eh_frame_section_sp->GetLoadBaseAddress (&target);
Chris Lattner24943d22010-06-08 16:52:24 +0000121 *eh_frame_len = eh_frame_section_sp->GetByteSize();
122 } else {
123 *eh_frame = 0;
124 *eh_frame_len = 0;
125 }
126
127 static ConstString g_section_name_unwind_info ("__unwind_info");
128 SectionSP unwind_info_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_unwind_info);
129 if (unwind_info_section_sp.get()) {
Greg Claytoneea26402010-09-14 23:36:40 +0000130 *compact_unwind_start = unwind_info_section_sp->GetLoadBaseAddress (&target);
Chris Lattner24943d22010-06-08 16:52:24 +0000131 *compact_unwind_len = unwind_info_section_sp->GetByteSize();
132 } else {
133 *compact_unwind_start = 0;
134 *compact_unwind_len = 0;
135 }
136 return UNW_ESUCCESS;
137}
138
139static int
140get_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)
141{
142 if (arg == 0)
143 return -1;
Greg Claytoneea26402010-09-14 23:36:40 +0000144 Thread *thread = (Thread *) arg;
145 Target &target = thread->GetProcess().GetTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000146 Address addr;
Greg Claytoneea26402010-09-14 23:36:40 +0000147 if (!target.GetSectionLoadList().ResolveLoadAddress(ip, addr))
Chris Lattner24943d22010-06-08 16:52:24 +0000148 return -1;
149 SymbolContext sc;
Greg Claytoneea26402010-09-14 23:36:40 +0000150 if (!target.GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction | eSymbolContextSymbol, sc))
Chris Lattner24943d22010-06-08 16:52:24 +0000151 return -1;
152 if (sc.function)
153 {
154 lldb::addr_t start, len;
Greg Claytoneea26402010-09-14 23:36:40 +0000155 start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
Chris Lattner24943d22010-06-08 16:52:24 +0000156 len = sc.function->GetAddressRange().GetByteSize();
157 if (start == LLDB_INVALID_ADDRESS || len == LLDB_INVALID_ADDRESS)
158 return -1;
159 *low = start;
160 *high = start + len;
161 return UNW_ESUCCESS;
162 }
163 if (sc.symbol)
164 {
165 lldb::addr_t start, len;
Greg Claytoneea26402010-09-14 23:36:40 +0000166 start = sc.symbol->GetAddressRangeRef().GetBaseAddress().GetLoadAddress(&target);
Chris Lattner24943d22010-06-08 16:52:24 +0000167 len = sc.symbol->GetAddressRangeRef().GetByteSize();
168 if (start == LLDB_INVALID_ADDRESS)
169 return -1;
170 *low = start;
171 if (len != LLDB_INVALID_ADDRESS)
172 *high = start + len;
173 else
174 *high = 0;
175 return UNW_ESUCCESS;
176 }
177 return -1;
178}
179
180static int
181access_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)
182{
183 if (arg == 0)
184 return -1;
185 Thread *th = (Thread *) arg;
186 /* FIXME Only support reading for now. */
187 if (write == 1)
188 return -1;
189
190 Error error;
191 if (th->GetProcess().ReadMemory (addr, valp, extent, error) != extent)
192 return -1;
193 return UNW_ESUCCESS;
194}
195
196
197static int
Greg Clayton54e7afa2010-07-09 20:39:50 +0000198reg_info
199(
200 lldb_private::unw_addr_space_t as,
201 lldb_private::unw_regnum_t regnum,
202 lldb_private::unw_regtype_t *type,
203 char *buf,
204 size_t buflen,
205 void *arg
206)
Chris Lattner24943d22010-06-08 16:52:24 +0000207{
208 if (arg == 0)
209 return -1;
210 Thread *th = (Thread *) arg;
211 RegisterContext *regc = th->GetRegisterContext();
212 if (regnum > regc->GetRegisterCount())
213 {
214 *type = UNW_NOT_A_REG;
215 return UNW_ESUCCESS;
216 }
217
218 const char *name = regc->GetRegisterName (regnum);
219 if (name == NULL)
220 {
221 *type = UNW_NOT_A_REG;
222 return UNW_ESUCCESS;
223 }
224 strlcpy (buf, name, buflen);
225
226 const lldb::RegisterInfo *reginfo = regc->GetRegisterInfoAtIndex (regnum);
227 if (reginfo == NULL || reginfo->encoding == eEncodingInvalid)
228 {
229 *type = UNW_NOT_A_REG;
230 return UNW_ESUCCESS;
231 }
232 if (reginfo->encoding == eEncodingUint || reginfo->encoding == eEncodingSint)
233 *type = UNW_INTEGER_REG;
234 if (reginfo->encoding == eEncodingIEEE754)
235 *type = UNW_FLOATING_POINT_REG;
236 if (reginfo->encoding == eEncodingVector)
237 *type = UNW_VECTOR_REG;
238
239 return UNW_ESUCCESS;
240}
241
242
243static int
244read_byte_for_edis (uint8_t *buf, uint64_t addr, void *arg)
245{
246 if (arg == 0)
247 return -1;
248 Thread *th = (Thread *) arg;
249 DataBufferHeap onebyte(1, 0);
250 Error error;
251 if (th->GetProcess().ReadMemory (addr, onebyte.GetBytes(), onebyte.GetByteSize(), error) != 1)
252 return -1;
253 *buf = onebyte.GetBytes()[0];
254 return UNW_ESUCCESS;
255}
256
257static int
258instruction_length (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, int *length, void *arg)
259{
260 EDDisassemblerRef disasm;
261 EDInstRef cur_insn;
262
263 if (arg == 0)
264 return -1;
Greg Claytoncf015052010-06-11 03:25:34 +0000265 Thread *thread = (Thread *) arg;
Greg Claytoneea26402010-09-14 23:36:40 +0000266 Target &target = thread->GetProcess().GetTarget();
267
268 const ArchSpec::CPU arch_cpu = target.GetArchitecture ().GetGenericCPUType();
Greg Claytoncf015052010-06-11 03:25:34 +0000269
270 if (arch_cpu == ArchSpec::eCPU_i386)
Chris Lattner24943d22010-06-08 16:52:24 +0000271 {
272 if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
273 return -1;
274 }
Greg Claytoncf015052010-06-11 03:25:34 +0000275 else if (arch_cpu == ArchSpec::eCPU_x86_64)
Chris Lattner24943d22010-06-08 16:52:24 +0000276 {
277 if (EDGetDisassembler (&disasm, "x86_64-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
278 return -1;
279 }
280 else
281 {
282 return -1;
283 }
284
285 if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr, arg) != 1)
286 return -1;
287 *length = EDInstByteSize (cur_insn);
288 EDReleaseInst (cur_insn);
289 return UNW_ESUCCESS;
290}
291
292lldb_private::unw_accessors_t
293get_macosx_libunwind_callbacks () {
294 lldb_private::unw_accessors_t ap;
295 bzero (&ap, sizeof (lldb_private::unw_accessors_t));
296 ap.find_proc_info = NULL;
297 ap.put_unwind_info = NULL;
298 ap.get_dyn_info_list_addr = NULL;
299 ap.find_image_info = find_image_info;
300 ap.access_mem = NULL;
301 ap.access_reg = access_reg;
302 ap.access_fpreg = NULL;
303 ap.access_vecreg = NULL;
304 ap.resume = NULL;
305 ap.get_proc_name = get_proc_name;
306 ap.get_proc_bounds = get_proc_bounds;
307 ap.access_raw = access_raw;
308 ap.reg_info = reg_info;
309 ap.proc_is_sigtramp = NULL;
310 ap.proc_is_inferior_function_call = NULL;
311 ap.access_reg_inf_func_call = NULL;
312 ap.instruction_length = instruction_length;
313 return ap;
314}
315
316
317} // namespace lldb_private
318
319#endif // #if defined(__cplusplus)
320#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_cpp_