blob: 869868546bdd982b427e5b099486268ad0922448 [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{
Enrico Granatafd4c84e2012-05-21 16:51:35 +000041 return ClangASTContext::IsPossibleDynamicType(in_value.GetClangAST(), in_value.GetClangType(), NULL,
42 true, // check for C++
43 false); // do not check for ObjC
Jim Ingham78a685a2011-04-16 00:01:13 +000044}
45
46bool
Jim Ingham2837b762011-05-04 03:43:18 +000047ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
48 lldb::DynamicValueType use_dynamic,
49 TypeAndOrName &class_type_or_name,
50 Address &dynamic_address)
Jim Ingham78a685a2011-04-16 00:01:13 +000051{
52 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
53 // in the object. That will point to the "address point" within the vtable (not the beginning of the
54 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name
55 // demangled will contain the full class name.
56 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the
57 // start of the value object which holds the dynamic type.
58 //
59
60 // Only a pointer or reference type can have a different dynamic and static type:
61 if (CouldHaveDynamicValue (in_value))
62 {
Jim Ingham78a685a2011-04-16 00:01:13 +000063 // 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 {
Greg Clayton726bc522012-03-28 17:13:26 +0000110 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
111 if (log)
112 log->Printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n",
113 original_ptr,
114 in_value.GetTypeName().GetCString(),
115 name);
116 // We are a C++ class, that's good. Get the class name and look it up:
Jim Ingham78a685a2011-04-16 00:01:13 +0000117 const char *class_name = name + strlen(vtable_demangled_prefix);
Jim Ingham61be0902011-05-02 18:13:59 +0000118 class_type_or_name.SetName (class_name);
Greg Clayton84db9102012-03-26 23:03:23 +0000119 const bool exact_match = true;
Jim Ingham78a685a2011-04-16 00:01:13 +0000120 TypeList class_types;
Greg Clayton29399a22012-04-06 17:41:13 +0000121
122 uint32_t num_matches = target->GetImages().FindTypes (sc,
123 ConstString(class_name),
124 exact_match,
125 UINT32_MAX,
126 class_types);
127
128 lldb::TypeSP type_sp;
Greg Clayton84db9102012-03-26 23:03:23 +0000129 if (num_matches == 0)
130 {
Greg Clayton726bc522012-03-28 17:13:26 +0000131 if (log)
132 log->Printf("0x%16.16llx: is not dynamic\n", original_ptr);
Greg Clayton84db9102012-03-26 23:03:23 +0000133 return false;
134 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000135 if (num_matches == 1)
136 {
Greg Clayton29399a22012-04-06 17:41:13 +0000137 type_sp = class_types.GetTypeAtIndex(0);
Greg Clayton726bc522012-03-28 17:13:26 +0000138 if (log)
139 log->Printf ("0x%16.16llx: static-type = '%s' has dynamic type: uid={0x%llx}, type-name='%s'\n",
140 original_ptr,
141 in_value.GetTypeName().AsCString(),
142 type_sp->GetID(),
143 type_sp->GetName().GetCString());
144
Jim Ingham61be0902011-05-02 18:13:59 +0000145 class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
Jim Ingham78a685a2011-04-16 00:01:13 +0000146 }
147 else if (num_matches > 1)
148 {
Greg Clayton29399a22012-04-06 17:41:13 +0000149 size_t i;
150 if (log)
Jim Ingham61be0902011-05-02 18:13:59 +0000151 {
Greg Clayton29399a22012-04-06 17:41:13 +0000152 for (i = 0; i < num_matches; i++)
Jim Ingham61be0902011-05-02 18:13:59 +0000153 {
Greg Clayton29399a22012-04-06 17:41:13 +0000154 type_sp = class_types.GetTypeAtIndex(i);
155 if (type_sp)
156 {
157 if (log)
158 log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n",
159 original_ptr,
160 in_value.GetTypeName().AsCString(),
161 type_sp->GetID(),
162 type_sp->GetName().GetCString());
163 }
Jim Ingham61be0902011-05-02 18:13:59 +0000164 }
165 }
Greg Clayton29399a22012-04-06 17:41:13 +0000166
167 for (i = 0; i < num_matches; i++)
168 {
169 type_sp = class_types.GetTypeAtIndex(i);
170 if (type_sp)
171 {
172 if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
173 {
174 if (log)
175 log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%llx}, type-name='%s'\n",
176 original_ptr,
177 in_value.GetTypeName().AsCString(),
178 type_sp->GetID(),
179 type_sp->GetName().GetCString());
180 class_type_or_name.SetTypeSP(type_sp);
181 break;
182 }
183 }
184 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000185
Greg Clayton29399a22012-04-06 17:41:13 +0000186 if (i == num_matches)
187 {
188 if (log)
189 log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
190 original_ptr,
191 in_value.GetTypeName().AsCString());
192 return false;
193 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000194 }
Greg Clayton29399a22012-04-06 17:41:13 +0000195
196 // There can only be one type with a given name,
197 // so we've just found duplicate definitions, and this
198 // one will do as well as any other.
199 // We don't consider something to have a dynamic type if
200 // it is the same as the static type. So compare against
201 // the value we were handed.
202 if (type_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +0000203 {
Greg Clayton29399a22012-04-06 17:41:13 +0000204 clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
205 clang::ASTContext *this_ast_ctx = type_sp->GetClangAST ();
206 if (in_ast_ctx == this_ast_ctx)
207 {
208 if (ClangASTContext::AreTypesSame (in_ast_ctx,
209 in_value.GetClangType(),
210 type_sp->GetClangFullType()))
211 {
212 // The dynamic type we found was the same type,
213 // so we don't have a dynamic type here...
214 return false;
215 }
216 }
217
218 // The offset_to_top is two pointers above the address.
219 Address offset_to_top_address = address_point_address;
220 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
221 offset_to_top_address.Slide (slide);
222
223 Error error;
224 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
225
226 size_t bytes_read = process->ReadMemory (offset_to_top_location,
227 memory_buffer,
228 address_byte_size,
229 error);
230
231 if (!error.Success() || (bytes_read != address_byte_size))
232 {
233 return false;
234 }
235
236 offset_ptr = 0;
237 int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
238
239 // So the dynamic type is a value that starts at offset_to_top
240 // above the original address.
241 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
242 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
243 {
244 dynamic_address.SetRawAddress(dynamic_addr);
245 }
246 return true;
Jim Ingham78a685a2011-04-16 00:01:13 +0000247 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000248 }
249 }
250 }
251 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000252 }
253
254 return false;
Jim Ingham5a369122010-09-28 01:25:32 +0000255}
256
257bool
258ItaniumABILanguageRuntime::IsVTableName (const char *name)
259{
260 if (name == NULL)
261 return false;
262
263 // Can we maybe ask Clang about this?
264 if (strstr (name, "_vptr$") == name)
265 return true;
266 else
267 return false;
268}
269
Jim Ingham22777012010-09-23 02:01:19 +0000270//------------------------------------------------------------------
271// Static Functions
272//------------------------------------------------------------------
Jim Ingham133e0fb2012-03-03 02:05:11 +0000273LanguageRuntime *
Jim Ingham22777012010-09-23 02:01:19 +0000274ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
275{
276 // FIXME: We have to check the process and make sure we actually know that this process supports
277 // the Itanium ABI.
278 if (language == eLanguageTypeC_plus_plus)
279 return new ItaniumABILanguageRuntime (process);
280 else
281 return NULL;
282}
283
284void
285ItaniumABILanguageRuntime::Initialize()
286{
287 PluginManager::RegisterPlugin (pluginName,
288 pluginDesc,
289 CreateInstance);
290}
291
292void
293ItaniumABILanguageRuntime::Terminate()
294{
295 PluginManager::UnregisterPlugin (CreateInstance);
296}
297
298//------------------------------------------------------------------
299// PluginInterface protocol
300//------------------------------------------------------------------
301const char *
302ItaniumABILanguageRuntime::GetPluginName()
303{
304 return pluginName;
305}
306
307const char *
308ItaniumABILanguageRuntime::GetShortPluginName()
309{
310 return pluginShort;
311}
312
313uint32_t
314ItaniumABILanguageRuntime::GetPluginVersion()
315{
316 return 1;
317}
318
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000319static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"};
Jim Ingham133e0fb2012-03-03 02:05:11 +0000320static const int num_throw_names = 3;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000321static const int num_expression_throw_names = 1;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000322
Jim Ingham219ba192012-03-05 04:47:34 +0000323BreakpointResolverSP
324ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
Jim Ingham133e0fb2012-03-03 02:05:11 +0000325{
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000326 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
327}
328
329BreakpointResolverSP
330ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
331{
Jim Ingham219ba192012-03-05 04:47:34 +0000332 BreakpointResolverSP resolver_sp;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000333 static const int total_expressions = sizeof (exception_names)/sizeof (char *);
Jim Ingham219ba192012-03-05 04:47:34 +0000334
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000335 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
336 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception
337 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
338 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
339
340 uint32_t num_expressions;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000341 if (catch_bp && throw_bp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000342 {
343 if (for_expressions)
344 num_expressions = total_expressions;
345 else
346 num_expressions = total_expressions - num_expression_throw_names;
347
Jim Ingham219ba192012-03-05 04:47:34 +0000348 resolver_sp.reset (new BreakpointResolverName (bkpt,
349 exception_names,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000350 num_expressions,
Jim Ingham219ba192012-03-05 04:47:34 +0000351 eFunctionNameTypeBase,
352 eLazyBoolNo));
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000353 }
Jim Ingham133e0fb2012-03-03 02:05:11 +0000354 else if (throw_bp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000355 {
356 if (for_expressions)
357 num_expressions = num_throw_names - num_expression_throw_names;
358 else
359 num_expressions = num_throw_names;
360
Jim Ingham219ba192012-03-05 04:47:34 +0000361 resolver_sp.reset (new BreakpointResolverName (bkpt,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000362 exception_names + 1,
363 num_expressions,
Jim Ingham219ba192012-03-05 04:47:34 +0000364 eFunctionNameTypeBase,
365 eLazyBoolNo));
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000366 }
Jim Ingham133e0fb2012-03-03 02:05:11 +0000367 else if (catch_bp)
Jim Ingham219ba192012-03-05 04:47:34 +0000368 resolver_sp.reset (new BreakpointResolverName (bkpt,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000369 exception_names,
370 total_expressions - num_throw_names,
Jim Ingham219ba192012-03-05 04:47:34 +0000371 eFunctionNameTypeBase,
372 eLazyBoolNo));
Jim Ingham133e0fb2012-03-03 02:05:11 +0000373
Jim Ingham219ba192012-03-05 04:47:34 +0000374 return resolver_sp;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000375}
376
Jim Ingham22777012010-09-23 02:01:19 +0000377void
Sean Callananf2115102010-11-03 22:19:38 +0000378ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
379{
380 if (!m_process)
381 return;
382
Jim Ingham133e0fb2012-03-03 02:05:11 +0000383 const bool catch_bp = false;
384 const bool throw_bp = true;
385 const bool is_internal = true;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000386 const bool for_expressions = true;
387
388 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
389 // stop at exception allocation as well.
Jim Ingham133e0fb2012-03-03 02:05:11 +0000390
Sean Callananf2115102010-11-03 22:19:38 +0000391 if (!m_cxx_exception_bp_sp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000392 {
393 Target &target = m_process->GetTarget();
394
395 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
396 SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL);
397
398 m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
399 }
Jim Inghame3846fd2011-07-23 00:12:05 +0000400 else
401 m_cxx_exception_bp_sp->SetEnabled (true);
Sean Callananf2115102010-11-03 22:19:38 +0000402
Sean Callananf2115102010-11-03 22:19:38 +0000403}
404
405void
406ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
407{
408 if (!m_process)
409 return;
410
411 if (m_cxx_exception_bp_sp.get())
412 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000413 m_cxx_exception_bp_sp->SetEnabled (false);
Jim Ingham133e0fb2012-03-03 02:05:11 +0000414 }
Sean Callananf2115102010-11-03 22:19:38 +0000415}
416
417bool
418ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
419{
420 if (!m_process)
421 return false;
422
423 if (!stop_reason ||
424 stop_reason->GetStopReason() != eStopReasonBreakpoint)
425 return false;
426
427 uint64_t break_site_id = stop_reason->GetValue();
Jim Ingham564d8bc22012-03-09 04:10:47 +0000428 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
429 m_cxx_exception_bp_sp->GetID());
Sean Callananf2115102010-11-03 22:19:38 +0000430
Sean Callananf2115102010-11-03 22:19:38 +0000431}