blob: 90b17d1c084efb371589f7a0f30b8d7aaf475a2f [file] [log] [blame]
Jim Ingham22777012010-09-23 02:01:19 +00001//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ItaniumABILanguageRuntime.h"
11
Sean Callananf2115102010-11-03 22:19:38 +000012#include "lldb/Breakpoint/BreakpointLocation.h"
Jim Ingham22777012010-09-23 02:01:19 +000013#include "lldb/Core/ConstString.h"
14#include "lldb/Core/Error.h"
15#include "lldb/Core/Module.h"
16#include "lldb/Core/PluginManager.h"
17#include "lldb/Core/Scalar.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000018#include "lldb/Core/ValueObject.h"
19#include "lldb/Core/ValueObjectMemory.h"
Jim Ingham22777012010-09-23 02:01:19 +000020#include "lldb/Symbol/ClangASTContext.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Target/RegisterContext.h"
Sean Callananf2115102010-11-03 22:19:38 +000023#include "lldb/Target/StopInfo.h"
Jim Ingham22777012010-09-23 02:01:19 +000024#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27#include <vector>
28
29using namespace lldb;
30using namespace lldb_private;
31
32static const char *pluginName = "ItaniumABILanguageRuntime";
33static const char *pluginDesc = "Itanium ABI for the C++ language";
34static const char *pluginShort = "language.itanium";
Jim Ingham78a685a2011-04-16 00:01:13 +000035static const char *vtable_demangled_prefix = "vtable for ";
Jim Ingham22777012010-09-23 02:01:19 +000036
Jim Ingham78a685a2011-04-16 00:01:13 +000037bool
38ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
Jim Ingham5a369122010-09-28 01:25:32 +000039{
Greg Clayton007d5be2011-05-30 00:49:24 +000040 return in_value.IsPossibleCPlusPlusDynamicType();
Jim Ingham78a685a2011-04-16 00:01:13 +000041}
42
43bool
Jim Ingham2837b762011-05-04 03:43:18 +000044ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
45 lldb::DynamicValueType use_dynamic,
46 TypeAndOrName &class_type_or_name,
47 Address &dynamic_address)
Jim Ingham78a685a2011-04-16 00:01:13 +000048{
49 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
50 // in the object. That will point to the "address point" within the vtable (not the beginning of the
51 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name
52 // demangled will contain the full class name.
53 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the
54 // start of the value object which holds the dynamic type.
55 //
56
57 // Only a pointer or reference type can have a different dynamic and static type:
58 if (CouldHaveDynamicValue (in_value))
59 {
60 // FIXME: Can we get the Clang Type and ask it if the thing is really virtual? That would avoid false positives,
61 // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong.
62
63 // First job, pull out the address at 0 offset from the object.
64 AddressType address_type;
Enrico Granata9128ee22011-09-06 19:20:51 +000065 lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
Jim Ingham78a685a2011-04-16 00:01:13 +000066 if (original_ptr == LLDB_INVALID_ADDRESS)
67 return false;
68
Enrico Granata6f3533f2011-07-29 19:53:35 +000069 Target *target = in_value.GetUpdatePoint().GetTargetSP().get();
70 Process *process = in_value.GetUpdatePoint().GetProcessSP().get();
Jim Ingham78a685a2011-04-16 00:01:13 +000071
72 char memory_buffer[16];
73 DataExtractor data(memory_buffer, sizeof(memory_buffer),
74 process->GetByteOrder(),
75 process->GetAddressByteSize());
76 size_t address_byte_size = process->GetAddressByteSize();
77 Error error;
78 size_t bytes_read = process->ReadMemory (original_ptr,
79 memory_buffer,
80 address_byte_size,
81 error);
82 if (!error.Success() || (bytes_read != address_byte_size))
83 {
84 return false;
85 }
86
87 uint32_t offset_ptr = 0;
88 lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
89
90 if (offset_ptr == 0)
91 return false;
92
93 // Now find the symbol that contains this address:
94
95 SymbolContext sc;
96 Address address_point_address;
97 if (target && !target->GetSectionLoadList().IsEmpty())
98 {
99 if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
100 {
101 target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
102 Symbol *symbol = sc.symbol;
103 if (symbol != NULL)
104 {
105 const char *name = symbol->GetMangled().GetDemangledName().AsCString();
106 if (strstr(name, vtable_demangled_prefix) == name)
107 {
108 // We are a C++ class, that's good. Get the class name and look it up:
109 const char *class_name = name + strlen(vtable_demangled_prefix);
Jim Ingham61be0902011-05-02 18:13:59 +0000110 class_type_or_name.SetName (class_name);
Jim Ingham78a685a2011-04-16 00:01:13 +0000111 TypeList class_types;
112 uint32_t num_matches = target->GetImages().FindTypes (sc,
113 ConstString(class_name),
114 true,
115 UINT32_MAX,
116 class_types);
117 if (num_matches == 1)
118 {
Jim Ingham61be0902011-05-02 18:13:59 +0000119 class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
Jim Ingham78a685a2011-04-16 00:01:13 +0000120 }
121 else if (num_matches > 1)
122 {
Jim Ingham61be0902011-05-02 18:13:59 +0000123 for (size_t i = 0; i < num_matches; i++)
124 {
125 lldb::TypeSP this_type(class_types.GetTypeAtIndex(i));
126 if (this_type)
127 {
128 if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType()))
129 {
130 // There can only be one type with a given name,
131 // so we've just found duplicate definitions, and this
132 // one will do as well as any other.
133 // We don't consider something to have a dynamic type if
134 // it is the same as the static type. So compare against
135 // the value we were handed:
136
137 clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
138 clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
139 if (in_ast_ctx != this_ast_ctx
140 || !ClangASTContext::AreTypesSame (in_ast_ctx,
141 in_value.GetClangType(),
142 this_type->GetClangFullType()))
143 {
144 class_type_or_name.SetTypeSP (this_type);
145 return true;
146 }
147 return false;
148 }
149 }
150 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000151 }
Jim Ingham61be0902011-05-02 18:13:59 +0000152 else
Jim Ingham78a685a2011-04-16 00:01:13 +0000153 return false;
154
155 // The offset_to_top is two pointers above the address.
156 Address offset_to_top_address = address_point_address;
157 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
158 offset_to_top_address.Slide (slide);
159
160 Error error;
161 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
162
163 size_t bytes_read = process->ReadMemory (offset_to_top_location,
164 memory_buffer,
165 address_byte_size,
166 error);
167
168 if (!error.Success() || (bytes_read != address_byte_size))
169 {
170 return false;
171 }
172
173 offset_ptr = 0;
174 int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
175
176 // So the dynamic type is a value that starts at offset_to_top
177 // above the original address.
178 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
179 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
180 {
181 dynamic_address.SetOffset(dynamic_addr);
182 dynamic_address.SetSection(NULL);
183 }
184 return true;
185 }
186 }
187 }
188 }
189
190 }
191
192 return false;
Jim Ingham5a369122010-09-28 01:25:32 +0000193}
194
195bool
196ItaniumABILanguageRuntime::IsVTableName (const char *name)
197{
198 if (name == NULL)
199 return false;
200
201 // Can we maybe ask Clang about this?
202 if (strstr (name, "_vptr$") == name)
203 return true;
204 else
205 return false;
206}
207
Jim Ingham22777012010-09-23 02:01:19 +0000208//------------------------------------------------------------------
209// Static Functions
210//------------------------------------------------------------------
211lldb_private::LanguageRuntime *
212ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
213{
214 // FIXME: We have to check the process and make sure we actually know that this process supports
215 // the Itanium ABI.
216 if (language == eLanguageTypeC_plus_plus)
217 return new ItaniumABILanguageRuntime (process);
218 else
219 return NULL;
220}
221
222void
223ItaniumABILanguageRuntime::Initialize()
224{
225 PluginManager::RegisterPlugin (pluginName,
226 pluginDesc,
227 CreateInstance);
228}
229
230void
231ItaniumABILanguageRuntime::Terminate()
232{
233 PluginManager::UnregisterPlugin (CreateInstance);
234}
235
236//------------------------------------------------------------------
237// PluginInterface protocol
238//------------------------------------------------------------------
239const char *
240ItaniumABILanguageRuntime::GetPluginName()
241{
242 return pluginName;
243}
244
245const char *
246ItaniumABILanguageRuntime::GetShortPluginName()
247{
248 return pluginShort;
249}
250
251uint32_t
252ItaniumABILanguageRuntime::GetPluginVersion()
253{
254 return 1;
255}
256
257void
Sean Callananf2115102010-11-03 22:19:38 +0000258ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
259{
260 if (!m_process)
261 return;
262
263 if (!m_cxx_exception_bp_sp)
264 m_cxx_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
265 "__cxa_throw",
266 eFunctionNameTypeBase,
267 true);
Jim Inghame3846fd2011-07-23 00:12:05 +0000268 else
269 m_cxx_exception_bp_sp->SetEnabled (true);
Sean Callananf2115102010-11-03 22:19:38 +0000270
271 if (!m_cxx_exception_alloc_bp_sp)
272 m_cxx_exception_alloc_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
273 "__cxa_allocate",
274 eFunctionNameTypeBase,
275 true);
Jim Inghame3846fd2011-07-23 00:12:05 +0000276 else
277 m_cxx_exception_alloc_bp_sp->SetEnabled (true);
Sean Callananf2115102010-11-03 22:19:38 +0000278}
279
280void
281ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
282{
283 if (!m_process)
284 return;
285
286 if (m_cxx_exception_bp_sp.get())
287 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000288 m_cxx_exception_bp_sp->SetEnabled (false);
Sean Callananf2115102010-11-03 22:19:38 +0000289 }
290
291 if (m_cxx_exception_alloc_bp_sp.get())
292 {
Jim Inghame3846fd2011-07-23 00:12:05 +0000293 m_cxx_exception_bp_sp->SetEnabled (false);
Sean Callananf2115102010-11-03 22:19:38 +0000294 }
295}
296
297bool
298ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
299{
300 if (!m_process)
301 return false;
302
303 if (!stop_reason ||
304 stop_reason->GetStopReason() != eStopReasonBreakpoint)
305 return false;
306
307 uint64_t break_site_id = stop_reason->GetValue();
308 lldb::BreakpointSiteSP bp_site_sp = m_process->GetBreakpointSiteList().FindByID(break_site_id);
309
310 if (!bp_site_sp)
311 return false;
312
313 uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
314
315 bool check_cxx_exception = false;
316 break_id_t cxx_exception_bid;
317
318 bool check_cxx_exception_alloc = false;
319 break_id_t cxx_exception_alloc_bid;
320
321 if (m_cxx_exception_bp_sp)
322 {
323 check_cxx_exception = true;
324 cxx_exception_bid = m_cxx_exception_bp_sp->GetID();
325 }
326
327 if (m_cxx_exception_alloc_bp_sp)
328 {
329 check_cxx_exception_alloc = true;
330 cxx_exception_alloc_bid = m_cxx_exception_alloc_bp_sp->GetID();
331 }
332
333 for (uint32_t i = 0; i < num_owners; i++)
334 {
335 break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID();
336
337 if ((check_cxx_exception && (bid == cxx_exception_bid)) ||
338 (check_cxx_exception_alloc && (bid == cxx_exception_alloc_bid)))
339 return true;
340 }
341
342 return false;
343}