blob: 0c9efcc8d8a814b6d4a7fcec4ca36d3feb6b6276 [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"
Greg Clayton726bc522012-03-28 17:13:26 +000015#include "lldb/Core/Log.h"
Jim Ingham22777012010-09-23 02:01:19 +000016#include "lldb/Core/Module.h"
17#include "lldb/Core/PluginManager.h"
18#include "lldb/Core/Scalar.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000019#include "lldb/Core/ValueObject.h"
20#include "lldb/Core/ValueObjectMemory.h"
Jim Ingham22777012010-09-23 02:01:19 +000021#include "lldb/Symbol/ClangASTContext.h"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/RegisterContext.h"
Sean Callananf2115102010-11-03 22:19:38 +000024#include "lldb/Target/StopInfo.h"
Jim Ingham22777012010-09-23 02:01:19 +000025#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27
28#include <vector>
29
30using namespace lldb;
31using namespace lldb_private;
32
33static const char *pluginName = "ItaniumABILanguageRuntime";
34static const char *pluginDesc = "Itanium ABI for the C++ language";
35static const char *pluginShort = "language.itanium";
Jim Ingham78a685a2011-04-16 00:01:13 +000036static const char *vtable_demangled_prefix = "vtable for ";
Jim Ingham22777012010-09-23 02:01:19 +000037
Jim Ingham78a685a2011-04-16 00:01:13 +000038bool
39ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
Jim Ingham5a369122010-09-28 01:25:32 +000040{
Greg Clayton007d5be2011-05-30 00:49:24 +000041 return in_value.IsPossibleCPlusPlusDynamicType();
Jim Ingham78a685a2011-04-16 00:01:13 +000042}
43
44bool
Jim Ingham2837b762011-05-04 03:43:18 +000045ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
46 lldb::DynamicValueType use_dynamic,
47 TypeAndOrName &class_type_or_name,
48 Address &dynamic_address)
Jim Ingham78a685a2011-04-16 00:01:13 +000049{
50 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
51 // in the object. That will point to the "address point" within the vtable (not the beginning of the
52 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name
53 // demangled will contain the full class name.
54 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the
55 // start of the value object which holds the dynamic type.
56 //
57
58 // Only a pointer or reference type can have a different dynamic and static type:
59 if (CouldHaveDynamicValue (in_value))
60 {
Jim Ingham78a685a2011-04-16 00:01:13 +000061 // First job, pull out the address at 0 offset from the object.
62 AddressType address_type;
Enrico Granata9128ee22011-09-06 19:20:51 +000063 lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
Jim Ingham78a685a2011-04-16 00:01:13 +000064 if (original_ptr == LLDB_INVALID_ADDRESS)
65 return false;
Greg Claytoncc4d0142012-02-17 07:49:44 +000066
67 ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
68
69 Target *target = exe_ctx.GetTargetPtr();
70 Process *process = exe_ctx.GetProcessPtr();
Jim Ingham78a685a2011-04-16 00:01:13 +000071
72 char memory_buffer[16];
73 DataExtractor data(memory_buffer, sizeof(memory_buffer),
74 process->GetByteOrder(),
75 process->GetAddressByteSize());
76 size_t address_byte_size = process->GetAddressByteSize();
77 Error error;
78 size_t bytes_read = process->ReadMemory (original_ptr,
79 memory_buffer,
80 address_byte_size,
81 error);
82 if (!error.Success() || (bytes_read != address_byte_size))
83 {
84 return false;
85 }
86
87 uint32_t offset_ptr = 0;
88 lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
89
90 if (offset_ptr == 0)
91 return false;
92
93 // Now find the symbol that contains this address:
94
95 SymbolContext sc;
96 Address address_point_address;
97 if (target && !target->GetSectionLoadList().IsEmpty())
98 {
99 if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
100 {
101 target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
102 Symbol *symbol = sc.symbol;
103 if (symbol != NULL)
104 {
105 const char *name = symbol->GetMangled().GetDemangledName().AsCString();
106 if (strstr(name, vtable_demangled_prefix) == name)
107 {
Greg Clayton726bc522012-03-28 17:13:26 +0000108 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
109 if (log)
110 log->Printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n",
111 original_ptr,
112 in_value.GetTypeName().GetCString(),
113 name);
114 // We are a C++ class, that's good. Get the class name and look it up:
Jim Ingham78a685a2011-04-16 00:01:13 +0000115 const char *class_name = name + strlen(vtable_demangled_prefix);
Jim Ingham61be0902011-05-02 18:13:59 +0000116 class_type_or_name.SetName (class_name);
Greg Clayton84db9102012-03-26 23:03:23 +0000117 const bool exact_match = true;
Jim Ingham78a685a2011-04-16 00:01:13 +0000118 TypeList class_types;
Greg Clayton29399a22012-04-06 17:41:13 +0000119
120 uint32_t num_matches = target->GetImages().FindTypes (sc,
121 ConstString(class_name),
122 exact_match,
123 UINT32_MAX,
124 class_types);
125
126 lldb::TypeSP type_sp;
Greg Clayton84db9102012-03-26 23:03:23 +0000127 if (num_matches == 0)
128 {
Greg Clayton726bc522012-03-28 17:13:26 +0000129 if (log)
130 log->Printf("0x%16.16llx: is not dynamic\n", original_ptr);
Greg Clayton84db9102012-03-26 23:03:23 +0000131 return false;
132 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000133 if (num_matches == 1)
134 {
Greg Clayton29399a22012-04-06 17:41:13 +0000135 type_sp = class_types.GetTypeAtIndex(0);
Greg Clayton726bc522012-03-28 17:13:26 +0000136 if (log)
137 log->Printf ("0x%16.16llx: static-type = '%s' has dynamic type: uid={0x%llx}, type-name='%s'\n",
138 original_ptr,
139 in_value.GetTypeName().AsCString(),
140 type_sp->GetID(),
141 type_sp->GetName().GetCString());
142
Jim Ingham61be0902011-05-02 18:13:59 +0000143 class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
Jim Ingham78a685a2011-04-16 00:01:13 +0000144 }
145 else if (num_matches > 1)
146 {
Greg Clayton29399a22012-04-06 17:41:13 +0000147 size_t i;
148 if (log)
Jim Ingham61be0902011-05-02 18:13:59 +0000149 {
Greg Clayton29399a22012-04-06 17:41:13 +0000150 for (i = 0; i < num_matches; i++)
Jim Ingham61be0902011-05-02 18:13:59 +0000151 {
Greg Clayton29399a22012-04-06 17:41:13 +0000152 type_sp = class_types.GetTypeAtIndex(i);
153 if (type_sp)
154 {
155 if (log)
156 log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n",
157 original_ptr,
158 in_value.GetTypeName().AsCString(),
159 type_sp->GetID(),
160 type_sp->GetName().GetCString());
161 }
Jim Ingham61be0902011-05-02 18:13:59 +0000162 }
163 }
Greg Clayton29399a22012-04-06 17:41:13 +0000164
165 for (i = 0; i < num_matches; i++)
166 {
167 type_sp = class_types.GetTypeAtIndex(i);
168 if (type_sp)
169 {
170 if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
171 {
172 if (log)
173 log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%llx}, type-name='%s'\n",
174 original_ptr,
175 in_value.GetTypeName().AsCString(),
176 type_sp->GetID(),
177 type_sp->GetName().GetCString());
178 class_type_or_name.SetTypeSP(type_sp);
179 break;
180 }
181 }
182 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000183
Greg Clayton29399a22012-04-06 17:41:13 +0000184 if (i == num_matches)
185 {
186 if (log)
187 log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
188 original_ptr,
189 in_value.GetTypeName().AsCString());
190 return false;
191 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000192 }
Greg Clayton29399a22012-04-06 17:41:13 +0000193
194 // There can only be one type with a given name,
195 // so we've just found duplicate definitions, and this
196 // one will do as well as any other.
197 // We don't consider something to have a dynamic type if
198 // it is the same as the static type. So compare against
199 // the value we were handed.
200 if (type_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +0000201 {
Greg Clayton29399a22012-04-06 17:41:13 +0000202 clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
203 clang::ASTContext *this_ast_ctx = type_sp->GetClangAST ();
204 if (in_ast_ctx == this_ast_ctx)
205 {
206 if (ClangASTContext::AreTypesSame (in_ast_ctx,
207 in_value.GetClangType(),
208 type_sp->GetClangFullType()))
209 {
210 // The dynamic type we found was the same type,
211 // so we don't have a dynamic type here...
212 return false;
213 }
214 }
215
216 // The offset_to_top is two pointers above the address.
217 Address offset_to_top_address = address_point_address;
218 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
219 offset_to_top_address.Slide (slide);
220
221 Error error;
222 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
223
224 size_t bytes_read = process->ReadMemory (offset_to_top_location,
225 memory_buffer,
226 address_byte_size,
227 error);
228
229 if (!error.Success() || (bytes_read != address_byte_size))
230 {
231 return false;
232 }
233
234 offset_ptr = 0;
235 int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
236
237 // So the dynamic type is a value that starts at offset_to_top
238 // above the original address.
239 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
240 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
241 {
242 dynamic_address.SetRawAddress(dynamic_addr);
243 }
244 return true;
Jim Ingham78a685a2011-04-16 00:01:13 +0000245 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000246 }
247 }
248 }
249 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000250 }
251
252 return false;
Jim Ingham5a369122010-09-28 01:25:32 +0000253}
254
255bool
256ItaniumABILanguageRuntime::IsVTableName (const char *name)
257{
258 if (name == NULL)
259 return false;
260
261 // Can we maybe ask Clang about this?
262 if (strstr (name, "_vptr$") == name)
263 return true;
264 else
265 return false;
266}
267
Jim Ingham22777012010-09-23 02:01:19 +0000268//------------------------------------------------------------------
269// Static Functions
270//------------------------------------------------------------------
Jim Ingham133e0fb2012-03-03 02:05:11 +0000271LanguageRuntime *
Jim Ingham22777012010-09-23 02:01:19 +0000272ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
273{
274 // FIXME: We have to check the process and make sure we actually know that this process supports
275 // the Itanium ABI.
276 if (language == eLanguageTypeC_plus_plus)
277 return new ItaniumABILanguageRuntime (process);
278 else
279 return NULL;
280}
281
282void
283ItaniumABILanguageRuntime::Initialize()
284{
285 PluginManager::RegisterPlugin (pluginName,
286 pluginDesc,
287 CreateInstance);
288}
289
290void
291ItaniumABILanguageRuntime::Terminate()
292{
293 PluginManager::UnregisterPlugin (CreateInstance);
294}
295
296//------------------------------------------------------------------
297// PluginInterface protocol
298//------------------------------------------------------------------
299const char *
300ItaniumABILanguageRuntime::GetPluginName()
301{
302 return pluginName;
303}
304
305const char *
306ItaniumABILanguageRuntime::GetShortPluginName()
307{
308 return pluginShort;
309}
310
311uint32_t
312ItaniumABILanguageRuntime::GetPluginVersion()
313{
314 return 1;
315}
316
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000317static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"};
Jim Ingham133e0fb2012-03-03 02:05:11 +0000318static const int num_throw_names = 3;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000319static const int num_expression_throw_names = 1;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000320
Jim Ingham219ba192012-03-05 04:47:34 +0000321BreakpointResolverSP
322ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
Jim Ingham133e0fb2012-03-03 02:05:11 +0000323{
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000324 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
325}
326
327BreakpointResolverSP
328ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
329{
Jim Ingham219ba192012-03-05 04:47:34 +0000330 BreakpointResolverSP resolver_sp;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000331 static const int total_expressions = sizeof (exception_names)/sizeof (char *);
Jim Ingham219ba192012-03-05 04:47:34 +0000332
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000333 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
334 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception
335 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
336 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
337
338 uint32_t num_expressions;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000339 if (catch_bp && throw_bp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000340 {
341 if (for_expressions)
342 num_expressions = total_expressions;
343 else
344 num_expressions = total_expressions - num_expression_throw_names;
345
Jim Ingham219ba192012-03-05 04:47:34 +0000346 resolver_sp.reset (new BreakpointResolverName (bkpt,
347 exception_names,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000348 num_expressions,
Jim Ingham219ba192012-03-05 04:47:34 +0000349 eFunctionNameTypeBase,
350 eLazyBoolNo));
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000351 }
Jim Ingham133e0fb2012-03-03 02:05:11 +0000352 else if (throw_bp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000353 {
354 if (for_expressions)
355 num_expressions = num_throw_names - num_expression_throw_names;
356 else
357 num_expressions = num_throw_names;
358
Jim Ingham219ba192012-03-05 04:47:34 +0000359 resolver_sp.reset (new BreakpointResolverName (bkpt,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000360 exception_names + 1,
361 num_expressions,
Jim Ingham219ba192012-03-05 04:47:34 +0000362 eFunctionNameTypeBase,
363 eLazyBoolNo));
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000364 }
Jim Ingham133e0fb2012-03-03 02:05:11 +0000365 else if (catch_bp)
Jim Ingham219ba192012-03-05 04:47:34 +0000366 resolver_sp.reset (new BreakpointResolverName (bkpt,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000367 exception_names,
368 total_expressions - num_throw_names,
Jim Ingham219ba192012-03-05 04:47:34 +0000369 eFunctionNameTypeBase,
370 eLazyBoolNo));
Jim Ingham133e0fb2012-03-03 02:05:11 +0000371
Jim Ingham219ba192012-03-05 04:47:34 +0000372 return resolver_sp;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000373}
374
Jim Ingham22777012010-09-23 02:01:19 +0000375void
Sean Callananf2115102010-11-03 22:19:38 +0000376ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
377{
378 if (!m_process)
379 return;
380
Jim Ingham133e0fb2012-03-03 02:05:11 +0000381 const bool catch_bp = false;
382 const bool throw_bp = true;
383 const bool is_internal = true;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000384 const bool for_expressions = true;
385
386 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
387 // stop at exception allocation as well.
Jim Ingham133e0fb2012-03-03 02:05:11 +0000388
Sean Callananf2115102010-11-03 22:19:38 +0000389 if (!m_cxx_exception_bp_sp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000390 {
391 Target &target = m_process->GetTarget();
392
393 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
394 SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL);
395
396 m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
397 }
Jim Inghame3846fd2011-07-23 00:12:05 +0000398 else
399 m_cxx_exception_bp_sp->SetEnabled (true);
Sean Callananf2115102010-11-03 22:19:38 +0000400
Sean Callananf2115102010-11-03 22:19:38 +0000401}
402
403void
404ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
405{
406 if (!m_process)
407 return;
408
409 if (m_cxx_exception_bp_sp.get())
410 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000411 m_cxx_exception_bp_sp->SetEnabled (false);
Jim Ingham133e0fb2012-03-03 02:05:11 +0000412 }
Sean Callananf2115102010-11-03 22:19:38 +0000413}
414
415bool
416ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
417{
418 if (!m_process)
419 return false;
420
421 if (!stop_reason ||
422 stop_reason->GetStopReason() != eStopReasonBreakpoint)
423 return false;
424
425 uint64_t break_site_id = stop_reason->GetValue();
Jim Ingham564d8bc22012-03-09 04:10:47 +0000426 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
427 m_cxx_exception_bp_sp->GetID());
Sean Callananf2115102010-11-03 22:19:38 +0000428
Sean Callananf2115102010-11-03 22:19:38 +0000429}