1254721Semaste//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "ItaniumABILanguageRuntime.h"
11254721Semaste
12254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h"
13254721Semaste#include "lldb/Core/ConstString.h"
14254721Semaste#include "lldb/Core/Error.h"
15254721Semaste#include "lldb/Core/Log.h"
16254721Semaste#include "lldb/Core/Module.h"
17254721Semaste#include "lldb/Core/PluginManager.h"
18254721Semaste#include "lldb/Core/Scalar.h"
19254721Semaste#include "lldb/Core/ValueObject.h"
20254721Semaste#include "lldb/Core/ValueObjectMemory.h"
21254721Semaste#include "lldb/Symbol/ClangASTContext.h"
22254721Semaste#include "lldb/Symbol/Symbol.h"
23254721Semaste#include "lldb/Symbol/TypeList.h"
24254721Semaste#include "lldb/Target/Process.h"
25254721Semaste#include "lldb/Target/RegisterContext.h"
26269024Semaste#include "lldb/Target/SectionLoadList.h"
27254721Semaste#include "lldb/Target/StopInfo.h"
28254721Semaste#include "lldb/Target/Target.h"
29254721Semaste#include "lldb/Target/Thread.h"
30254721Semaste
31254721Semaste#include <vector>
32254721Semaste
33254721Semasteusing namespace lldb;
34254721Semasteusing namespace lldb_private;
35254721Semaste
36254721Semastestatic const char *vtable_demangled_prefix = "vtable for ";
37254721Semaste
38254721Semastebool
39254721SemasteItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
40254721Semaste{
41254721Semaste    const bool check_cxx = true;
42254721Semaste    const bool check_objc = false;
43254721Semaste    return in_value.GetClangType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
44254721Semaste}
45254721Semaste
46254721Semastebool
47254721SemasteItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
48254721Semaste                                                     lldb::DynamicValueType use_dynamic,
49254721Semaste                                                     TypeAndOrName &class_type_or_name,
50254721Semaste                                                     Address &dynamic_address)
51254721Semaste{
52254721Semaste    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
53254721Semaste    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
54254721Semaste    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name
55254721Semaste    // demangled will contain the full class name.
56254721Semaste    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
57254721Semaste    // start of the value object which holds the dynamic type.
58254721Semaste    //
59254721Semaste
60254721Semaste    class_type_or_name.Clear();
61254721Semaste
62254721Semaste    // Only a pointer or reference type can have a different dynamic and static type:
63254721Semaste    if (CouldHaveDynamicValue (in_value))
64254721Semaste    {
65254721Semaste        // First job, pull out the address at 0 offset from the object.
66254721Semaste        AddressType address_type;
67254721Semaste        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
68254721Semaste        if (original_ptr == LLDB_INVALID_ADDRESS)
69254721Semaste            return false;
70254721Semaste
71254721Semaste        ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
72254721Semaste
73254721Semaste        Target *target = exe_ctx.GetTargetPtr();
74254721Semaste        Process *process = exe_ctx.GetProcessPtr();
75254721Semaste
76254721Semaste        char memory_buffer[16];
77254721Semaste        DataExtractor data(memory_buffer, sizeof(memory_buffer),
78254721Semaste                           process->GetByteOrder(),
79254721Semaste                           process->GetAddressByteSize());
80254721Semaste        size_t address_byte_size = process->GetAddressByteSize();
81254721Semaste        Error error;
82254721Semaste        size_t bytes_read = process->ReadMemory (original_ptr,
83254721Semaste                                                 memory_buffer,
84254721Semaste                                                 address_byte_size,
85254721Semaste                                                 error);
86254721Semaste        if (!error.Success() || (bytes_read != address_byte_size))
87254721Semaste        {
88254721Semaste            return false;
89254721Semaste        }
90254721Semaste
91254721Semaste        lldb::offset_t offset = 0;
92254721Semaste        lldb::addr_t vtable_address_point = data.GetAddress (&offset);
93254721Semaste
94254721Semaste        if (offset == 0)
95254721Semaste            return false;
96254721Semaste
97254721Semaste        // Now find the symbol that contains this address:
98254721Semaste
99254721Semaste        SymbolContext sc;
100254721Semaste        Address address_point_address;
101254721Semaste        if (target && !target->GetSectionLoadList().IsEmpty())
102254721Semaste        {
103254721Semaste            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
104254721Semaste            {
105254721Semaste                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
106254721Semaste                Symbol *symbol = sc.symbol;
107254721Semaste                if (symbol != NULL)
108254721Semaste                {
109254721Semaste                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
110254721Semaste                    if (strstr(name, vtable_demangled_prefix) == name)
111254721Semaste                    {
112254721Semaste                        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
113254721Semaste                        if (log)
114254721Semaste                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
115254721Semaste                                         original_ptr,
116254721Semaste                                         in_value.GetTypeName().GetCString(),
117254721Semaste                                         name);
118254721Semaste                        // We are a C++ class, that's good.  Get the class name and look it up:
119254721Semaste                        const char *class_name = name + strlen(vtable_demangled_prefix);
120254721Semaste                        class_type_or_name.SetName (class_name);
121254721Semaste                        const bool exact_match = true;
122254721Semaste                        TypeList class_types;
123254721Semaste
124254721Semaste                        uint32_t num_matches = 0;
125254721Semaste                        // First look in the module that the vtable symbol came from
126254721Semaste                        // and look for a single exact match.
127254721Semaste                        if (sc.module_sp)
128254721Semaste                        {
129254721Semaste                            num_matches = sc.module_sp->FindTypes (sc,
130254721Semaste                                                                   ConstString(class_name),
131254721Semaste                                                                   exact_match,
132254721Semaste                                                                   1,
133254721Semaste                                                                   class_types);
134254721Semaste                        }
135254721Semaste
136254721Semaste                        // If we didn't find a symbol, then move on to the entire
137254721Semaste                        // module list in the target and get as many unique matches
138254721Semaste                        // as possible
139254721Semaste                        if (num_matches == 0)
140254721Semaste                        {
141254721Semaste                            num_matches = target->GetImages().FindTypes (sc,
142254721Semaste                                                                         ConstString(class_name),
143254721Semaste                                                                         exact_match,
144254721Semaste                                                                         UINT32_MAX,
145254721Semaste                                                                         class_types);
146254721Semaste                        }
147254721Semaste
148254721Semaste                        lldb::TypeSP type_sp;
149254721Semaste                        if (num_matches == 0)
150254721Semaste                        {
151254721Semaste                            if (log)
152254721Semaste                                log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
153254721Semaste                            return false;
154254721Semaste                        }
155254721Semaste                        if (num_matches == 1)
156254721Semaste                        {
157254721Semaste                            type_sp = class_types.GetTypeAtIndex(0);
158254721Semaste                            if (log)
159254721Semaste                                log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n",
160254721Semaste                                             original_ptr,
161254721Semaste                                             in_value.GetTypeName().AsCString(),
162254721Semaste                                             type_sp->GetID(),
163254721Semaste                                             type_sp->GetName().GetCString());
164254721Semaste
165254721Semaste                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
166254721Semaste                        }
167254721Semaste                        else if (num_matches > 1)
168254721Semaste                        {
169254721Semaste                            size_t i;
170254721Semaste                            if (log)
171254721Semaste                            {
172254721Semaste                                for (i = 0; i < num_matches; i++)
173254721Semaste                                {
174254721Semaste                                    type_sp = class_types.GetTypeAtIndex(i);
175254721Semaste                                    if (type_sp)
176254721Semaste                                    {
177254721Semaste                                        if (log)
178254721Semaste                                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
179254721Semaste                                                         original_ptr,
180254721Semaste                                                         in_value.GetTypeName().AsCString(),
181254721Semaste                                                         type_sp->GetID(),
182254721Semaste                                                         type_sp->GetName().GetCString());
183254721Semaste                                    }
184254721Semaste                                }
185254721Semaste                            }
186254721Semaste
187254721Semaste                            for (i = 0; i < num_matches; i++)
188254721Semaste                            {
189254721Semaste                                type_sp = class_types.GetTypeAtIndex(i);
190254721Semaste                                if (type_sp)
191254721Semaste                                {
192254721Semaste                                    if (type_sp->GetClangFullType().IsCXXClassType())
193254721Semaste                                    {
194254721Semaste                                        if (log)
195254721Semaste                                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
196254721Semaste                                                         original_ptr,
197254721Semaste                                                         in_value.GetTypeName().AsCString(),
198254721Semaste                                                         type_sp->GetID(),
199254721Semaste                                                         type_sp->GetName().GetCString());
200254721Semaste                                        class_type_or_name.SetTypeSP(type_sp);
201254721Semaste                                        break;
202254721Semaste                                    }
203254721Semaste                                }
204254721Semaste                            }
205254721Semaste
206254721Semaste                            if (i == num_matches)
207254721Semaste                            {
208254721Semaste                                if (log)
209254721Semaste                                    log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
210254721Semaste                                                 original_ptr,
211254721Semaste                                                 in_value.GetTypeName().AsCString());
212254721Semaste                                return false;
213254721Semaste                            }
214254721Semaste                        }
215254721Semaste
216254721Semaste                        // There can only be one type with a given name,
217254721Semaste                        // so we've just found duplicate definitions, and this
218254721Semaste                        // one will do as well as any other.
219254721Semaste                        // We don't consider something to have a dynamic type if
220254721Semaste                        // it is the same as the static type.  So compare against
221254721Semaste                        // the value we were handed.
222254721Semaste                        if (type_sp)
223254721Semaste                        {
224254721Semaste                            if (ClangASTContext::AreTypesSame (in_value.GetClangType(),
225254721Semaste                                                               type_sp->GetClangFullType()))
226254721Semaste                            {
227254721Semaste                                // The dynamic type we found was the same type,
228254721Semaste                                // so we don't have a dynamic type here...
229254721Semaste                                return false;
230254721Semaste                            }
231254721Semaste
232254721Semaste                            // The offset_to_top is two pointers above the address.
233254721Semaste                            Address offset_to_top_address = address_point_address;
234254721Semaste                            int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
235254721Semaste                            offset_to_top_address.Slide (slide);
236254721Semaste
237254721Semaste                            Error error;
238254721Semaste                            lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
239254721Semaste
240254721Semaste                            size_t bytes_read = process->ReadMemory (offset_to_top_location,
241254721Semaste                                                                     memory_buffer,
242254721Semaste                                                                     address_byte_size,
243254721Semaste                                                                     error);
244254721Semaste
245254721Semaste                            if (!error.Success() || (bytes_read != address_byte_size))
246254721Semaste                            {
247254721Semaste                                return false;
248254721Semaste                            }
249254721Semaste
250254721Semaste                            offset = 0;
251254721Semaste                            int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize());
252254721Semaste
253254721Semaste                            // So the dynamic type is a value that starts at offset_to_top
254254721Semaste                            // above the original address.
255254721Semaste                            lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
256254721Semaste                            if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
257254721Semaste                            {
258254721Semaste                                dynamic_address.SetRawAddress(dynamic_addr);
259254721Semaste                            }
260254721Semaste                            return true;
261254721Semaste                        }
262254721Semaste                    }
263254721Semaste                }
264254721Semaste            }
265254721Semaste        }
266254721Semaste    }
267254721Semaste
268254721Semaste    return class_type_or_name.IsEmpty() == false;
269254721Semaste}
270254721Semaste
271254721Semastebool
272254721SemasteItaniumABILanguageRuntime::IsVTableName (const char *name)
273254721Semaste{
274254721Semaste    if (name == NULL)
275254721Semaste        return false;
276254721Semaste
277254721Semaste    // Can we maybe ask Clang about this?
278254721Semaste    if (strstr (name, "_vptr$") == name)
279254721Semaste        return true;
280254721Semaste    else
281254721Semaste        return false;
282254721Semaste}
283254721Semaste
284254721Semaste//------------------------------------------------------------------
285254721Semaste// Static Functions
286254721Semaste//------------------------------------------------------------------
287254721SemasteLanguageRuntime *
288254721SemasteItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
289254721Semaste{
290254721Semaste    // FIXME: We have to check the process and make sure we actually know that this process supports
291254721Semaste    // the Itanium ABI.
292254721Semaste    if (language == eLanguageTypeC_plus_plus)
293254721Semaste        return new ItaniumABILanguageRuntime (process);
294254721Semaste    else
295254721Semaste        return NULL;
296254721Semaste}
297254721Semaste
298254721Semastevoid
299254721SemasteItaniumABILanguageRuntime::Initialize()
300254721Semaste{
301254721Semaste    PluginManager::RegisterPlugin (GetPluginNameStatic(),
302254721Semaste                                   "Itanium ABI for the C++ language",
303254721Semaste                                   CreateInstance);
304254721Semaste}
305254721Semaste
306254721Semastevoid
307254721SemasteItaniumABILanguageRuntime::Terminate()
308254721Semaste{
309254721Semaste    PluginManager::UnregisterPlugin (CreateInstance);
310254721Semaste}
311254721Semaste
312254721Semastelldb_private::ConstString
313254721SemasteItaniumABILanguageRuntime::GetPluginNameStatic()
314254721Semaste{
315254721Semaste    static ConstString g_name("itanium");
316254721Semaste    return g_name;
317254721Semaste}
318254721Semaste
319254721Semaste//------------------------------------------------------------------
320254721Semaste// PluginInterface protocol
321254721Semaste//------------------------------------------------------------------
322254721Semastelldb_private::ConstString
323254721SemasteItaniumABILanguageRuntime::GetPluginName()
324254721Semaste{
325254721Semaste    return GetPluginNameStatic();
326254721Semaste}
327254721Semaste
328254721Semasteuint32_t
329254721SemasteItaniumABILanguageRuntime::GetPluginVersion()
330254721Semaste{
331254721Semaste    return 1;
332254721Semaste}
333254721Semaste
334254721SemasteBreakpointResolverSP
335254721SemasteItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
336254721Semaste{
337254721Semaste    return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
338254721Semaste}
339254721Semaste
340254721SemasteBreakpointResolverSP
341254721SemasteItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
342254721Semaste{
343254721Semaste    // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
344254721Semaste    // anything better with predicting unwinding the expression parser does.  So we have two forms of the exception
345254721Semaste    // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
346254721Semaste    // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
347254721Semaste    static const char *g_catch_name = "__cxa_begin_catch";
348254721Semaste    static const char *g_throw_name1 = "__cxa_throw";
349254721Semaste    static const char *g_throw_name2 = "__cxa_rethrow";
350254721Semaste    static const char *g_exception_throw_name = "__cxa_allocate_exception";
351254721Semaste    std::vector<const char *> exception_names;
352254721Semaste    exception_names.reserve(4);
353254721Semaste    if (catch_bp)
354254721Semaste        exception_names.push_back(g_catch_name);
355254721Semaste
356254721Semaste    if (throw_bp)
357254721Semaste    {
358254721Semaste        exception_names.push_back(g_throw_name1);
359254721Semaste        exception_names.push_back(g_throw_name2);
360254721Semaste    }
361254721Semaste
362254721Semaste    if (for_expressions)
363254721Semaste        exception_names.push_back(g_exception_throw_name);
364254721Semaste
365254721Semaste    BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
366254721Semaste                                                                  exception_names.data(),
367254721Semaste                                                                  exception_names.size(),
368254721Semaste                                                                  eFunctionNameTypeBase,
369254721Semaste                                                                  eLazyBoolNo));
370254721Semaste
371254721Semaste    return resolver_sp;
372254721Semaste}
373254721Semaste
374254721Semaste
375254721Semaste
376254721Semastelldb::SearchFilterSP
377254721SemasteItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
378254721Semaste{
379254721Semaste    Target &target = m_process->GetTarget();
380254721Semaste
381254721Semaste    if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
382254721Semaste    {
383254721Semaste        // Limit the number of modules that are searched for these breakpoints for
384254721Semaste        // Apple binaries.
385254721Semaste        FileSpecList filter_modules;
386254721Semaste        filter_modules.Append(FileSpec("libc++abi.dylib", false));
387254721Semaste        filter_modules.Append(FileSpec("libSystem.B.dylib", false));
388254721Semaste        return target.GetSearchFilterForModuleList(&filter_modules);
389254721Semaste    }
390254721Semaste    else
391254721Semaste    {
392254721Semaste        return LanguageRuntime::CreateExceptionSearchFilter();
393254721Semaste    }
394254721Semaste}
395254721Semaste
396254721Semastelldb::BreakpointSP
397254721SemasteItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
398254721Semaste                                                      bool throw_bp,
399254721Semaste                                                      bool for_expressions,
400254721Semaste                                                      bool is_internal)
401254721Semaste{
402254721Semaste    Target &target = m_process->GetTarget();
403254721Semaste    FileSpecList filter_modules;
404254721Semaste    BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
405254721Semaste    SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
406269024Semaste    const bool hardware = false;
407269024Semaste    const bool resolve_indirect_functions = false;
408269024Semaste    return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions);
409254721Semaste}
410254721Semaste
411254721Semastevoid
412254721SemasteItaniumABILanguageRuntime::SetExceptionBreakpoints ()
413254721Semaste{
414254721Semaste    if (!m_process)
415254721Semaste        return;
416254721Semaste
417254721Semaste    const bool catch_bp = false;
418254721Semaste    const bool throw_bp = true;
419254721Semaste    const bool is_internal = true;
420254721Semaste    const bool for_expressions = true;
421254721Semaste
422254721Semaste    // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
423254721Semaste    // stop at exception allocation as well.
424254721Semaste
425254721Semaste    if (m_cxx_exception_bp_sp)
426254721Semaste    {
427254721Semaste        m_cxx_exception_bp_sp->SetEnabled (true);
428254721Semaste    }
429254721Semaste    else
430254721Semaste    {
431254721Semaste        m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
432254721Semaste        if (m_cxx_exception_bp_sp)
433254721Semaste            m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
434254721Semaste    }
435254721Semaste
436254721Semaste}
437254721Semaste
438254721Semastevoid
439254721SemasteItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
440254721Semaste{
441254721Semaste    if (!m_process)
442254721Semaste        return;
443254721Semaste
444254721Semaste    if (m_cxx_exception_bp_sp)
445254721Semaste    {
446254721Semaste        m_cxx_exception_bp_sp->SetEnabled (false);
447254721Semaste    }
448254721Semaste}
449254721Semaste
450254721Semastebool
451263367SemasteItaniumABILanguageRuntime::ExceptionBreakpointsAreSet ()
452263367Semaste{
453263367Semaste    return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
454263367Semaste}
455263367Semaste
456263367Semastebool
457254721SemasteItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
458254721Semaste{
459254721Semaste    if (!m_process)
460254721Semaste        return false;
461254721Semaste
462254721Semaste    if (!stop_reason ||
463254721Semaste        stop_reason->GetStopReason() != eStopReasonBreakpoint)
464254721Semaste        return false;
465254721Semaste
466254721Semaste    uint64_t break_site_id = stop_reason->GetValue();
467254721Semaste    return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
468254721Semaste                                                                               m_cxx_exception_bp_sp->GetID());
469254721Semaste
470254721Semaste}
471