blob: 58a7ac043c5d99de7349bbb4e9cbe3582c8cb07b [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
24#include "lldb-enumerations.h"
25#include "libunwind.h"
26#include "llvm-c/EnhancedDisassembly.h"
27
28using namespace lldb;
29
30namespace lldb_private {
31
32/* Don't implement (libunwind does not use)
33 find_proc_info
34 put_unwind_info
35 get_dyn_info_list_addr
36 access_mem
37 resume
38*/
39/*
40 Should implement (not needed yet)
41 access_fpreg
42 access_vecreg
43 proc_is_sigtramp
44 proc_is_inferior_function_call
45 access_reg_inf_func_call
46*/
47
48static int
49access_reg (lldb_private::unw_addr_space_t as, lldb_private::unw_regnum_t regnum, lldb_private::unw_word_t *valp, int write, void *arg)
50{
51 if (arg == 0)
52 return -1;
53 Thread *th = (Thread *) arg;
54 /* FIXME Only support reading for now. */
55 if (write == 1)
56 return -1;
57 if (th->GetRegisterContext()->GetRegisterInfoAtIndex(regnum) == NULL)
58 return -1;
59 DataExtractor de;
60 if (!th->GetRegisterContext()->ReadRegisterBytes (regnum, de))
61 return -1;
62 memcpy (valp, de.GetDataStart(), de.GetByteSize());
63 return UNW_ESUCCESS;
64}
65
66static int
67get_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)
68{
69 if (arg == 0)
70 return -1;
71 Thread *th = (Thread *) arg;
72 Address addr;
73 if (!th->GetProcess().ResolveLoadAddress(ip, addr))
74 return -1;
75
76 SymbolContext sc;
77 if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction, sc))
78 return -1;
79 if (!sc.symbol)
80 return -1;
81 strlcpy (bufp, sc.symbol->GetMangled().GetMangledName().AsCString(""), buf_len);
82 if (offp)
83 *offp = addr.GetLoadAddress(&th->GetProcess()) - sc.symbol->GetValue().GetLoadAddress(&th->GetProcess());
84 return UNW_ESUCCESS;
85}
86
87static int
88find_image_info (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t load_addr, lldb_private::unw_word_t *mh,
89 lldb_private::unw_word_t *text_start, lldb_private::unw_word_t *text_end,
90 lldb_private::unw_word_t *eh_frame, lldb_private::unw_word_t *eh_frame_len,
91 lldb_private::unw_word_t *compact_unwind_start, lldb_private::unw_word_t *compact_unwind_len, void *arg)
92{
93 if (arg == 0)
94 return -1;
95 Thread *th = (Thread *) arg;
96 Address addr;
97 if (!th->GetProcess().ResolveLoadAddress(load_addr, addr))
98 return -1;
99
100 SymbolContext sc;
101 if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextModule, sc))
102 return -1;
103
104 SectionList *sl = sc.module_sp->GetObjectFile()->GetSectionList();
105 static ConstString g_segment_name_TEXT("__TEXT");
106 SectionSP text_segment_sp(sl->FindSectionByName(g_segment_name_TEXT));
107 if (!text_segment_sp)
108 return -1;
109
110 *mh = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
111 *text_start = text_segment_sp->GetLoadBaseAddress (&th->GetProcess());
112 *text_end = *text_start + text_segment_sp->GetByteSize();
113
114 static ConstString g_section_name_eh_frame ("__eh_frame");
115 SectionSP eh_frame_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_eh_frame);
116 if (eh_frame_section_sp.get()) {
117 *eh_frame = eh_frame_section_sp->GetLoadBaseAddress (&th->GetProcess());
118 *eh_frame_len = eh_frame_section_sp->GetByteSize();
119 } else {
120 *eh_frame = 0;
121 *eh_frame_len = 0;
122 }
123
124 static ConstString g_section_name_unwind_info ("__unwind_info");
125 SectionSP unwind_info_section_sp = text_segment_sp->GetChildren().FindSectionByName(g_section_name_unwind_info);
126 if (unwind_info_section_sp.get()) {
127 *compact_unwind_start = unwind_info_section_sp->GetLoadBaseAddress (&th->GetProcess());
128 *compact_unwind_len = unwind_info_section_sp->GetByteSize();
129 } else {
130 *compact_unwind_start = 0;
131 *compact_unwind_len = 0;
132 }
133 return UNW_ESUCCESS;
134}
135
136static int
137get_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)
138{
139 if (arg == 0)
140 return -1;
141 Thread *th = (Thread *) arg;
142 Address addr;
143 if (!th->GetProcess().ResolveLoadAddress(ip, addr))
144 return -1;
145 SymbolContext sc;
146 if (!th->GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (addr, eSymbolContextFunction | eSymbolContextSymbol, sc))
147 return -1;
148 if (sc.function)
149 {
150 lldb::addr_t start, len;
151 start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(&th->GetProcess());
152 len = sc.function->GetAddressRange().GetByteSize();
153 if (start == LLDB_INVALID_ADDRESS || len == LLDB_INVALID_ADDRESS)
154 return -1;
155 *low = start;
156 *high = start + len;
157 return UNW_ESUCCESS;
158 }
159 if (sc.symbol)
160 {
161 lldb::addr_t start, len;
162 start = sc.symbol->GetAddressRangeRef().GetBaseAddress().GetLoadAddress(&th->GetProcess());
163 len = sc.symbol->GetAddressRangeRef().GetByteSize();
164 if (start == LLDB_INVALID_ADDRESS)
165 return -1;
166 *low = start;
167 if (len != LLDB_INVALID_ADDRESS)
168 *high = start + len;
169 else
170 *high = 0;
171 return UNW_ESUCCESS;
172 }
173 return -1;
174}
175
176static int
177access_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)
178{
179 if (arg == 0)
180 return -1;
181 Thread *th = (Thread *) arg;
182 /* FIXME Only support reading for now. */
183 if (write == 1)
184 return -1;
185
186 Error error;
187 if (th->GetProcess().ReadMemory (addr, valp, extent, error) != extent)
188 return -1;
189 return UNW_ESUCCESS;
190}
191
192
193static int
194reg_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)
195{
196 if (arg == 0)
197 return -1;
198 Thread *th = (Thread *) arg;
199 RegisterContext *regc = th->GetRegisterContext();
200 if (regnum > regc->GetRegisterCount())
201 {
202 *type = UNW_NOT_A_REG;
203 return UNW_ESUCCESS;
204 }
205
206 const char *name = regc->GetRegisterName (regnum);
207 if (name == NULL)
208 {
209 *type = UNW_NOT_A_REG;
210 return UNW_ESUCCESS;
211 }
212 strlcpy (buf, name, buflen);
213
214 const lldb::RegisterInfo *reginfo = regc->GetRegisterInfoAtIndex (regnum);
215 if (reginfo == NULL || reginfo->encoding == eEncodingInvalid)
216 {
217 *type = UNW_NOT_A_REG;
218 return UNW_ESUCCESS;
219 }
220 if (reginfo->encoding == eEncodingUint || reginfo->encoding == eEncodingSint)
221 *type = UNW_INTEGER_REG;
222 if (reginfo->encoding == eEncodingIEEE754)
223 *type = UNW_FLOATING_POINT_REG;
224 if (reginfo->encoding == eEncodingVector)
225 *type = UNW_VECTOR_REG;
226
227 return UNW_ESUCCESS;
228}
229
230
231static int
232read_byte_for_edis (uint8_t *buf, uint64_t addr, void *arg)
233{
234 if (arg == 0)
235 return -1;
236 Thread *th = (Thread *) arg;
237 DataBufferHeap onebyte(1, 0);
238 Error error;
239 if (th->GetProcess().ReadMemory (addr, onebyte.GetBytes(), onebyte.GetByteSize(), error) != 1)
240 return -1;
241 *buf = onebyte.GetBytes()[0];
242 return UNW_ESUCCESS;
243}
244
245static int
246instruction_length (lldb_private::unw_addr_space_t as, lldb_private::unw_word_t addr, int *length, void *arg)
247{
248 EDDisassemblerRef disasm;
249 EDInstRef cur_insn;
250
251 if (arg == 0)
252 return -1;
253 Thread *th = (Thread *) arg;
254 const ArchSpec target_arch (th->GetProcess().GetTarget().GetArchitecture ());
255
256 if (target_arch.GetCPUType() == CPU_TYPE_I386)
257 {
258 if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
259 return -1;
260 }
261 else if (target_arch.GetCPUType() == CPU_TYPE_X86_64)
262 {
263 if (EDGetDisassembler (&disasm, "x86_64-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
264 return -1;
265 }
266 else
267 {
268 return -1;
269 }
270
271 if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr, arg) != 1)
272 return -1;
273 *length = EDInstByteSize (cur_insn);
274 EDReleaseInst (cur_insn);
275 return UNW_ESUCCESS;
276}
277
278lldb_private::unw_accessors_t
279get_macosx_libunwind_callbacks () {
280 lldb_private::unw_accessors_t ap;
281 bzero (&ap, sizeof (lldb_private::unw_accessors_t));
282 ap.find_proc_info = NULL;
283 ap.put_unwind_info = NULL;
284 ap.get_dyn_info_list_addr = NULL;
285 ap.find_image_info = find_image_info;
286 ap.access_mem = NULL;
287 ap.access_reg = access_reg;
288 ap.access_fpreg = NULL;
289 ap.access_vecreg = NULL;
290 ap.resume = NULL;
291 ap.get_proc_name = get_proc_name;
292 ap.get_proc_bounds = get_proc_bounds;
293 ap.access_raw = access_raw;
294 ap.reg_info = reg_info;
295 ap.proc_is_sigtramp = NULL;
296 ap.proc_is_inferior_function_call = NULL;
297 ap.access_reg_inf_func_call = NULL;
298 ap.instruction_length = instruction_length;
299 return ap;
300}
301
302
303} // namespace lldb_private
304
305#endif // #if defined(__cplusplus)
306#endif // #ifndef liblldb_MacOSXLibunwindCallbacks_cpp_