blob: 6713a0ad674d02a2dc528f013f99e461859cbf00 [file] [log] [blame]
Kate Stoneb9c1b512016-09-06 20:57:50 +00001//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*-
2//C++ -*-===//
Jim Ingham22777012010-09-23 02:01:19 +00003//
Chandler Carruth2946cd72019-01-19 08:50:56 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jim Ingham22777012010-09-23 02:01:19 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "ItaniumABILanguageRuntime.h"
11
Sean Callananf2115102010-11-03 22:19:38 +000012#include "lldb/Breakpoint/BreakpointLocation.h"
Enrico Granata221cfdd2016-03-25 23:14:24 +000013#include "lldb/Core/Mangled.h"
Jim Ingham22777012010-09-23 02:01:19 +000014#include "lldb/Core/Module.h"
15#include "lldb/Core/PluginManager.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000016#include "lldb/Core/ValueObject.h"
17#include "lldb/Core/ValueObjectMemory.h"
Kuba Mracekc9e11902018-12-20 02:01:59 +000018#include "lldb/DataFormatters/FormattersHelpers.h"
19#include "lldb/Expression/DiagnosticManager.h"
20#include "lldb/Expression/FunctionCaller.h"
Enrico Granata221cfdd2016-03-25 23:14:24 +000021#include "lldb/Interpreter/CommandObject.h"
22#include "lldb/Interpreter/CommandObjectMultiword.h"
23#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham22777012010-09-23 02:01:19 +000024#include "lldb/Symbol/ClangASTContext.h"
Greg Clayton1f746072012-08-29 21:13:06 +000025#include "lldb/Symbol/Symbol.h"
Greg Claytonae088e52016-02-10 21:28:13 +000026#include "lldb/Symbol/SymbolFile.h"
Greg Clayton1f746072012-08-29 21:13:06 +000027#include "lldb/Symbol/TypeList.h"
Jim Ingham22777012010-09-23 02:01:19 +000028#include "lldb/Target/Process.h"
29#include "lldb/Target/RegisterContext.h"
Greg Claytond5944cd2013-12-06 01:12:00 +000030#include "lldb/Target/SectionLoadList.h"
Sean Callananf2115102010-11-03 22:19:38 +000031#include "lldb/Target/StopInfo.h"
Jim Ingham22777012010-09-23 02:01:19 +000032#include "lldb/Target/Target.h"
33#include "lldb/Target/Thread.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000034#include "lldb/Utility/ConstString.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000035#include "lldb/Utility/Log.h"
Pavel Labathd821c992018-08-07 11:07:21 +000036#include "lldb/Utility/Scalar.h"
Zachary Turner97206d52017-05-12 04:51:55 +000037#include "lldb/Utility/Status.h"
Jim Ingham22777012010-09-23 02:01:19 +000038
39#include <vector>
40
41using namespace lldb;
42using namespace lldb_private;
43
Jim Ingham78a685a2011-04-16 00:01:13 +000044static const char *vtable_demangled_prefix = "vtable for ";
Jim Ingham22777012010-09-23 02:01:19 +000045
Alex Langford056f6f12019-06-08 18:45:00 +000046char ItaniumABILanguageRuntime::ID = 0;
47
Kate Stoneb9c1b512016-09-06 20:57:50 +000048bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
49 const bool check_cxx = true;
50 const bool check_objc = false;
Konrad Kleine248a1302019-05-23 11:14:47 +000051 return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx,
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 check_objc);
Jim Ingham78a685a2011-04-16 00:01:13 +000053}
54
Kate Stoneb9c1b512016-09-06 20:57:50 +000055TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
56 ValueObject &in_value, lldb::addr_t original_ptr,
57 lldb::addr_t vtable_load_addr) {
58 if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) {
59 // Find the symbol that contains the "vtable_load_addr" address
60 Address vtable_addr;
61 Target &target = m_process->GetTarget();
62 if (!target.GetSectionLoadList().IsEmpty()) {
63 if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr,
64 vtable_addr)) {
65 // See if we have cached info for this type already
66 TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr);
67 if (type_info)
68 return type_info;
Greg Claytonc2267782016-05-23 20:37:24 +000069
Kate Stoneb9c1b512016-09-06 20:57:50 +000070 SymbolContext sc;
71 target.GetImages().ResolveSymbolContextForAddress(
72 vtable_addr, eSymbolContextSymbol, sc);
73 Symbol *symbol = sc.symbol;
Konrad Kleine248a1302019-05-23 11:14:47 +000074 if (symbol != nullptr) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 const char *name =
76 symbol->GetMangled()
77 .GetDemangledName(lldb::eLanguageTypeC_plus_plus)
78 .AsCString();
79 if (name && strstr(name, vtable_demangled_prefix) == name) {
80 Log *log(
81 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +000082 LLDB_LOGF(log,
83 "0x%16.16" PRIx64
84 ": static-type = '%s' has vtable symbol '%s'\n",
85 original_ptr, in_value.GetTypeName().GetCString(), name);
Kate Stoneb9c1b512016-09-06 20:57:50 +000086 // We are a C++ class, that's good. Get the class name and look it
87 // up:
88 const char *class_name = name + strlen(vtable_demangled_prefix);
Jim Ingham06292862018-03-01 02:44:34 +000089 // We know the class name is absolute, so tell FindTypes that by
90 // prefixing it with the root namespace:
91 std::string lookup_name("::");
92 lookup_name.append(class_name);
93
Kate Stoneb9c1b512016-09-06 20:57:50 +000094 type_info.SetName(class_name);
95 const bool exact_match = true;
96 TypeList class_types;
Greg Claytonc2267782016-05-23 20:37:24 +000097
Kate Stoneb9c1b512016-09-06 20:57:50 +000098 uint32_t num_matches = 0;
Adrian Prantl05097242018-04-30 16:49:04 +000099 // First look in the module that the vtable symbol came from and
100 // look for a single exact match.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 llvm::DenseSet<SymbolFile *> searched_symbol_files;
102 if (sc.module_sp) {
103 num_matches = sc.module_sp->FindTypes(
Zachary Turner576495e2019-01-14 22:41:21 +0000104 ConstString(lookup_name), exact_match, 1,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105 searched_symbol_files, class_types);
Jim Ingham78a685a2011-04-16 00:01:13 +0000106 }
Greg Claytonc2267782016-05-23 20:37:24 +0000107
Adrian Prantl05097242018-04-30 16:49:04 +0000108 // If we didn't find a symbol, then move on to the entire module
109 // list in the target and get as many unique matches as possible
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 if (num_matches == 0) {
111 num_matches = target.GetImages().FindTypes(
Zachary Turner576495e2019-01-14 22:41:21 +0000112 nullptr, ConstString(lookup_name), exact_match, UINT32_MAX,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 searched_symbol_files, class_types);
Greg Claytonc2267782016-05-23 20:37:24 +0000114 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115
116 lldb::TypeSP type_sp;
117 if (num_matches == 0) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000118 LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n",
119 original_ptr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 return TypeAndOrName();
121 }
122 if (num_matches == 1) {
123 type_sp = class_types.GetTypeAtIndex(0);
124 if (type_sp) {
125 if (ClangASTContext::IsCXXClassType(
126 type_sp->GetForwardCompilerType())) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000127 LLDB_LOGF(
128 log,
129 "0x%16.16" PRIx64
130 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
131 "}, type-name='%s'\n",
132 original_ptr, in_value.GetTypeName().AsCString(),
133 type_sp->GetID(), type_sp->GetName().GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134 type_info.SetTypeSP(type_sp);
135 }
136 }
137 } else if (num_matches > 1) {
138 size_t i;
139 if (log) {
140 for (i = 0; i < num_matches; i++) {
141 type_sp = class_types.GetTypeAtIndex(i);
142 if (type_sp) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000143 LLDB_LOGF(
144 log,
145 "0x%16.16" PRIx64
146 ": static-type = '%s' has multiple matching dynamic "
147 "types: uid={0x%" PRIx64 "}, type-name='%s'\n",
148 original_ptr, in_value.GetTypeName().AsCString(),
149 type_sp->GetID(), type_sp->GetName().GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150 }
151 }
152 }
153
154 for (i = 0; i < num_matches; i++) {
155 type_sp = class_types.GetTypeAtIndex(i);
156 if (type_sp) {
157 if (ClangASTContext::IsCXXClassType(
158 type_sp->GetForwardCompilerType())) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000159 LLDB_LOGF(
160 log,
161 "0x%16.16" PRIx64 ": static-type = '%s' has multiple "
162 "matching dynamic types, picking "
163 "this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
164 original_ptr, in_value.GetTypeName().AsCString(),
165 type_sp->GetID(), type_sp->GetName().GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166 type_info.SetTypeSP(type_sp);
167 }
168 }
169 }
170
171 if (log && i == num_matches) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000172 LLDB_LOGF(log,
173 "0x%16.16" PRIx64
174 ": static-type = '%s' has multiple matching dynamic "
175 "types, didn't find a C++ match\n",
176 original_ptr, in_value.GetTypeName().AsCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177 }
178 }
179 if (type_info)
180 SetDynamicTypeInfo(vtable_addr, type_info);
181 return type_info;
182 }
Greg Claytonc2267782016-05-23 20:37:24 +0000183 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 }
Greg Claytonc2267782016-05-23 20:37:24 +0000185 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 }
187 return TypeAndOrName();
Jim Ingham5a369122010-09-28 01:25:32 +0000188}
189
Kate Stoneb9c1b512016-09-06 20:57:50 +0000190bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
191 ValueObject &in_value, lldb::DynamicValueType use_dynamic,
192 TypeAndOrName &class_type_or_name, Address &dynamic_address,
193 Value::ValueType &value_type) {
194 // For Itanium, if the type has a vtable pointer in the object, it will be at
Adrian Prantl05097242018-04-30 16:49:04 +0000195 // offset 0 in the object. That will point to the "address point" within the
196 // vtable (not the beginning of the vtable.) We can then look up the symbol
197 // containing this "address point" and that symbol's name demangled will
198 // contain the full class name. The second pointer above the "address point"
199 // is the "offset_to_top". We'll use that to get the start of the value
200 // object which holds the dynamic type.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000201 //
Enrico Granatac74275b2015-09-22 19:45:52 +0000202
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203 class_type_or_name.Clear();
204 value_type = Value::ValueType::eValueTypeScalar;
205
206 // Only a pointer or reference type can have a different dynamic and static
207 // type:
Adrian Prantl212e23d2018-10-15 21:35:45 +0000208 if (!CouldHaveDynamicValue(in_value))
209 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210
Adrian Prantl212e23d2018-10-15 21:35:45 +0000211 // 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;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216
Adrian Prantl212e23d2018-10-15 21:35:45 +0000217 ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218
Adrian Prantl212e23d2018-10-15 21:35:45 +0000219 Process *process = exe_ctx.GetProcessPtr();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220
Adrian Prantl212e23d2018-10-15 21:35:45 +0000221 if (process == nullptr)
222 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000223
Adrian Prantl212e23d2018-10-15 21:35:45 +0000224 Status error;
225 const lldb::addr_t vtable_address_point =
226 process->ReadPointerFromMemory(original_ptr, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227
Adrian Prantl212e23d2018-10-15 21:35:45 +0000228 if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS)
229 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230
Adrian Prantl212e23d2018-10-15 21:35:45 +0000231 class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr,
232 vtable_address_point);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233
Adrian Prantl212e23d2018-10-15 21:35:45 +0000234 if (!class_type_or_name)
235 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236
Pavel Labatha933d6c2019-03-15 14:02:35 +0000237 CompilerType type = class_type_or_name.GetCompilerType();
Adrian Prantl212e23d2018-10-15 21:35:45 +0000238 // There can only be one type with a given name, so we've just found
239 // duplicate definitions, and this one will do as well as any other. We
240 // don't consider something to have a dynamic type if it is the same as
241 // the static type. So compare against the value we were handed.
Pavel Labatha933d6c2019-03-15 14:02:35 +0000242 if (!type)
Adrian Prantl212e23d2018-10-15 21:35:45 +0000243 return true;
244
Pavel Labatha933d6c2019-03-15 14:02:35 +0000245 if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type)) {
Adrian Prantl212e23d2018-10-15 21:35:45 +0000246 // The dynamic type we found was the same type, so we don't have a
247 // dynamic type here...
248 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 }
250
Adrian Prantl212e23d2018-10-15 21:35:45 +0000251 // The offset_to_top is two pointers above the vtable pointer.
252 const uint32_t addr_byte_size = process->GetAddressByteSize();
253 const lldb::addr_t offset_to_top_location =
254 vtable_address_point - 2 * addr_byte_size;
255 // Watch for underflow, offset_to_top_location should be less than
256 // vtable_address_point
257 if (offset_to_top_location >= vtable_address_point)
258 return false;
259 const int64_t offset_to_top = process->ReadSignedIntegerFromMemory(
260 offset_to_top_location, addr_byte_size, INT64_MIN, error);
261
262 if (offset_to_top == INT64_MIN)
263 return false;
264 // So the dynamic type is a value that starts at offset_to_top above
265 // the original address.
266 lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
267 if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(
268 dynamic_addr, dynamic_address)) {
269 dynamic_address.SetRawAddress(dynamic_addr);
270 }
271 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272}
273
274TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType(
275 const TypeAndOrName &type_and_or_name, ValueObject &static_value) {
276 CompilerType static_type(static_value.GetCompilerType());
277 Flags static_type_flags(static_type.GetTypeInfo());
278
279 TypeAndOrName ret(type_and_or_name);
280 if (type_and_or_name.HasType()) {
281 // The type will always be the type of the dynamic object. If our parent's
Adrian Prantl05097242018-04-30 16:49:04 +0000282 // type was a pointer, then our type should be a pointer to the type of the
283 // dynamic object. If a reference, then the original type should be
284 // okay...
Kate Stoneb9c1b512016-09-06 20:57:50 +0000285 CompilerType orig_type = type_and_or_name.GetCompilerType();
286 CompilerType corrected_type = orig_type;
287 if (static_type_flags.AllSet(eTypeIsPointer))
288 corrected_type = orig_type.GetPointerType();
289 else if (static_type_flags.AllSet(eTypeIsReference))
290 corrected_type = orig_type.GetLValueReferenceType();
291 ret.SetCompilerType(corrected_type);
292 } else {
293 // If we are here we need to adjust our dynamic type name to include the
294 // correct & or * symbol
295 std::string corrected_name(type_and_or_name.GetName().GetCString());
296 if (static_type_flags.AllSet(eTypeIsPointer))
297 corrected_name.append(" *");
298 else if (static_type_flags.AllSet(eTypeIsReference))
299 corrected_name.append(" &");
300 // the parent type should be a correctly pointer'ed or referenc'ed type
301 ret.SetCompilerType(static_type);
302 ret.SetName(corrected_name.c_str());
303 }
304 return ret;
305}
306
Jim Ingham22777012010-09-23 02:01:19 +0000307// Static Functions
Jim Ingham133e0fb2012-03-03 02:05:11 +0000308LanguageRuntime *
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309ItaniumABILanguageRuntime::CreateInstance(Process *process,
310 lldb::LanguageType language) {
311 // FIXME: We have to check the process and make sure we actually know that
312 // this process supports
313 // the Itanium ABI.
314 if (language == eLanguageTypeC_plus_plus ||
315 language == eLanguageTypeC_plus_plus_03 ||
316 language == eLanguageTypeC_plus_plus_11 ||
317 language == eLanguageTypeC_plus_plus_14)
318 return new ItaniumABILanguageRuntime(process);
319 else
Konrad Kleine248a1302019-05-23 11:14:47 +0000320 return nullptr;
Jim Ingham22777012010-09-23 02:01:19 +0000321}
322
Kate Stoneb9c1b512016-09-06 20:57:50 +0000323class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed {
Enrico Granata221cfdd2016-03-25 23:14:24 +0000324public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 CommandObjectMultiwordItaniumABI_Demangle(CommandInterpreter &interpreter)
326 : CommandObjectParsed(interpreter, "demangle",
327 "Demangle a C++ mangled name.",
328 "language cplusplus demangle") {
329 CommandArgumentEntry arg;
330 CommandArgumentData index_arg;
331
332 // Define the first (and only) variant of this arg.
333 index_arg.arg_type = eArgTypeSymbol;
334 index_arg.arg_repetition = eArgRepeatPlus;
335
336 // There is only one variant this argument could be; put it into the
337 // argument entry.
338 arg.push_back(index_arg);
339
340 // Push the data for the first argument into the m_arguments vector.
341 m_arguments.push_back(arg);
342 }
343
344 ~CommandObjectMultiwordItaniumABI_Demangle() override = default;
345
Enrico Granata221cfdd2016-03-25 23:14:24 +0000346protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 bool DoExecute(Args &command, CommandReturnObject &result) override {
348 bool demangled_any = false;
349 bool error_any = false;
Zachary Turner97d2c402016-10-05 23:40:23 +0000350 for (auto &entry : command.entries()) {
Raphael Isemann0d9a2012019-09-13 11:26:48 +0000351 if (entry.ref().empty())
Zachary Turner97d2c402016-10-05 23:40:23 +0000352 continue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000353
Zachary Turner97d2c402016-10-05 23:40:23 +0000354 // the actual Mangled class should be strict about this, but on the
355 // command line if you're copying mangled names out of 'nm' on Darwin,
Adrian Prantl05097242018-04-30 16:49:04 +0000356 // they will come out with an extra underscore - be willing to strip this
357 // on behalf of the user. This is the moral equivalent of the -_/-n
Zachary Turner97d2c402016-10-05 23:40:23 +0000358 // options to c++filt
Raphael Isemann0d9a2012019-09-13 11:26:48 +0000359 auto name = entry.ref();
Zachary Turner97d2c402016-10-05 23:40:23 +0000360 if (name.startswith("__Z"))
361 name = name.drop_front();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362
Zachary Turner97d2c402016-10-05 23:40:23 +0000363 Mangled mangled(name, true);
364 if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) {
365 ConstString demangled(
366 mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus));
367 demangled_any = true;
Raphael Isemann0d9a2012019-09-13 11:26:48 +0000368 result.AppendMessageWithFormat("%s ---> %s\n", entry.c_str(),
Zachary Turner97d2c402016-10-05 23:40:23 +0000369 demangled.GetCString());
370 } else {
371 error_any = true;
372 result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n",
Raphael Isemann0d9a2012019-09-13 11:26:48 +0000373 entry.ref().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000374 }
Enrico Granata221cfdd2016-03-25 23:14:24 +0000375 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376
377 result.SetStatus(
378 error_any ? lldb::eReturnStatusFailed
379 : (demangled_any ? lldb::eReturnStatusSuccessFinishResult
380 : lldb::eReturnStatusSuccessFinishNoResult));
381 return result.Succeeded();
382 }
Enrico Granata221cfdd2016-03-25 23:14:24 +0000383};
384
Kate Stoneb9c1b512016-09-06 20:57:50 +0000385class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword {
Enrico Granata221cfdd2016-03-25 23:14:24 +0000386public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000387 CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter)
388 : CommandObjectMultiword(
389 interpreter, "cplusplus",
390 "Commands for operating on the C++ language runtime.",
391 "cplusplus <subcommand> [<subcommand-options>]") {
392 LoadSubCommand(
393 "demangle",
394 CommandObjectSP(
395 new CommandObjectMultiwordItaniumABI_Demangle(interpreter)));
396 }
397
398 ~CommandObjectMultiwordItaniumABI() override = default;
Enrico Granata221cfdd2016-03-25 23:14:24 +0000399};
400
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401void ItaniumABILanguageRuntime::Initialize() {
402 PluginManager::RegisterPlugin(
403 GetPluginNameStatic(), "Itanium ABI for the C++ language", CreateInstance,
404 [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
405 return CommandObjectSP(
406 new CommandObjectMultiwordItaniumABI(interpreter));
407 });
Jim Ingham22777012010-09-23 02:01:19 +0000408}
409
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410void ItaniumABILanguageRuntime::Terminate() {
411 PluginManager::UnregisterPlugin(CreateInstance);
Jim Ingham22777012010-09-23 02:01:19 +0000412}
413
Kate Stoneb9c1b512016-09-06 20:57:50 +0000414lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginNameStatic() {
415 static ConstString g_name("itanium");
416 return g_name;
Greg Clayton57abc5d2013-05-10 21:47:16 +0000417}
418
Jim Ingham22777012010-09-23 02:01:19 +0000419// PluginInterface protocol
Kate Stoneb9c1b512016-09-06 20:57:50 +0000420lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginName() {
421 return GetPluginNameStatic();
Jim Ingham22777012010-09-23 02:01:19 +0000422}
423
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424uint32_t ItaniumABILanguageRuntime::GetPluginVersion() { return 1; }
425
426BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
427 Breakpoint *bkpt, bool catch_bp, bool throw_bp) {
428 return CreateExceptionResolver(bkpt, catch_bp, throw_bp, false);
Jim Ingham22777012010-09-23 02:01:19 +0000429}
430
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
432 Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) {
433 // One complication here is that most users DON'T want to stop at
Adrian Prantl05097242018-04-30 16:49:04 +0000434 // __cxa_allocate_expression, but until we can do anything better with
435 // predicting unwinding the expression parser does. So we have two forms of
436 // the exception breakpoints, one for expressions that leaves out
437 // __cxa_allocate_exception, and one that includes it. The
438 // SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in
439 // the runtime the former.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000440 static const char *g_catch_name = "__cxa_begin_catch";
441 static const char *g_throw_name1 = "__cxa_throw";
442 static const char *g_throw_name2 = "__cxa_rethrow";
443 static const char *g_exception_throw_name = "__cxa_allocate_exception";
444 std::vector<const char *> exception_names;
445 exception_names.reserve(4);
446 if (catch_bp)
447 exception_names.push_back(g_catch_name);
448
449 if (throw_bp) {
450 exception_names.push_back(g_throw_name1);
451 exception_names.push_back(g_throw_name2);
452 }
453
454 if (for_expressions)
455 exception_names.push_back(g_exception_throw_name);
456
457 BreakpointResolverSP resolver_sp(new BreakpointResolverName(
458 bkpt, exception_names.data(), exception_names.size(),
459 eFunctionNameTypeBase, eLanguageTypeUnknown, 0, eLazyBoolNo));
460
461 return resolver_sp;
Jim Inghamf0fd55e2012-03-06 18:10:38 +0000462}
463
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() {
465 Target &target = m_process->GetTarget();
Greg Claytonbff78252013-03-11 18:42:51 +0000466
Alex Langford6691f1b2019-06-11 22:52:08 +0000467 FileSpecList filter_modules;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468 if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) {
469 // Limit the number of modules that are searched for these breakpoints for
470 // Apple binaries.
Jonas Devliegheref893d5b2019-07-18 20:19:24 +0000471 filter_modules.EmplaceBack("libc++abi.dylib");
472 filter_modules.EmplaceBack("libSystem.B.dylib");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473 }
Alex Langford6691f1b2019-06-11 22:52:08 +0000474 return target.GetSearchFilterForModuleList(&filter_modules);
Greg Claytonbff78252013-03-11 18:42:51 +0000475}
476
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477lldb::BreakpointSP ItaniumABILanguageRuntime::CreateExceptionBreakpoint(
478 bool catch_bp, bool throw_bp, bool for_expressions, bool is_internal) {
479 Target &target = m_process->GetTarget();
480 FileSpecList filter_modules;
481 BreakpointResolverSP exception_resolver_sp =
Konrad Kleine248a1302019-05-23 11:14:47 +0000482 CreateExceptionResolver(nullptr, catch_bp, throw_bp, for_expressions);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483 SearchFilterSP filter_sp(CreateExceptionSearchFilter());
484 const bool hardware = false;
485 const bool resolve_indirect_functions = false;
486 return target.CreateBreakpoint(filter_sp, exception_resolver_sp, is_internal,
487 hardware, resolve_indirect_functions);
488}
489
490void ItaniumABILanguageRuntime::SetExceptionBreakpoints() {
491 if (!m_process)
492 return;
493
494 const bool catch_bp = false;
495 const bool throw_bp = true;
496 const bool is_internal = true;
497 const bool for_expressions = true;
498
499 // For the exception breakpoints set by the Expression parser, we'll be a
Adrian Prantl05097242018-04-30 16:49:04 +0000500 // little more aggressive and stop at exception allocation as well.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501
502 if (m_cxx_exception_bp_sp) {
503 m_cxx_exception_bp_sp->SetEnabled(true);
504 } else {
505 m_cxx_exception_bp_sp = CreateExceptionBreakpoint(
506 catch_bp, throw_bp, for_expressions, is_internal);
Greg Claytonbff78252013-03-11 18:42:51 +0000507 if (m_cxx_exception_bp_sp)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000508 m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
509 }
Sean Callananf2115102010-11-03 22:19:38 +0000510}
511
Kate Stoneb9c1b512016-09-06 20:57:50 +0000512void ItaniumABILanguageRuntime::ClearExceptionBreakpoints() {
513 if (!m_process)
514 return;
515
516 if (m_cxx_exception_bp_sp) {
517 m_cxx_exception_bp_sp->SetEnabled(false);
518 }
Sean Callananf2115102010-11-03 22:19:38 +0000519}
520
Kate Stoneb9c1b512016-09-06 20:57:50 +0000521bool ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet() {
522 return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000523}
524
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525bool ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop(
526 lldb::StopInfoSP stop_reason) {
527 if (!m_process)
528 return false;
529
530 if (!stop_reason || stop_reason->GetStopReason() != eStopReasonBreakpoint)
531 return false;
532
533 uint64_t break_site_id = stop_reason->GetValue();
534 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(
535 break_site_id, m_cxx_exception_bp_sp->GetID());
Sean Callananf2115102010-11-03 22:19:38 +0000536}
Greg Claytonc2267782016-05-23 20:37:24 +0000537
Kuba Mracekc9e11902018-12-20 02:01:59 +0000538ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread(
539 ThreadSP thread_sp) {
Kuba Mracek19d1f202019-01-04 00:20:52 +0000540 if (!thread_sp->SafeToCallFunctions())
541 return {};
542
Kuba Mracekc9e11902018-12-20 02:01:59 +0000543 ClangASTContext *clang_ast_context =
544 m_process->GetTarget().GetScratchClangASTContext();
545 CompilerType voidstar =
546 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
547
548 DiagnosticManager diagnostics;
549 ExecutionContext exe_ctx;
550 EvaluateExpressionOptions options;
551
552 options.SetUnwindOnError(true);
553 options.SetIgnoreBreakpoints(true);
554 options.SetStopOthers(true);
Adrian Prantl4c03ea12019-04-05 22:43:42 +0000555 options.SetTimeout(m_process->GetUtilityExpressionTimeout());
Kuba Mracekc9e11902018-12-20 02:01:59 +0000556 options.SetTryAllThreads(false);
557 thread_sp->CalculateExecutionContext(exe_ctx);
558
559 const ModuleList &modules = m_process->GetTarget().GetImages();
560 SymbolContextList contexts;
561 SymbolContext context;
562
563 modules.FindSymbolsWithNameAndType(
564 ConstString("__cxa_current_exception_type"), eSymbolTypeCode, contexts);
565 contexts.GetContextAtIndex(0, context);
566 Address addr = context.symbol->GetAddress();
567
568 Status error;
569 FunctionCaller *function_caller =
570 m_process->GetTarget().GetFunctionCallerForLanguage(
571 eLanguageTypeC, voidstar, addr, ValueList(), "caller", error);
572
573 ExpressionResults func_call_ret;
574 Value results;
575 func_call_ret = function_caller->ExecuteFunction(exe_ctx, nullptr, options,
576 diagnostics, results);
577 if (func_call_ret != eExpressionCompleted || !error.Success()) {
578 return ValueObjectSP();
579 }
580
581 size_t ptr_size = m_process->GetAddressByteSize();
582 addr_t result_ptr = results.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
583 addr_t exception_addr =
584 m_process->ReadPointerFromMemory(result_ptr - ptr_size, error);
585
Alex Langfordbd3adfe2019-05-15 01:46:45 +0000586 if (!error.Success()) {
587 return ValueObjectSP();
588 }
589
Kuba Mracekc9e11902018-12-20 02:01:59 +0000590 lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr,
591 *m_process);
592 ValueObjectSP exception = ValueObject::CreateValueObjectFromData(
593 "exception", exception_isw.GetAsData(m_process->GetByteOrder()), exe_ctx,
594 voidstar);
595 exception = exception->GetDynamicValue(eDynamicDontRunTarget);
596
597 return exception;
598}
599
Kate Stoneb9c1b512016-09-06 20:57:50 +0000600TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo(
601 const lldb_private::Address &vtable_addr) {
602 std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
603 DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr);
604 if (pos == m_dynamic_type_map.end())
605 return TypeAndOrName();
606 else
607 return pos->second;
Greg Claytonc2267782016-05-23 20:37:24 +0000608}
609
Kate Stoneb9c1b512016-09-06 20:57:50 +0000610void ItaniumABILanguageRuntime::SetDynamicTypeInfo(
611 const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) {
612 std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
613 m_dynamic_type_map[vtable_addr] = type_info;
Greg Claytonc2267782016-05-23 20:37:24 +0000614}