blob: ebf2a093fc46b992c7b8356b13d752149a318579 [file] [log] [blame]
Jim Ingham22777012010-09-23 02:01:19 +00001//===-- ItaniumABILanguageRuntime.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#include "ItaniumABILanguageRuntime.h"
11
Sean Callananf2115102010-11-03 22:19:38 +000012#include "lldb/Breakpoint/BreakpointLocation.h"
Jim Ingham22777012010-09-23 02:01:19 +000013#include "lldb/Core/ConstString.h"
14#include "lldb/Core/Error.h"
15#include "lldb/Core/Module.h"
16#include "lldb/Core/PluginManager.h"
17#include "lldb/Core/Scalar.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000018#include "lldb/Core/ValueObject.h"
19#include "lldb/Core/ValueObjectMemory.h"
Jim Ingham22777012010-09-23 02:01:19 +000020#include "lldb/Symbol/ClangASTContext.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Target/RegisterContext.h"
Sean Callananf2115102010-11-03 22:19:38 +000023#include "lldb/Target/StopInfo.h"
Jim Ingham22777012010-09-23 02:01:19 +000024#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27#include <vector>
28
29using namespace lldb;
30using namespace lldb_private;
31
32static const char *pluginName = "ItaniumABILanguageRuntime";
33static const char *pluginDesc = "Itanium ABI for the C++ language";
34static const char *pluginShort = "language.itanium";
Jim Ingham78a685a2011-04-16 00:01:13 +000035static const char *vtable_demangled_prefix = "vtable for ";
Jim Ingham22777012010-09-23 02:01:19 +000036
Jim Ingham78a685a2011-04-16 00:01:13 +000037bool
38ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
Jim Ingham5a369122010-09-28 01:25:32 +000039{
Greg Clayton007d5be2011-05-30 00:49:24 +000040 return in_value.IsPossibleCPlusPlusDynamicType();
Jim Ingham78a685a2011-04-16 00:01:13 +000041}
42
43bool
Jim Ingham2837b762011-05-04 03:43:18 +000044ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
45 lldb::DynamicValueType use_dynamic,
46 TypeAndOrName &class_type_or_name,
47 Address &dynamic_address)
Jim Ingham78a685a2011-04-16 00:01:13 +000048{
49 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
50 // in the object. That will point to the "address point" within the vtable (not the beginning of the
51 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name
52 // demangled will contain the full class name.
53 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the
54 // start of the value object which holds the dynamic type.
55 //
56
57 // Only a pointer or reference type can have a different dynamic and static type:
58 if (CouldHaveDynamicValue (in_value))
59 {
60 // FIXME: Can we get the Clang Type and ask it if the thing is really virtual? That would avoid false positives,
61 // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong.
62
63 // First job, pull out the address at 0 offset from the object.
64 AddressType address_type;
Enrico Granata9128ee22011-09-06 19:20:51 +000065 lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
Jim Ingham78a685a2011-04-16 00:01:13 +000066 if (original_ptr == LLDB_INVALID_ADDRESS)
67 return false;
Greg Claytoncc4d0142012-02-17 07:49:44 +000068
69 ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
70
71 Target *target = exe_ctx.GetTargetPtr();
72 Process *process = exe_ctx.GetProcessPtr();
Jim Ingham78a685a2011-04-16 00:01:13 +000073
74 char memory_buffer[16];
75 DataExtractor data(memory_buffer, sizeof(memory_buffer),
76 process->GetByteOrder(),
77 process->GetAddressByteSize());
78 size_t address_byte_size = process->GetAddressByteSize();
79 Error error;
80 size_t bytes_read = process->ReadMemory (original_ptr,
81 memory_buffer,
82 address_byte_size,
83 error);
84 if (!error.Success() || (bytes_read != address_byte_size))
85 {
86 return false;
87 }
88
89 uint32_t offset_ptr = 0;
90 lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
91
92 if (offset_ptr == 0)
93 return false;
94
95 // Now find the symbol that contains this address:
96
97 SymbolContext sc;
98 Address address_point_address;
99 if (target && !target->GetSectionLoadList().IsEmpty())
100 {
101 if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
102 {
103 target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
104 Symbol *symbol = sc.symbol;
105 if (symbol != NULL)
106 {
107 const char *name = symbol->GetMangled().GetDemangledName().AsCString();
108 if (strstr(name, vtable_demangled_prefix) == name)
109 {
110 // We are a C++ class, that's good. Get the class name and look it up:
111 const char *class_name = name + strlen(vtable_demangled_prefix);
Jim Ingham61be0902011-05-02 18:13:59 +0000112 class_type_or_name.SetName (class_name);
Jim Ingham78a685a2011-04-16 00:01:13 +0000113 TypeList class_types;
114 uint32_t num_matches = target->GetImages().FindTypes (sc,
115 ConstString(class_name),
116 true,
117 UINT32_MAX,
118 class_types);
119 if (num_matches == 1)
120 {
Jim Ingham61be0902011-05-02 18:13:59 +0000121 class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
Jim Ingham78a685a2011-04-16 00:01:13 +0000122 }
123 else if (num_matches > 1)
124 {
Jim Ingham61be0902011-05-02 18:13:59 +0000125 for (size_t i = 0; i < num_matches; i++)
126 {
127 lldb::TypeSP this_type(class_types.GetTypeAtIndex(i));
128 if (this_type)
129 {
130 if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType()))
131 {
132 // There can only be one type with a given name,
133 // so we've just found duplicate definitions, and this
134 // one will do as well as any other.
135 // We don't consider something to have a dynamic type if
136 // it is the same as the static type. So compare against
137 // the value we were handed:
138
139 clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
140 clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
141 if (in_ast_ctx != this_ast_ctx
142 || !ClangASTContext::AreTypesSame (in_ast_ctx,
143 in_value.GetClangType(),
144 this_type->GetClangFullType()))
145 {
146 class_type_or_name.SetTypeSP (this_type);
147 return true;
148 }
149 return false;
150 }
151 }
152 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000153 }
Jim Ingham61be0902011-05-02 18:13:59 +0000154 else
Jim Ingham78a685a2011-04-16 00:01:13 +0000155 return false;
156
157 // The offset_to_top is two pointers above the address.
158 Address offset_to_top_address = address_point_address;
159 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
160 offset_to_top_address.Slide (slide);
161
162 Error error;
163 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
164
165 size_t bytes_read = process->ReadMemory (offset_to_top_location,
166 memory_buffer,
167 address_byte_size,
168 error);
169
170 if (!error.Success() || (bytes_read != address_byte_size))
171 {
172 return false;
173 }
174
175 offset_ptr = 0;
176 int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
177
178 // So the dynamic type is a value that starts at offset_to_top
179 // above the original address.
180 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
181 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
182 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000183 dynamic_address.SetRawAddress(dynamic_addr);
Jim Ingham78a685a2011-04-16 00:01:13 +0000184 }
185 return true;
186 }
187 }
188 }
189 }
190
191 }
192
193 return false;
Jim Ingham5a369122010-09-28 01:25:32 +0000194}
195
196bool
197ItaniumABILanguageRuntime::IsVTableName (const char *name)
198{
199 if (name == NULL)
200 return false;
201
202 // Can we maybe ask Clang about this?
203 if (strstr (name, "_vptr$") == name)
204 return true;
205 else
206 return false;
207}
208
Jim Ingham22777012010-09-23 02:01:19 +0000209//------------------------------------------------------------------
210// Static Functions
211//------------------------------------------------------------------
Jim Ingham133e0fb2012-03-03 02:05:11 +0000212LanguageRuntime *
Jim Ingham22777012010-09-23 02:01:19 +0000213ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
214{
215 // FIXME: We have to check the process and make sure we actually know that this process supports
216 // the Itanium ABI.
217 if (language == eLanguageTypeC_plus_plus)
218 return new ItaniumABILanguageRuntime (process);
219 else
220 return NULL;
221}
222
223void
224ItaniumABILanguageRuntime::Initialize()
225{
226 PluginManager::RegisterPlugin (pluginName,
227 pluginDesc,
228 CreateInstance);
229}
230
231void
232ItaniumABILanguageRuntime::Terminate()
233{
234 PluginManager::UnregisterPlugin (CreateInstance);
235}
236
237//------------------------------------------------------------------
238// PluginInterface protocol
239//------------------------------------------------------------------
240const char *
241ItaniumABILanguageRuntime::GetPluginName()
242{
243 return pluginName;
244}
245
246const char *
247ItaniumABILanguageRuntime::GetShortPluginName()
248{
249 return pluginShort;
250}
251
252uint32_t
253ItaniumABILanguageRuntime::GetPluginVersion()
254{
255 return 1;
256}
257
Jim Ingham133e0fb2012-03-03 02:05:11 +0000258static const char *exception_names[] = {"__cxa_throw", "__cxa_allocate", "__cxa_rethrow", "__cxa_catch"};
259static const int num_throw_names = 3;
260
261BreakpointSP
262ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp, bool throw_bp, bool is_internal)
263{
264 BreakpointSP exc_breakpt_sp;
265 if (catch_bp && throw_bp)
266 exc_breakpt_sp = m_process->GetTarget().CreateBreakpoint (NULL,
267 NULL,
268 exception_names,
269 sizeof (exception_names)/sizeof (char *),
270 eFunctionNameTypeBase,
271 is_internal,
272 eLazyBoolNo);
273 else if (throw_bp)
274 exc_breakpt_sp = m_process->GetTarget().CreateBreakpoint (NULL,
275 NULL,
276 exception_names,
277 num_throw_names,
278 eFunctionNameTypeBase,
279 is_internal,
280 eLazyBoolNo);
281 else if (catch_bp)
282 exc_breakpt_sp = m_process->GetTarget().CreateBreakpoint (NULL,
283 NULL,
284 exception_names + num_throw_names,
285 sizeof (exception_names)/sizeof (char *) - num_throw_names,
286 eFunctionNameTypeBase,
287 is_internal,
288 eLazyBoolNo);
289
290 return exc_breakpt_sp;
291}
292
Jim Ingham22777012010-09-23 02:01:19 +0000293void
Sean Callananf2115102010-11-03 22:19:38 +0000294ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
295{
296 if (!m_process)
297 return;
298
Jim Ingham133e0fb2012-03-03 02:05:11 +0000299 const bool catch_bp = false;
300 const bool throw_bp = true;
301 const bool is_internal = true;
302
Sean Callananf2115102010-11-03 22:19:38 +0000303 if (!m_cxx_exception_bp_sp)
Jim Ingham133e0fb2012-03-03 02:05:11 +0000304 m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, is_internal);
Jim Inghame3846fd2011-07-23 00:12:05 +0000305 else
306 m_cxx_exception_bp_sp->SetEnabled (true);
Sean Callananf2115102010-11-03 22:19:38 +0000307
Sean Callananf2115102010-11-03 22:19:38 +0000308}
309
310void
311ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
312{
313 if (!m_process)
314 return;
315
316 if (m_cxx_exception_bp_sp.get())
317 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000318 m_cxx_exception_bp_sp->SetEnabled (false);
Jim Ingham133e0fb2012-03-03 02:05:11 +0000319 }
Sean Callananf2115102010-11-03 22:19:38 +0000320}
321
322bool
323ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
324{
325 if (!m_process)
326 return false;
327
328 if (!stop_reason ||
329 stop_reason->GetStopReason() != eStopReasonBreakpoint)
330 return false;
331
332 uint64_t break_site_id = stop_reason->GetValue();
333 lldb::BreakpointSiteSP bp_site_sp = m_process->GetBreakpointSiteList().FindByID(break_site_id);
334
335 if (!bp_site_sp)
336 return false;
337
338 uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
339
Sean Callananf2115102010-11-03 22:19:38 +0000340 break_id_t cxx_exception_bid;
341
Jim Ingham133e0fb2012-03-03 02:05:11 +0000342 if (!m_cxx_exception_bp_sp)
343 return false;
344
345 cxx_exception_bid = m_cxx_exception_bp_sp->GetID();
346
Sean Callananf2115102010-11-03 22:19:38 +0000347 for (uint32_t i = 0; i < num_owners; i++)
348 {
349 break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID();
350
Jim Ingham133e0fb2012-03-03 02:05:11 +0000351 if (bid == cxx_exception_bid)
Sean Callananf2115102010-11-03 22:19:38 +0000352 return true;
353 }
354
355 return false;
356}