1 //===-- 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 
12 #include "lldb/Breakpoint/BreakpointLocation.h"
13 #include "lldb/Core/ConstString.h"
14 #include "lldb/Core/Error.h"
15 #include "lldb/Core/Log.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Scalar.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Core/ValueObjectMemory.h"
21 #include "lldb/Symbol/ClangASTContext.h"
22 #include "lldb/Symbol/Symbol.h"
23 #include "lldb/Symbol/SymbolFile.h"
24 #include "lldb/Symbol/TypeList.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/RegisterContext.h"
27 #include "lldb/Target/SectionLoadList.h"
28 #include "lldb/Target/StopInfo.h"
29 #include "lldb/Target/Target.h"
30 #include "lldb/Target/Thread.h"
31 
32 #include <vector>
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 static const char *vtable_demangled_prefix = "vtable for ";
38 
39 bool
40 ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
41 {
42     const bool check_cxx = true;
43     const bool check_objc = false;
44     return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
45 }
46 
47 bool
48 ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
49                                                      lldb::DynamicValueType use_dynamic,
50                                                      TypeAndOrName &class_type_or_name,
51                                                      Address &dynamic_address,
52                                                      Value::ValueType &value_type)
53 {
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 
62     class_type_or_name.Clear();
63     value_type = Value::ValueType::eValueTypeScalar;
64 
65     // Only a pointer or reference type can have a different dynamic and static type:
66     if (CouldHaveDynamicValue (in_value))
67     {
68         // First job, pull out the address at 0 offset from the object.
69         AddressType address_type;
70         lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
71         if (original_ptr == LLDB_INVALID_ADDRESS)
72             return false;
73 
74         ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
75 
76         Target *target = exe_ctx.GetTargetPtr();
77         Process *process = exe_ctx.GetProcessPtr();
78 
79         char memory_buffer[16];
80         DataExtractor data(memory_buffer, sizeof(memory_buffer),
81                            process->GetByteOrder(),
82                            process->GetAddressByteSize());
83         size_t address_byte_size = process->GetAddressByteSize();
84         Error error;
85         size_t bytes_read = process->ReadMemory (original_ptr,
86                                                  memory_buffer,
87                                                  address_byte_size,
88                                                  error);
89         if (!error.Success() || (bytes_read != address_byte_size))
90         {
91             return false;
92         }
93 
94         lldb::offset_t offset = 0;
95         lldb::addr_t vtable_address_point = data.GetAddress (&offset);
96 
97         if (offset == 0)
98             return false;
99 
100         // Now find the symbol that contains this address:
101 
102         SymbolContext sc;
103         Address address_point_address;
104         if (target && !target->GetSectionLoadList().IsEmpty())
105         {
106             if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
107             {
108                 target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
109                 Symbol *symbol = sc.symbol;
110                 if (symbol != NULL)
111                 {
112                     const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString();
113                     if (name && strstr(name, vtable_demangled_prefix) == name)
114                     {
115                         Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
116                         if (log)
117                             log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
118                                          original_ptr,
119                                          in_value.GetTypeName().GetCString(),
120                                          name);
121                         // We are a C++ class, that's good.  Get the class name and look it up:
122                         const char *class_name = name + strlen(vtable_demangled_prefix);
123                         class_type_or_name.SetName (class_name);
124                         const bool exact_match = true;
125                         TypeList class_types;
126 
127                         uint32_t num_matches = 0;
128                         // First look in the module that the vtable symbol came from
129                         // and look for a single exact match.
130                         llvm::DenseSet<SymbolFile *> searched_symbol_files;
131                         if (sc.module_sp)
132                         {
133                             num_matches = sc.module_sp->FindTypes (sc,
134                                                                    ConstString(class_name),
135                                                                    exact_match,
136                                                                    1,
137                                                                    searched_symbol_files,
138                                                                    class_types);
139                         }
140 
141                         // If we didn't find a symbol, then move on to the entire
142                         // module list in the target and get as many unique matches
143                         // as possible
144                         if (num_matches == 0)
145                         {
146                             num_matches = target->GetImages().FindTypes (sc,
147                                                                          ConstString(class_name),
148                                                                          exact_match,
149                                                                          UINT32_MAX,
150                                                                          searched_symbol_files,
151                                                                          class_types);
152                         }
153 
154                         lldb::TypeSP type_sp;
155                         if (num_matches == 0)
156                         {
157                             if (log)
158                                 log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
159                             return false;
160                         }
161                         if (num_matches == 1)
162                         {
163                             type_sp = class_types.GetTypeAtIndex(0);
164                             if (log)
165                                 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n",
166                                              original_ptr,
167                                              in_value.GetTypeName().AsCString(),
168                                              type_sp->GetID(),
169                                              type_sp->GetName().GetCString());
170 
171                             class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
172                         }
173                         else if (num_matches > 1)
174                         {
175                             size_t i;
176                             if (log)
177                             {
178                                 for (i = 0; i < num_matches; i++)
179                                 {
180                                     type_sp = class_types.GetTypeAtIndex(i);
181                                     if (type_sp)
182                                     {
183                                         if (log)
184                                             log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
185                                                          original_ptr,
186                                                          in_value.GetTypeName().AsCString(),
187                                                          type_sp->GetID(),
188                                                          type_sp->GetName().GetCString());
189                                     }
190                                 }
191                             }
192 
193                             for (i = 0; i < num_matches; i++)
194                             {
195                                 type_sp = class_types.GetTypeAtIndex(i);
196                                 if (type_sp)
197                                 {
198                                     if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType()))
199                                     {
200                                         if (log)
201                                             log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
202                                                          original_ptr,
203                                                          in_value.GetTypeName().AsCString(),
204                                                          type_sp->GetID(),
205                                                          type_sp->GetName().GetCString());
206                                         class_type_or_name.SetTypeSP(type_sp);
207                                         break;
208                                     }
209                                 }
210                             }
211 
212                             if (i == num_matches)
213                             {
214                                 if (log)
215                                     log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
216                                                  original_ptr,
217                                                  in_value.GetTypeName().AsCString());
218                                 return false;
219                             }
220                         }
221 
222                         // There can only be one type with a given name,
223                         // so we've just found duplicate definitions, and this
224                         // one will do as well as any other.
225                         // We don't consider something to have a dynamic type if
226                         // it is the same as the static type.  So compare against
227                         // the value we were handed.
228                         if (type_sp)
229                         {
230                             if (ClangASTContext::AreTypesSame (in_value.GetCompilerType(),
231                                                                type_sp->GetForwardCompilerType ()))
232                             {
233                                 // The dynamic type we found was the same type,
234                                 // so we don't have a dynamic type here...
235                                 return false;
236                             }
237 
238                             // The offset_to_top is two pointers above the address.
239                             Address offset_to_top_address = address_point_address;
240                             int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
241                             offset_to_top_address.Slide (slide);
242 
243                             Error error;
244                             lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
245 
246                             size_t bytes_read = process->ReadMemory (offset_to_top_location,
247                                                                      memory_buffer,
248                                                                      address_byte_size,
249                                                                      error);
250 
251                             if (!error.Success() || (bytes_read != address_byte_size))
252                             {
253                                 return false;
254                             }
255 
256                             offset = 0;
257                             int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize());
258 
259                             // So the dynamic type is a value that starts at offset_to_top
260                             // above the original address.
261                             lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
262                             if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
263                             {
264                                 dynamic_address.SetRawAddress(dynamic_addr);
265                             }
266                             return true;
267                         }
268                     }
269                 }
270             }
271         }
272     }
273 
274     return class_type_or_name.IsEmpty() == false;
275 }
276 
277 TypeAndOrName
278 ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name,
279                                             ValueObject& static_value)
280 {
281     CompilerType static_type(static_value.GetCompilerType());
282     Flags static_type_flags(static_type.GetTypeInfo());
283 
284     TypeAndOrName ret(type_and_or_name);
285     if (type_and_or_name.HasType())
286     {
287         // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
288         // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
289         // should be okay...
290         CompilerType orig_type = type_and_or_name.GetCompilerType();
291         CompilerType corrected_type = orig_type;
292         if (static_type_flags.AllSet(eTypeIsPointer))
293             corrected_type = orig_type.GetPointerType ();
294         else if (static_type_flags.AllSet(eTypeIsReference))
295             corrected_type = orig_type.GetLValueReferenceType();
296         ret.SetCompilerType(corrected_type);
297     }
298     else
299     {
300         // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
301         std::string corrected_name (type_and_or_name.GetName().GetCString());
302         if (static_type_flags.AllSet(eTypeIsPointer))
303             corrected_name.append(" *");
304         else if (static_type_flags.AllSet(eTypeIsReference))
305             corrected_name.append(" &");
306         // the parent type should be a correctly pointer'ed or referenc'ed type
307         ret.SetCompilerType(static_type);
308         ret.SetName(corrected_name.c_str());
309     }
310     return ret;
311 }
312 
313 bool
314 ItaniumABILanguageRuntime::IsVTableName (const char *name)
315 {
316     if (name == NULL)
317         return false;
318 
319     // Can we maybe ask Clang about this?
320     if (strstr (name, "_vptr$") == name)
321         return true;
322     else
323         return false;
324 }
325 
326 //------------------------------------------------------------------
327 // Static Functions
328 //------------------------------------------------------------------
329 LanguageRuntime *
330 ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
331 {
332     // FIXME: We have to check the process and make sure we actually know that this process supports
333     // the Itanium ABI.
334     if (language == eLanguageTypeC_plus_plus ||
335         language == eLanguageTypeC_plus_plus_03 ||
336         language == eLanguageTypeC_plus_plus_11 ||
337         language == eLanguageTypeC_plus_plus_14)
338         return new ItaniumABILanguageRuntime (process);
339     else
340         return NULL;
341 }
342 
343 void
344 ItaniumABILanguageRuntime::Initialize()
345 {
346     PluginManager::RegisterPlugin (GetPluginNameStatic(),
347                                    "Itanium ABI for the C++ language",
348                                    CreateInstance);
349 }
350 
351 void
352 ItaniumABILanguageRuntime::Terminate()
353 {
354     PluginManager::UnregisterPlugin (CreateInstance);
355 }
356 
357 lldb_private::ConstString
358 ItaniumABILanguageRuntime::GetPluginNameStatic()
359 {
360     static ConstString g_name("itanium");
361     return g_name;
362 }
363 
364 //------------------------------------------------------------------
365 // PluginInterface protocol
366 //------------------------------------------------------------------
367 lldb_private::ConstString
368 ItaniumABILanguageRuntime::GetPluginName()
369 {
370     return GetPluginNameStatic();
371 }
372 
373 uint32_t
374 ItaniumABILanguageRuntime::GetPluginVersion()
375 {
376     return 1;
377 }
378 
379 BreakpointResolverSP
380 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
381 {
382     return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
383 }
384 
385 BreakpointResolverSP
386 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
387 {
388     // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
389     // anything better with predicting unwinding the expression parser does.  So we have two forms of the exception
390     // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
391     // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
392     static const char *g_catch_name = "__cxa_begin_catch";
393     static const char *g_throw_name1 = "__cxa_throw";
394     static const char *g_throw_name2 = "__cxa_rethrow";
395     static const char *g_exception_throw_name = "__cxa_allocate_exception";
396     std::vector<const char *> exception_names;
397     exception_names.reserve(4);
398     if (catch_bp)
399         exception_names.push_back(g_catch_name);
400 
401     if (throw_bp)
402     {
403         exception_names.push_back(g_throw_name1);
404         exception_names.push_back(g_throw_name2);
405     }
406 
407     if (for_expressions)
408         exception_names.push_back(g_exception_throw_name);
409 
410     BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
411                                                                   exception_names.data(),
412                                                                   exception_names.size(),
413                                                                   eFunctionNameTypeBase,
414                                                                   eLanguageTypeUnknown,
415                                                                   eLazyBoolNo));
416 
417     return resolver_sp;
418 }
419 
420 
421 
422 lldb::SearchFilterSP
423 ItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
424 {
425     Target &target = m_process->GetTarget();
426 
427     if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
428     {
429         // Limit the number of modules that are searched for these breakpoints for
430         // Apple binaries.
431         FileSpecList filter_modules;
432         filter_modules.Append(FileSpec("libc++abi.dylib", false));
433         filter_modules.Append(FileSpec("libSystem.B.dylib", false));
434         return target.GetSearchFilterForModuleList(&filter_modules);
435     }
436     else
437     {
438         return LanguageRuntime::CreateExceptionSearchFilter();
439     }
440 }
441 
442 lldb::BreakpointSP
443 ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
444                                                       bool throw_bp,
445                                                       bool for_expressions,
446                                                       bool is_internal)
447 {
448     Target &target = m_process->GetTarget();
449     FileSpecList filter_modules;
450     BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
451     SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
452     const bool hardware = false;
453     const bool resolve_indirect_functions = false;
454     return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions);
455 }
456 
457 void
458 ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
459 {
460     if (!m_process)
461         return;
462 
463     const bool catch_bp = false;
464     const bool throw_bp = true;
465     const bool is_internal = true;
466     const bool for_expressions = true;
467 
468     // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
469     // stop at exception allocation as well.
470 
471     if (m_cxx_exception_bp_sp)
472     {
473         m_cxx_exception_bp_sp->SetEnabled (true);
474     }
475     else
476     {
477         m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
478         if (m_cxx_exception_bp_sp)
479             m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
480     }
481 
482 }
483 
484 void
485 ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
486 {
487     if (!m_process)
488         return;
489 
490     if (m_cxx_exception_bp_sp)
491     {
492         m_cxx_exception_bp_sp->SetEnabled (false);
493     }
494 }
495 
496 bool
497 ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet ()
498 {
499     return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
500 }
501 
502 bool
503 ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
504 {
505     if (!m_process)
506         return false;
507 
508     if (!stop_reason ||
509         stop_reason->GetStopReason() != eStopReasonBreakpoint)
510         return false;
511 
512     uint64_t break_site_id = stop_reason->GetValue();
513     return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
514                                                                                m_cxx_exception_bp_sp->GetID());
515 
516 }
517