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/Mangled.h"
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/PluginManager.h"
19 #include "lldb/Core/Scalar.h"
20 #include "lldb/Core/ValueObject.h"
21 #include "lldb/Core/ValueObjectMemory.h"
22 #include "lldb/Interpreter/CommandObject.h"
23 #include "lldb/Interpreter/CommandObjectMultiword.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Symbol/ClangASTContext.h"
26 #include "lldb/Symbol/Symbol.h"
27 #include "lldb/Symbol/SymbolFile.h"
28 #include "lldb/Symbol/TypeList.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/SectionLoadList.h"
32 #include "lldb/Target/StopInfo.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/Thread.h"
35 
36 #include <vector>
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 
41 static const char *vtable_demangled_prefix = "vtable for ";
42 
43 bool
44 ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
45 {
46     const bool check_cxx = true;
47     const bool check_objc = false;
48     return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
49 }
50 
51 TypeAndOrName
52 ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr,
53                                                         lldb::addr_t vtable_load_addr)
54 {
55     if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS)
56     {
57         // Find the symbol that contains the "vtable_load_addr" address
58         Address vtable_addr;
59         Target &target = m_process->GetTarget();
60         if (!target.GetSectionLoadList().IsEmpty())
61         {
62             if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, vtable_addr))
63             {
64                 // See if we have cached info for this type already
65                 TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr);
66                 if (type_info)
67                     return type_info;
68 
69                 SymbolContext sc;
70                 target.GetImages().ResolveSymbolContextForAddress(vtable_addr, eSymbolContextSymbol, sc);
71                 Symbol *symbol = sc.symbol;
72                 if (symbol != NULL)
73                 {
74                     const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString();
75                     if (name && strstr(name, vtable_demangled_prefix) == name)
76                     {
77                         Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
78                         if (log)
79                             log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
80                                          original_ptr,
81                                          in_value.GetTypeName().GetCString(),
82                                          name);
83                         // We are a C++ class, that's good.  Get the class name and look it up:
84                         const char *class_name = name + strlen(vtable_demangled_prefix);
85                         type_info.SetName(class_name);
86                         const bool exact_match = true;
87                         TypeList class_types;
88 
89                         uint32_t num_matches = 0;
90                         // First look in the module that the vtable symbol came from
91                         // and look for a single exact match.
92                         llvm::DenseSet<SymbolFile *> searched_symbol_files;
93                         if (sc.module_sp)
94                         {
95                             num_matches = sc.module_sp->FindTypes (sc,
96                                                                    ConstString(class_name),
97                                                                    exact_match,
98                                                                    1,
99                                                                    searched_symbol_files,
100                                                                    class_types);
101                         }
102 
103                         // If we didn't find a symbol, then move on to the entire
104                         // module list in the target and get as many unique matches
105                         // as possible
106                         if (num_matches == 0)
107                         {
108                             num_matches = target.GetImages().FindTypes(sc, ConstString(class_name), exact_match,
109                                                                        UINT32_MAX, searched_symbol_files, class_types);
110                         }
111 
112                         lldb::TypeSP type_sp;
113                         if (num_matches == 0)
114                         {
115                             if (log)
116                                 log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
117                             return TypeAndOrName();
118                         }
119                         if (num_matches == 1)
120                         {
121                             type_sp = class_types.GetTypeAtIndex(0);
122                             if (type_sp)
123                             {
124                                 if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType()))
125                                 {
126                                     if (log)
127                                         log->Printf("0x%16.16" PRIx64
128                                                     ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
129                                                     "}, type-name='%s'\n",
130                                                     original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(),
131                                                     type_sp->GetName().GetCString());
132                                     type_info.SetTypeSP(type_sp);
133                                 }
134                             }
135                         }
136                         else if (num_matches > 1)
137                         {
138                             size_t i;
139                             if (log)
140                             {
141                                 for (i = 0; i < num_matches; i++)
142                                 {
143                                     type_sp = class_types.GetTypeAtIndex(i);
144                                     if (type_sp)
145                                     {
146                                         if (log)
147                                             log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
148                                                          original_ptr,
149                                                          in_value.GetTypeName().AsCString(),
150                                                          type_sp->GetID(),
151                                                          type_sp->GetName().GetCString());
152                                     }
153                                 }
154                             }
155 
156                             for (i = 0; i < num_matches; i++)
157                             {
158                                 type_sp = class_types.GetTypeAtIndex(i);
159                                 if (type_sp)
160                                 {
161                                     if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType()))
162                                     {
163                                         if (log)
164                                             log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
165                                                          original_ptr,
166                                                          in_value.GetTypeName().AsCString(),
167                                                          type_sp->GetID(),
168                                                          type_sp->GetName().GetCString());
169                                         type_info.SetTypeSP(type_sp);
170                                     }
171                                 }
172                             }
173 
174                             if (log && i == num_matches)
175                             {
176                                 log->Printf("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic "
177                                                               "types, didn't find a C++ match\n",
178                                             original_ptr, in_value.GetTypeName().AsCString());
179                             }
180                         }
181                         if (type_info)
182                             SetDynamicTypeInfo(vtable_addr, type_info);
183                         return type_info;
184                     }
185                 }
186             }
187         }
188     }
189     return TypeAndOrName();
190 }
191 
192 bool
193 ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
194                                                     TypeAndOrName &class_type_or_name, Address &dynamic_address,
195                                                     Value::ValueType &value_type)
196 {
197     // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
198     // in the object.  That will point to the "address point" within the vtable (not the beginning of the
199     // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name
200     // demangled will contain the full class name.
201     // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
202     // start of the value object which holds the dynamic type.
203     //
204 
205     class_type_or_name.Clear();
206     value_type = Value::ValueType::eValueTypeScalar;
207 
208     // Only a pointer or reference type can have a different dynamic and static type:
209     if (CouldHaveDynamicValue(in_value))
210     {
211         // First job, pull out the address at 0 offset from the object.
212         AddressType address_type;
213         lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
214         if (original_ptr == LLDB_INVALID_ADDRESS)
215             return false;
216 
217         ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
218 
219         Process *process = exe_ctx.GetProcessPtr();
220 
221         if (process == nullptr)
222             return false;
223 
224         Error error;
225         const lldb::addr_t vtable_address_point = process->ReadPointerFromMemory(original_ptr, error);
226 
227         if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS)
228         {
229             return false;
230         }
231 
232         class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, vtable_address_point);
233 
234         if (class_type_or_name)
235         {
236             TypeSP type_sp = class_type_or_name.GetTypeSP();
237             // There can only be one type with a given name,
238             // so we've just found duplicate definitions, and this
239             // one will do as well as any other.
240             // We don't consider something to have a dynamic type if
241             // it is the same as the static type.  So compare against
242             // the value we were handed.
243             if (type_sp)
244             {
245                 if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type_sp->GetForwardCompilerType()))
246                 {
247                     // The dynamic type we found was the same type,
248                     // so we don't have a dynamic type here...
249                     return false;
250                 }
251 
252                 // The offset_to_top is two pointers above the vtable pointer.
253                 const uint32_t addr_byte_size = process->GetAddressByteSize();
254                 const lldb::addr_t offset_to_top_location = vtable_address_point - 2 * addr_byte_size;
255                 // Watch for underflow, offset_to_top_location should be less than vtable_address_point
256                 if (offset_to_top_location >= vtable_address_point)
257                     return false;
258                 const int64_t offset_to_top =
259                     process->ReadSignedIntegerFromMemory(offset_to_top_location, addr_byte_size, INT64_MIN, error);
260 
261                 if (offset_to_top == INT64_MIN)
262                     return false;
263                 // So the dynamic type is a value that starts at offset_to_top
264                 // above the original address.
265                 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
266                 if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(dynamic_addr, dynamic_address))
267                 {
268                     dynamic_address.SetRawAddress(dynamic_addr);
269                 }
270                 return true;
271             }
272         }
273     }
274 
275     return class_type_or_name.IsEmpty() == false;
276 }
277 
278 TypeAndOrName
279 ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name,
280                                             ValueObject& static_value)
281 {
282     CompilerType static_type(static_value.GetCompilerType());
283     Flags static_type_flags(static_type.GetTypeInfo());
284 
285     TypeAndOrName ret(type_and_or_name);
286     if (type_and_or_name.HasType())
287     {
288         // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
289         // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
290         // should be okay...
291         CompilerType orig_type = type_and_or_name.GetCompilerType();
292         CompilerType corrected_type = orig_type;
293         if (static_type_flags.AllSet(eTypeIsPointer))
294             corrected_type = orig_type.GetPointerType ();
295         else if (static_type_flags.AllSet(eTypeIsReference))
296             corrected_type = orig_type.GetLValueReferenceType();
297         ret.SetCompilerType(corrected_type);
298     }
299     else
300     {
301         // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
302         std::string corrected_name (type_and_or_name.GetName().GetCString());
303         if (static_type_flags.AllSet(eTypeIsPointer))
304             corrected_name.append(" *");
305         else if (static_type_flags.AllSet(eTypeIsReference))
306             corrected_name.append(" &");
307         // the parent type should be a correctly pointer'ed or referenc'ed type
308         ret.SetCompilerType(static_type);
309         ret.SetName(corrected_name.c_str());
310     }
311     return ret;
312 }
313 
314 bool
315 ItaniumABILanguageRuntime::IsVTableName (const char *name)
316 {
317     if (name == NULL)
318         return false;
319 
320     // Can we maybe ask Clang about this?
321     if (strstr (name, "_vptr$") == name)
322         return true;
323     else
324         return false;
325 }
326 
327 //------------------------------------------------------------------
328 // Static Functions
329 //------------------------------------------------------------------
330 LanguageRuntime *
331 ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
332 {
333     // FIXME: We have to check the process and make sure we actually know that this process supports
334     // the Itanium ABI.
335     if (language == eLanguageTypeC_plus_plus ||
336         language == eLanguageTypeC_plus_plus_03 ||
337         language == eLanguageTypeC_plus_plus_11 ||
338         language == eLanguageTypeC_plus_plus_14)
339         return new ItaniumABILanguageRuntime (process);
340     else
341         return NULL;
342 }
343 
344 class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed
345 {
346 public:
347     CommandObjectMultiwordItaniumABI_Demangle (CommandInterpreter &interpreter) :
348     CommandObjectParsed (interpreter,
349                          "demangle",
350                          "Demangle a C++ mangled name.",
351                          "language cplusplus demangle")
352     {
353         CommandArgumentEntry arg;
354         CommandArgumentData index_arg;
355 
356         // Define the first (and only) variant of this arg.
357         index_arg.arg_type = eArgTypeSymbol;
358         index_arg.arg_repetition = eArgRepeatPlus;
359 
360         // There is only one variant this argument could be; put it into the argument entry.
361         arg.push_back (index_arg);
362 
363         // Push the data for the first argument into the m_arguments vector.
364         m_arguments.push_back (arg);
365     }
366 
367     ~CommandObjectMultiwordItaniumABI_Demangle() override = default;
368 
369 protected:
370     bool
371     DoExecute(Args& command, CommandReturnObject &result) override
372     {
373         bool demangled_any = false;
374         bool error_any = false;
375         for (size_t i = 0; i < command.GetArgumentCount(); i++)
376         {
377             auto arg = command.GetArgumentAtIndex(i);
378             if (arg && *arg)
379             {
380                 ConstString mangled_cs(arg);
381 
382                 // the actual Mangled class should be strict about this, but on the command line
383                 // if you're copying mangled names out of 'nm' on Darwin, they will come out with
384                 // an extra underscore - be willing to strip this on behalf of the user
385                 // This is the moral equivalent of the -_/-n options to c++filt
386                 if (mangled_cs.GetStringRef().startswith("__Z"))
387                     mangled_cs.SetCString(arg+1);
388 
389                 Mangled mangled(mangled_cs, true);
390                 if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus)
391                 {
392                     ConstString demangled(mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus));
393                     demangled_any = true;
394                     result.AppendMessageWithFormat("%s ---> %s\n", arg, demangled.GetCString());
395                 }
396                 else
397                 {
398                     error_any = true;
399                     result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", arg);
400                 }
401             }
402         }
403 
404         result.SetStatus(error_any ? lldb::eReturnStatusFailed :
405                          (demangled_any ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult));
406         return result.Succeeded();
407     }
408 };
409 
410 class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword
411 {
412 public:
413     CommandObjectMultiwordItaniumABI (CommandInterpreter &interpreter) :
414     CommandObjectMultiword (interpreter,
415                             "cplusplus",
416                             "A set of commands for operating on the C++ Language Runtime.",
417                             "cplusplus <subcommand> [<subcommand-options>]")
418     {
419         LoadSubCommand ("demangle",   CommandObjectSP (new CommandObjectMultiwordItaniumABI_Demangle (interpreter)));
420     }
421 
422     ~CommandObjectMultiwordItaniumABI() override = default;
423 };
424 
425 void
426 ItaniumABILanguageRuntime::Initialize()
427 {
428     PluginManager::RegisterPlugin (GetPluginNameStatic(),
429                                    "Itanium ABI for the C++ language",
430                                    CreateInstance,
431                                    [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP {
432                                        return CommandObjectSP(new CommandObjectMultiwordItaniumABI(interpreter));
433                                    });
434 }
435 
436 void
437 ItaniumABILanguageRuntime::Terminate()
438 {
439     PluginManager::UnregisterPlugin (CreateInstance);
440 }
441 
442 lldb_private::ConstString
443 ItaniumABILanguageRuntime::GetPluginNameStatic()
444 {
445     static ConstString g_name("itanium");
446     return g_name;
447 }
448 
449 //------------------------------------------------------------------
450 // PluginInterface protocol
451 //------------------------------------------------------------------
452 lldb_private::ConstString
453 ItaniumABILanguageRuntime::GetPluginName()
454 {
455     return GetPluginNameStatic();
456 }
457 
458 uint32_t
459 ItaniumABILanguageRuntime::GetPluginVersion()
460 {
461     return 1;
462 }
463 
464 BreakpointResolverSP
465 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
466 {
467     return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
468 }
469 
470 BreakpointResolverSP
471 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
472 {
473     // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
474     // anything better with predicting unwinding the expression parser does.  So we have two forms of the exception
475     // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
476     // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
477     static const char *g_catch_name = "__cxa_begin_catch";
478     static const char *g_throw_name1 = "__cxa_throw";
479     static const char *g_throw_name2 = "__cxa_rethrow";
480     static const char *g_exception_throw_name = "__cxa_allocate_exception";
481     std::vector<const char *> exception_names;
482     exception_names.reserve(4);
483     if (catch_bp)
484         exception_names.push_back(g_catch_name);
485 
486     if (throw_bp)
487     {
488         exception_names.push_back(g_throw_name1);
489         exception_names.push_back(g_throw_name2);
490     }
491 
492     if (for_expressions)
493         exception_names.push_back(g_exception_throw_name);
494 
495     BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
496                                                                   exception_names.data(),
497                                                                   exception_names.size(),
498                                                                   eFunctionNameTypeBase,
499                                                                   eLanguageTypeUnknown,
500                                                                   0,
501                                                                   eLazyBoolNo));
502 
503     return resolver_sp;
504 }
505 
506 
507 
508 lldb::SearchFilterSP
509 ItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
510 {
511     Target &target = m_process->GetTarget();
512 
513     if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
514     {
515         // Limit the number of modules that are searched for these breakpoints for
516         // Apple binaries.
517         FileSpecList filter_modules;
518         filter_modules.Append(FileSpec("libc++abi.dylib", false));
519         filter_modules.Append(FileSpec("libSystem.B.dylib", false));
520         return target.GetSearchFilterForModuleList(&filter_modules);
521     }
522     else
523     {
524         return LanguageRuntime::CreateExceptionSearchFilter();
525     }
526 }
527 
528 lldb::BreakpointSP
529 ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
530                                                       bool throw_bp,
531                                                       bool for_expressions,
532                                                       bool is_internal)
533 {
534     Target &target = m_process->GetTarget();
535     FileSpecList filter_modules;
536     BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
537     SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
538     const bool hardware = false;
539     const bool resolve_indirect_functions = false;
540     return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions);
541 }
542 
543 void
544 ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
545 {
546     if (!m_process)
547         return;
548 
549     const bool catch_bp = false;
550     const bool throw_bp = true;
551     const bool is_internal = true;
552     const bool for_expressions = true;
553 
554     // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
555     // stop at exception allocation as well.
556 
557     if (m_cxx_exception_bp_sp)
558     {
559         m_cxx_exception_bp_sp->SetEnabled (true);
560     }
561     else
562     {
563         m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
564         if (m_cxx_exception_bp_sp)
565             m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
566     }
567 
568 }
569 
570 void
571 ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
572 {
573     if (!m_process)
574         return;
575 
576     if (m_cxx_exception_bp_sp)
577     {
578         m_cxx_exception_bp_sp->SetEnabled (false);
579     }
580 }
581 
582 bool
583 ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet ()
584 {
585     return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
586 }
587 
588 bool
589 ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
590 {
591     if (!m_process)
592         return false;
593 
594     if (!stop_reason ||
595         stop_reason->GetStopReason() != eStopReasonBreakpoint)
596         return false;
597 
598     uint64_t break_site_id = stop_reason->GetValue();
599     return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
600                                                                                m_cxx_exception_bp_sp->GetID());
601 
602 }
603 
604 TypeAndOrName
605 ItaniumABILanguageRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr)
606 {
607     std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
608     DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr);
609     if (pos == m_dynamic_type_map.end())
610         return TypeAndOrName();
611     else
612         return pos->second;
613 }
614 
615 void
616 ItaniumABILanguageRuntime::SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info)
617 {
618     std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
619     m_dynamic_type_map[vtable_addr] = type_info;
620 }
621