blob: 902e22c34310303af7c60deafadd6608644982ec [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;
72 Thread *th = (Thread *) arg;
73 Address addr;
74 if (!th->GetProcess().ResolveLoadAddress(ip, addr))
75 return -1;
76
77 SymbolContext sc;
78 if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction, sc))
79 return -1;
80 if (!sc.symbol)
81 return -1;
82 strlcpy (bufp, sc.symbol->GetMangled().GetMangledName().AsCString(""), buf_len);
83 if (offp)
84 *offp = addr.GetLoadAddress(&th->GetProcess()) - sc.symbol->GetValue().GetLoadAddress(&th->GetProcess());
85 return UNW_ESUCCESS;
86}
87
88static int
89find_image_info (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t load_addr, lldb_private::unw_word_t *mh,
90 lldb_private::unw_word_t *text_start, lldb_private::unw_word_t *text_end,
91 lldb_private::unw_word_t *eh_frame, lldb_private::unw_word_t *eh_frame_len,
92 lldb_private::unw_word_t *compact_unwind_start, lldb_private::unw_word_t *compact_unwind_len, void *arg)
93{
94 if (arg == 0)
95 return -1;
96 Thread *th = (Thread *) arg;
97 Address addr;
98 if (!th->GetProcess().ResolveLoadAddress(load_addr, addr))
99 return -1;
100
101 SymbolContext sc;
102 if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextModule, sc))
103 return -1;
104
105 SectionList *sl = sc.module_sp->GetObjectFile()->GetSectionList();
106 static ConstString g_segment_name_TEXT("__TEXT");
107 SectionSP text_segment_sp(sl->FindSectionByName(g_segment_name_TEXT));
108 if (!text_segment_sp)
109 return -1;
110
111 *mh = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
112 *text_start = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
113 *text_end = *text_start + text_segment_sp->GetByteSize();
114
115 static ConstString g_section_name_eh_frame ("__eh_frame");
116 SectionSP eh_frame_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_eh_frame);
117 if (eh_frame_section_sp.get()) {
118 *eh_frame = eh_frame_section_sp->GetLoadBaseAddress (&th->GetProcess());
119 *eh_frame_len = eh_frame_section_sp->GetByteSize();
120 } else {
121 *eh_frame = 0;
122 *eh_frame_len = 0;
123 }
124
125 static ConstString g_section_name_unwind_info ("__unwind_info");
126 SectionSP unwind_info_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_unwind_info);
127 if (unwind_info_section_sp.get()) {
128 *compact_unwind_start = unwind_info_section_sp->GetLoadBaseAddress (&th->GetProcess());
129 *compact_unwind_len = unwind_info_section_sp->GetByteSize();
130 } else {
131 *compact_unwind_start = 0;
132 *compact_unwind_len = 0;
133 }
134 return UNW_ESUCCESS;
135}
136
137static int
138get_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)
139{
140 if (arg == 0)
141 return -1;
142 Thread *th = (Thread *) arg;
143 Address addr;
144 if (!th->GetProcess().ResolveLoadAddress(ip, addr))
145 return -1;
146 SymbolContext sc;
147 if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction | eSymbolContextSymbol, sc))
148 return -1;
149 if (sc.function)
150 {
151 lldb::addr_t start, len;
152 start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(&th->GetProcess());
153 len = sc.function->GetAddressRange().GetByteSize();
154 if (start == LLDB_INVALID_ADDRESS || len == LLDB_INVALID_ADDRESS)
155 return -1;
156 *low = start;
157 *high = start + len;
158 return UNW_ESUCCESS;
159 }
160 if (sc.symbol)
161 {
162 lldb::addr_t start, len;
163 start = sc.symbol->GetAddressRangeRef().GetBaseAddress().GetLoadAddress(&th->GetProcess());
164 len = sc.symbol->GetAddressRangeRef().GetByteSize();
165 if (start == LLDB_INVALID_ADDRESS)
166 return -1;
167 *low = start;
168 if (len != LLDB_INVALID_ADDRESS)
169 *high = start + len;
170 else
171 *high = 0;
172 return UNW_ESUCCESS;
173 }
174 return -1;
175}
176
177static int
178access_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)
179{
180 if (arg == 0)
181 return -1;
182 Thread *th = (Thread *) arg;
183 /* FIXME Only support reading for now. */
184 if (write == 1)
185 return -1;
186
187 Error error;
188 if (th->GetProcess().ReadMemory (addr, valp, extent, error) != extent)
189 return -1;
190 return UNW_ESUCCESS;
191}
192
193
194static int
Greg Clayton54e7afa2010-07-09 20:39:50 +0000195reg_info
196(
197 lldb_private::unw_addr_space_t as,
198 lldb_private::unw_regnum_t regnum,
199 lldb_private::unw_regtype_t *type,
200 char *buf,
201 size_t buflen,
202 void *arg
203)
Chris Lattner24943d22010-06-08 16:52:24 +0000204{
205 if (arg == 0)
206 return -1;
207 Thread *th = (Thread *) arg;
208 RegisterContext *regc = th->GetRegisterContext();
209 if (regnum > regc->GetRegisterCount())
210 {
211 *type = UNW_NOT_A_REG;
212 return UNW_ESUCCESS;
213 }
214
215 const char *name = regc->GetRegisterName (regnum);
216 if (name == NULL)
217 {
218 *type = UNW_NOT_A_REG;
219 return UNW_ESUCCESS;
220 }
221 strlcpy (buf, name, buflen);
222
223 const lldb::RegisterInfo *reginfo = regc->GetRegisterInfoAtIndex (regnum);
224 if (reginfo == NULL || reginfo->encoding == eEncodingInvalid)
225 {
226 *type = UNW_NOT_A_REG;
227 return UNW_ESUCCESS;
228 }
229 if (reginfo->encoding == eEncodingUint || reginfo->encoding == eEncodingSint)
230 *type = UNW_INTEGER_REG;
231 if (reginfo->encoding == eEncodingIEEE754)
232 *type = UNW_FLOATING_POINT_REG;
233 if (reginfo->encoding == eEncodingVector)
234 *type = UNW_VECTOR_REG;
235
236 return UNW_ESUCCESS;
237}
238
239
240static int
241read_byte_for_edis (uint8_t *buf, uint64_t addr, void *arg)
242{
243 if (arg == 0)
244 return -1;
245 Thread *th = (Thread *) arg;
246 DataBufferHeap onebyte(1, 0);
247 Error error;
248 if (th->GetProcess().ReadMemory (addr, onebyte.GetBytes(), onebyte.GetByteSize(), error) != 1)
249 return -1;
250 *buf = onebyte.GetBytes()[0];
251 return UNW_ESUCCESS;
252}
253
254static int
255instruction_length (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, int *length, void *arg)
256{
257 EDDisassemblerRef disasm;
258 EDInstRef cur_insn;
259
260 if (arg == 0)
261 return -1;
Greg Claytoncf015052010-06-11 03:25:34 +0000262 Thread *thread = (Thread *) arg;
Chris Lattner24943d22010-06-08 16:52:24 +0000263
Greg Claytoncf015052010-06-11 03:25:34 +0000264 const ArchSpec::CPU arch_cpu = thread->GetProcess().GetTarget().GetArchitecture ().GetGenericCPUType();
265
266 if (arch_cpu == ArchSpec::eCPU_i386)
Chris Lattner24943d22010-06-08 16:52:24 +0000267 {
268 if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
269 return -1;
270 }
Greg Claytoncf015052010-06-11 03:25:34 +0000271 else if (arch_cpu == ArchSpec::eCPU_x86_64)
Chris Lattner24943d22010-06-08 16:52:24 +0000272 {
273 if (EDGetDisassembler (&disasm, "x86_64-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
274 return -1;
275 }
276 else
277 {
278 return -1;
279 }
280
281 if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr, arg) != 1)
282 return -1;
283 *length = EDInstByteSize (cur_insn);
284 EDReleaseInst (cur_insn);
285 return UNW_ESUCCESS;
286}
287
288lldb_private::unw_accessors_t
289get_macosx_libunwind_callbacks () {
290 lldb_private::unw_accessors_t ap;
291 bzero (&ap, sizeof (lldb_private::unw_accessors_t));
292 ap.find_proc_info = NULL;
293 ap.put_unwind_info = NULL;
294 ap.get_dyn_info_list_addr = NULL;
295 ap.find_image_info = find_image_info;
296 ap.access_mem = NULL;
297 ap.access_reg = access_reg;
298 ap.access_fpreg = NULL;
299 ap.access_vecreg = NULL;
300 ap.resume = NULL;
301 ap.get_proc_name = get_proc_name;
302 ap.get_proc_bounds = get_proc_bounds;
303 ap.access_raw = access_raw;
304 ap.reg_info = reg_info;
305 ap.proc_is_sigtramp = NULL;
306 ap.proc_is_inferior_function_call = NULL;
307 ap.access_reg_inf_func_call = NULL;
308 ap.instruction_length = instruction_length;
309 return ap;
310}
311
312
313} // namespace lldb_private
314
315#endif // #if defined(__cplusplus)
316#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_cpp_