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