blob: 2cd340980c1079b385ea598d76da084bb5bcfa70 [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"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Symbol/Symbol.h"
23#include "lldb/Symbol/TypeList.h"
Jim Ingham22777012010-09-23 02:01:19 +000024#include "lldb/Target/Process.h"
25#include "lldb/Target/RegisterContext.h"
Sean Callananf2115102010-11-03 22:19:38 +000026#include "lldb/Target/StopInfo.h"
Jim Ingham22777012010-09-23 02:01:19 +000027#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
29
30#include <vector>
31
32using namespace lldb;
33using namespace lldb_private;
34
35static const char *pluginName = "ItaniumABILanguageRuntime";
36static const char *pluginDesc = "Itanium ABI for the C++ language";
37static const char *pluginShort = "language.itanium";
Jim Ingham78a685a2011-04-16 00:01:13 +000038static const char *vtable_demangled_prefix = "vtable for ";
Jim Ingham22777012010-09-23 02:01:19 +000039
Jim Ingham78a685a2011-04-16 00:01:13 +000040bool
41ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
Jim Ingham5a369122010-09-28 01:25:32 +000042{
Enrico Granatafd4c84e2012-05-21 16:51:35 +000043 return ClangASTContext::IsPossibleDynamicType(in_value.GetClangAST(), in_value.GetClangType(), NULL,
44 true, // check for C++
45 false); // do not check for ObjC
Jim Ingham78a685a2011-04-16 00:01:13 +000046}
47
48bool
Jim Ingham2837b762011-05-04 03:43:18 +000049ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
50 lldb::DynamicValueType use_dynamic,
51 TypeAndOrName &class_type_or_name,
52 Address &dynamic_address)
Jim Ingham78a685a2011-04-16 00:01:13 +000053{
54 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
55 // in the object. That will point to the "address point" within the vtable (not the beginning of the
56 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name
57 // demangled will contain the full class name.
58 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the
59 // start of the value object which holds the dynamic type.
60 //
61
Enrico Granataf7b1a342013-01-23 01:17:27 +000062 class_type_or_name.Clear();
63
Jim Ingham78a685a2011-04-16 00:01:13 +000064 // Only a pointer or reference type can have a different dynamic and static type:
65 if (CouldHaveDynamicValue (in_value))
66 {
Jim Ingham78a685a2011-04-16 00:01:13 +000067 // First job, pull out the address at 0 offset from the object.
68 AddressType address_type;
Enrico Granata9128ee22011-09-06 19:20:51 +000069 lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
Jim Ingham78a685a2011-04-16 00:01:13 +000070 if (original_ptr == LLDB_INVALID_ADDRESS)
71 return false;
Greg Claytoncc4d0142012-02-17 07:49:44 +000072
73 ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
74
75 Target *target = exe_ctx.GetTargetPtr();
76 Process *process = exe_ctx.GetProcessPtr();
Jim Ingham78a685a2011-04-16 00:01:13 +000077
78 char memory_buffer[16];
79 DataExtractor data(memory_buffer, sizeof(memory_buffer),
80 process->GetByteOrder(),
81 process->GetAddressByteSize());
82 size_t address_byte_size = process->GetAddressByteSize();
83 Error error;
84 size_t bytes_read = process->ReadMemory (original_ptr,
85 memory_buffer,
86 address_byte_size,
87 error);
88 if (!error.Success() || (bytes_read != address_byte_size))
89 {
90 return false;
91 }
92
93 uint32_t offset_ptr = 0;
94 lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
95
96 if (offset_ptr == 0)
97 return false;
98
99 // Now find the symbol that contains this address:
100
101 SymbolContext sc;
102 Address address_point_address;
103 if (target && !target->GetSectionLoadList().IsEmpty())
104 {
105 if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
106 {
107 target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
108 Symbol *symbol = sc.symbol;
109 if (symbol != NULL)
110 {
111 const char *name = symbol->GetMangled().GetDemangledName().AsCString();
112 if (strstr(name, vtable_demangled_prefix) == name)
113 {
Greg Clayton726bc522012-03-28 17:13:26 +0000114 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
115 if (log)
Daniel Malead01b2952012-11-29 21:49:15 +0000116 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
Greg Clayton726bc522012-03-28 17:13:26 +0000117 original_ptr,
118 in_value.GetTypeName().GetCString(),
119 name);
120 // We are a C++ class, that's good. Get the class name and look it up:
Jim Ingham78a685a2011-04-16 00:01:13 +0000121 const char *class_name = name + strlen(vtable_demangled_prefix);
Jim Ingham61be0902011-05-02 18:13:59 +0000122 class_type_or_name.SetName (class_name);
Greg Clayton84db9102012-03-26 23:03:23 +0000123 const bool exact_match = true;
Jim Ingham78a685a2011-04-16 00:01:13 +0000124 TypeList class_types;
Greg Clayton29399a22012-04-06 17:41:13 +0000125
Greg Claytoncc0c4d42012-07-10 01:22:15 +0000126 uint32_t num_matches = 0;
127 // First look in the module that the vtable symbol came from
128 // and look for a single exact match.
129 if (sc.module_sp)
130 {
131 num_matches = sc.module_sp->FindTypes (sc,
132 ConstString(class_name),
133 exact_match,
134 1,
135 class_types);
136 }
137
138 // If we didn't find a symbol, then move on to the entire
139 // module list in the target and get as many unique matches
140 // as possible
141 if (num_matches == 0)
142 {
143 num_matches = target->GetImages().FindTypes (sc,
144 ConstString(class_name),
145 exact_match,
146 UINT32_MAX,
147 class_types);
148 }
Greg Clayton29399a22012-04-06 17:41:13 +0000149
150 lldb::TypeSP type_sp;
Greg Clayton84db9102012-03-26 23:03:23 +0000151 if (num_matches == 0)
152 {
Greg Clayton726bc522012-03-28 17:13:26 +0000153 if (log)
Daniel Malead01b2952012-11-29 21:49:15 +0000154 log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
Greg Clayton84db9102012-03-26 23:03:23 +0000155 return false;
156 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000157 if (num_matches == 1)
158 {
Greg Clayton29399a22012-04-06 17:41:13 +0000159 type_sp = class_types.GetTypeAtIndex(0);
Greg Clayton726bc522012-03-28 17:13:26 +0000160 if (log)
Daniel Malead01b2952012-11-29 21:49:15 +0000161 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n",
Greg Clayton726bc522012-03-28 17:13:26 +0000162 original_ptr,
163 in_value.GetTypeName().AsCString(),
164 type_sp->GetID(),
165 type_sp->GetName().GetCString());
166
Jim Ingham61be0902011-05-02 18:13:59 +0000167 class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
Jim Ingham78a685a2011-04-16 00:01:13 +0000168 }
169 else if (num_matches > 1)
170 {
Greg Clayton29399a22012-04-06 17:41:13 +0000171 size_t i;
172 if (log)
Jim Ingham61be0902011-05-02 18:13:59 +0000173 {
Greg Clayton29399a22012-04-06 17:41:13 +0000174 for (i = 0; i < num_matches; i++)
Jim Ingham61be0902011-05-02 18:13:59 +0000175 {
Greg Clayton29399a22012-04-06 17:41:13 +0000176 type_sp = class_types.GetTypeAtIndex(i);
177 if (type_sp)
178 {
179 if (log)
Daniel Malead01b2952012-11-29 21:49:15 +0000180 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
Greg Clayton29399a22012-04-06 17:41:13 +0000181 original_ptr,
182 in_value.GetTypeName().AsCString(),
183 type_sp->GetID(),
184 type_sp->GetName().GetCString());
185 }
Jim Ingham61be0902011-05-02 18:13:59 +0000186 }
187 }
Greg Clayton29399a22012-04-06 17:41:13 +0000188
189 for (i = 0; i < num_matches; i++)
190 {
191 type_sp = class_types.GetTypeAtIndex(i);
192 if (type_sp)
193 {
194 if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
195 {
196 if (log)
Daniel Malead01b2952012-11-29 21:49:15 +0000197 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
Greg Clayton29399a22012-04-06 17:41:13 +0000198 original_ptr,
199 in_value.GetTypeName().AsCString(),
200 type_sp->GetID(),
201 type_sp->GetName().GetCString());
202 class_type_or_name.SetTypeSP(type_sp);
203 break;
204 }
205 }
206 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000207
Greg Clayton29399a22012-04-06 17:41:13 +0000208 if (i == num_matches)
209 {
210 if (log)
Daniel Malead01b2952012-11-29 21:49:15 +0000211 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
Greg Clayton29399a22012-04-06 17:41:13 +0000212 original_ptr,
213 in_value.GetTypeName().AsCString());
214 return false;
215 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000216 }
Greg Clayton29399a22012-04-06 17:41:13 +0000217
218 // There can only be one type with a given name,
219 // so we've just found duplicate definitions, and this
220 // one will do as well as any other.
221 // We don't consider something to have a dynamic type if
222 // it is the same as the static type. So compare against
223 // the value we were handed.
224 if (type_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +0000225 {
Greg Clayton29399a22012-04-06 17:41:13 +0000226 clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
227 clang::ASTContext *this_ast_ctx = type_sp->GetClangAST ();
228 if (in_ast_ctx == this_ast_ctx)
229 {
230 if (ClangASTContext::AreTypesSame (in_ast_ctx,
231 in_value.GetClangType(),
232 type_sp->GetClangFullType()))
233 {
234 // The dynamic type we found was the same type,
235 // so we don't have a dynamic type here...
236 return false;
237 }
238 }
239
240 // The offset_to_top is two pointers above the address.
241 Address offset_to_top_address = address_point_address;
242 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
243 offset_to_top_address.Slide (slide);
244
245 Error error;
246 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
247
248 size_t bytes_read = process->ReadMemory (offset_to_top_location,
249 memory_buffer,
250 address_byte_size,
251 error);
252
253 if (!error.Success() || (bytes_read != address_byte_size))
254 {
255 return false;
256 }
257
258 offset_ptr = 0;
259 int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
260
261 // So the dynamic type is a value that starts at offset_to_top
262 // above the original address.
263 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
264 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
265 {
266 dynamic_address.SetRawAddress(dynamic_addr);
267 }
268 return true;
Jim Ingham78a685a2011-04-16 00:01:13 +0000269 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000270 }
271 }
272 }
273 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000274 }
275
Enrico Granataf7b1a342013-01-23 01:17:27 +0000276 return class_type_or_name.IsEmpty() == false;
Jim Ingham5a369122010-09-28 01:25:32 +0000277}
278
279bool
280ItaniumABILanguageRuntime::IsVTableName (const char *name)
281{
282 if (name == NULL)
283 return false;
284
285 // Can we maybe ask Clang about this?
286 if (strstr (name, "_vptr$") == name)
287 return true;
288 else
289 return false;
290}
291
Jim Ingham22777012010-09-23 02:01:19 +0000292//------------------------------------------------------------------
293// Static Functions
294//------------------------------------------------------------------
Jim Ingham133e0fb2012-03-03 02:05:11 +0000295LanguageRuntime *
Jim Ingham22777012010-09-23 02:01:19 +0000296ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
297{
298 // FIXME: We have to check the process and make sure we actually know that this process supports
299 // the Itanium ABI.
300 if (language == eLanguageTypeC_plus_plus)
301 return new ItaniumABILanguageRuntime (process);
302 else
303 return NULL;
304}
305
306void
307ItaniumABILanguageRuntime::Initialize()
308{
309 PluginManager::RegisterPlugin (pluginName,
310 pluginDesc,
311 CreateInstance);
312}
313
314void
315ItaniumABILanguageRuntime::Terminate()
316{
317 PluginManager::UnregisterPlugin (CreateInstance);
318}
319
320//------------------------------------------------------------------
321// PluginInterface protocol
322//------------------------------------------------------------------
323const char *
324ItaniumABILanguageRuntime::GetPluginName()
325{
326 return pluginName;
327}
328
329const char *
330ItaniumABILanguageRuntime::GetShortPluginName()
331{
332 return pluginShort;
333}
334
335uint32_t
336ItaniumABILanguageRuntime::GetPluginVersion()
337{
338 return 1;
339}
340
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000341static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"};
Jim Ingham133e0fb2012-03-03 02:05:11 +0000342static const int num_throw_names = 3;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000343static const int num_expression_throw_names = 1;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000344
Jim Ingham219ba192012-03-05 04:47:34 +0000345BreakpointResolverSP
346ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
Jim Ingham133e0fb2012-03-03 02:05:11 +0000347{
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000348 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
349}
350
351BreakpointResolverSP
352ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
353{
Jim Ingham219ba192012-03-05 04:47:34 +0000354 BreakpointResolverSP resolver_sp;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000355 static const int total_expressions = sizeof (exception_names)/sizeof (char *);
Jim Ingham219ba192012-03-05 04:47:34 +0000356
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000357 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
358 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception
359 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
360 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
361
362 uint32_t num_expressions;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000363 if (catch_bp && throw_bp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000364 {
365 if (for_expressions)
366 num_expressions = total_expressions;
367 else
368 num_expressions = total_expressions - num_expression_throw_names;
369
Jim Ingham219ba192012-03-05 04:47:34 +0000370 resolver_sp.reset (new BreakpointResolverName (bkpt,
371 exception_names,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000372 num_expressions,
Jim Ingham219ba192012-03-05 04:47:34 +0000373 eFunctionNameTypeBase,
374 eLazyBoolNo));
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000375 }
Jim Ingham133e0fb2012-03-03 02:05:11 +0000376 else if (throw_bp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000377 {
378 if (for_expressions)
379 num_expressions = num_throw_names - num_expression_throw_names;
380 else
381 num_expressions = num_throw_names;
382
Jim Ingham219ba192012-03-05 04:47:34 +0000383 resolver_sp.reset (new BreakpointResolverName (bkpt,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000384 exception_names + 1,
385 num_expressions,
Jim Ingham219ba192012-03-05 04:47:34 +0000386 eFunctionNameTypeBase,
387 eLazyBoolNo));
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000388 }
Jim Ingham133e0fb2012-03-03 02:05:11 +0000389 else if (catch_bp)
Jim Ingham219ba192012-03-05 04:47:34 +0000390 resolver_sp.reset (new BreakpointResolverName (bkpt,
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000391 exception_names,
392 total_expressions - num_throw_names,
Jim Ingham219ba192012-03-05 04:47:34 +0000393 eFunctionNameTypeBase,
394 eLazyBoolNo));
Jim Ingham133e0fb2012-03-03 02:05:11 +0000395
Jim Ingham219ba192012-03-05 04:47:34 +0000396 return resolver_sp;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000397}
398
Jim Ingham22777012010-09-23 02:01:19 +0000399void
Sean Callananf2115102010-11-03 22:19:38 +0000400ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
401{
402 if (!m_process)
403 return;
404
Jim Ingham133e0fb2012-03-03 02:05:11 +0000405 const bool catch_bp = false;
406 const bool throw_bp = true;
407 const bool is_internal = true;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000408 const bool for_expressions = true;
409
410 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
411 // stop at exception allocation as well.
Jim Ingham133e0fb2012-03-03 02:05:11 +0000412
Sean Callananf2115102010-11-03 22:19:38 +0000413 if (!m_cxx_exception_bp_sp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000414 {
415 Target &target = m_process->GetTarget();
416
417 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
418 SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL);
419
420 m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
421 }
Jim Inghame3846fd2011-07-23 00:12:05 +0000422 else
423 m_cxx_exception_bp_sp->SetEnabled (true);
Sean Callananf2115102010-11-03 22:19:38 +0000424
Sean Callananf2115102010-11-03 22:19:38 +0000425}
426
427void
428ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
429{
430 if (!m_process)
431 return;
432
433 if (m_cxx_exception_bp_sp.get())
434 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000435 m_cxx_exception_bp_sp->SetEnabled (false);
Jim Ingham133e0fb2012-03-03 02:05:11 +0000436 }
Sean Callananf2115102010-11-03 22:19:38 +0000437}
438
439bool
440ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
441{
442 if (!m_process)
443 return false;
444
445 if (!stop_reason ||
446 stop_reason->GetStopReason() != eStopReasonBreakpoint)
447 return false;
448
449 uint64_t break_site_id = stop_reason->GetValue();
Jim Ingham564d8bc22012-03-09 04:10:47 +0000450 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
451 m_cxx_exception_bp_sp->GetID());
Sean Callananf2115102010-11-03 22:19:38 +0000452
Sean Callananf2115102010-11-03 22:19:38 +0000453}