blob: 05e66f389742472bdae819b50a2a9f6690352b5a [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
Greg Claytonc7bece562013-01-25 18:06:21 +000093 lldb::offset_t offset = 0;
94 lldb::addr_t vtable_address_point = data.GetAddress (&offset);
Jim Ingham78a685a2011-04-16 00:01:13 +000095
Greg Claytonc7bece562013-01-25 18:06:21 +000096 if (offset == 0)
Jim Ingham78a685a2011-04-16 00:01:13 +000097 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 Clayton5160ce52013-03-27 23:08:40 +0000114 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Greg Clayton726bc522012-03-28 17:13:26 +0000115 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
Greg Claytonc7bece562013-01-25 18:06:21 +0000258 offset = 0;
259 int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize());
Greg Clayton29399a22012-04-06 17:41:13 +0000260
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 Ingham219ba192012-03-05 04:47:34 +0000341BreakpointResolverSP
342ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
Jim Ingham133e0fb2012-03-03 02:05:11 +0000343{
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000344 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
345}
346
347BreakpointResolverSP
348ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
349{
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000350 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
351 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception
352 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
353 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
Greg Claytonbff78252013-03-11 18:42:51 +0000354 static const char *g_catch_name = "__cxa_begin_catch";
355 static const char *g_throw_name1 = "__cxa_throw";
356 static const char *g_throw_name2 = "__cxa_rethrow";
357 static const char *g_exception_throw_name = "__cxa_allocate_exception";
358 std::vector<const char *> exception_names;
359 exception_names.reserve(4);
360 if (catch_bp)
361 exception_names.push_back(g_catch_name);
362
363 if (throw_bp)
364 {
365 exception_names.push_back(g_throw_name1);
366 exception_names.push_back(g_throw_name2);
367 }
368
369 if (for_expressions)
370 exception_names.push_back(g_exception_throw_name);
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000371
Greg Claytonbff78252013-03-11 18:42:51 +0000372 BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
373 exception_names.data(),
374 exception_names.size(),
375 eFunctionNameTypeBase,
376 eLazyBoolNo));
Jim Ingham133e0fb2012-03-03 02:05:11 +0000377
Jim Ingham219ba192012-03-05 04:47:34 +0000378 return resolver_sp;
Jim Ingham133e0fb2012-03-03 02:05:11 +0000379}
380
Greg Claytonbff78252013-03-11 18:42:51 +0000381
382
383lldb::SearchFilterSP
384ItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
385{
386 Target &target = m_process->GetTarget();
387
388 if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
389 {
390 // Limit the number of modules that are searched for these breakpoints for
391 // Apple binaries.
392 FileSpecList filter_modules;
393 filter_modules.Append(FileSpec("libc++abi.dylib", false));
394 filter_modules.Append(FileSpec("libSystem.B.dylib", false));
395 return target.GetSearchFilterForModuleList(&filter_modules);
396 }
397 else
398 {
399 return LanguageRuntime::CreateExceptionSearchFilter();
400 }
401}
402
403lldb::BreakpointSP
404ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
405 bool throw_bp,
406 bool for_expressions,
407 bool is_internal)
408{
409 Target &target = m_process->GetTarget();
410 FileSpecList filter_modules;
411 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
412 SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
413 return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
414}
415
Jim Ingham22777012010-09-23 02:01:19 +0000416void
Sean Callananf2115102010-11-03 22:19:38 +0000417ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
418{
419 if (!m_process)
420 return;
421
Jim Ingham133e0fb2012-03-03 02:05:11 +0000422 const bool catch_bp = false;
423 const bool throw_bp = true;
424 const bool is_internal = true;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000425 const bool for_expressions = true;
426
427 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
428 // stop at exception allocation as well.
Jim Ingham133e0fb2012-03-03 02:05:11 +0000429
Greg Claytonbff78252013-03-11 18:42:51 +0000430 if (m_cxx_exception_bp_sp)
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000431 {
Greg Claytonbff78252013-03-11 18:42:51 +0000432 m_cxx_exception_bp_sp->SetEnabled (true);
433 }
434 else
435 {
436 m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
Jim Ingham0ac57092013-02-14 03:05:42 +0000437 if (m_cxx_exception_bp_sp)
438 m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000439 }
Sean Callananf2115102010-11-03 22:19:38 +0000440
Sean Callananf2115102010-11-03 22:19:38 +0000441}
442
443void
444ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
445{
446 if (!m_process)
447 return;
448
Greg Claytonbff78252013-03-11 18:42:51 +0000449 if (m_cxx_exception_bp_sp)
Sean Callananf2115102010-11-03 22:19:38 +0000450 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000451 m_cxx_exception_bp_sp->SetEnabled (false);
Jim Ingham133e0fb2012-03-03 02:05:11 +0000452 }
Sean Callananf2115102010-11-03 22:19:38 +0000453}
454
455bool
456ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
457{
458 if (!m_process)
459 return false;
460
461 if (!stop_reason ||
462 stop_reason->GetStopReason() != eStopReasonBreakpoint)
463 return false;
464
465 uint64_t break_site_id = stop_reason->GetValue();
Jim Ingham564d8bc22012-03-09 04:10:47 +0000466 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
467 m_cxx_exception_bp_sp->GetID());
Sean Callananf2115102010-11-03 22:19:38 +0000468
Sean Callananf2115102010-11-03 22:19:38 +0000469}