[Go to site: main page, start]

LLDB mainline
ItaniumABIRuntime.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ItaniumABIRuntime.h"
10
16
17using namespace lldb;
18using namespace lldb_private;
19
20static const char *vtable_demangled_prefix = "vtable for ";
21
24
25llvm::StringRef ItaniumABIRuntime::GetName() const {
26 return "Itanium ABI runtime";
27}
28
30 return mangled.GetDemangledName().GetStringRef().starts_with(
32}
33
36 const LanguageRuntime::VTableInfo &vtable_info) {
37 if (vtable_info.addr.IsSectionOffset()) {
38 // See if we have cached info for this type already
39 TypeAndOrName type_info = GetDynamicTypeInfo(vtable_info.addr);
40 if (type_info)
41 return type_info;
42
43 if (vtable_info.symbol) {
45 llvm::StringRef symbol_name =
47 LLDB_LOGF(log,
48 "0x%16.16" PRIx64
49 ": static-type = '%s' has vtable symbol '%s'\n",
50 in_value.GetPointerValue().address,
51 in_value.GetTypeName().GetCString(), symbol_name.str().c_str());
52 // We are a C++ class, that's good. Get the class name and look it
53 // up:
54 llvm::StringRef class_name = symbol_name;
55 class_name.consume_front(vtable_demangled_prefix);
56 // We know the class name is absolute, so tell FindTypes that by
57 // prefixing it with the root namespace:
58 std::string lookup_name("::");
59 lookup_name.append(class_name.data(), class_name.size());
60
61 type_info.SetName(class_name);
62 bool any_found = false;
63 TypeSP type_sp = LookupTypeByName(
64 class_name, vtable_info.symbol->CalculateSymbolContextModule(),
65 any_found);
66 if (!any_found)
67 return TypeAndOrName(); // Type is not dynamic.
68
69 if (type_sp) {
70 LLDB_LOGF(log,
71 "0x%16.16" PRIx64
72 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
73 "}, type-name='%s'\n",
74 in_value.GetPointerValue().address,
75 in_value.GetTypeName().AsCString(""), type_sp->GetID(),
76 type_sp->GetName().GetCString());
77 type_info.SetTypeSP(std::move(type_sp));
78 }
79 if (type_info)
80 SetDynamicTypeInfo(vtable_info.addr, type_info);
81 return type_info;
82 }
83 }
84 return TypeAndOrName();
85}
86
88 ValueObject &in_value, lldb::DynamicValueType use_dynamic,
89 const LanguageRuntime::VTableInfo &vtable_info,
90 TypeAndOrName &class_type_or_name, Address &dynamic_address) {
91 // For Itanium, if the type has a vtable pointer in the object, it will be at
92 // offset 0 in the object. That will point to the "address point" within the
93 // vtable (not the beginning of the vtable.) We can then look up the symbol
94 // containing this "address point" and that symbol's name demangled will
95 // contain the full class name. The second pointer above the "address point"
96 // is the "offset_to_top". We'll use that to get the start of the value
97 // object which holds the dynamic type.
98
99 // Check if we have a vtable pointer in this value. If we don't it will
100 // return an error, else it will return a valid resolved address. We don't
101 // want GetVTableInfo to check the type since we accept void * as a possible
102 // dynamic type and that won't pass the type check. We already checked the
103 // type above in CouldHaveDynamicValue(...).
104 class_type_or_name = GetTypeInfo(in_value, vtable_info);
105
106 if (!class_type_or_name)
107 return false;
108
109 CompilerType type = class_type_or_name.GetCompilerType();
110 // There can only be one type with a given name, so we've just found
111 // duplicate definitions, and this one will do as well as any other. We
112 // don't consider something to have a dynamic type if it is the same as
113 // the static type. So compare against the value we were handed.
114 if (!type)
115 return true;
116
117 if (TypeSystemClang::AreTypesSame(in_value.GetCompilerType(), type)) {
118 // The dynamic type we found was the same type, so we don't have a
119 // dynamic type here...
120 return false;
121 }
122
123 // The offset_to_top is two pointers above the vtable pointer.
124 Target &target = m_process->GetTarget();
125 const addr_t vtable_load_addr = vtable_info.addr.GetLoadAddress(&target);
126 if (vtable_load_addr == LLDB_INVALID_ADDRESS)
127 return false;
128 const uint32_t addr_byte_size = m_process->GetAddressByteSize();
129 const lldb::addr_t offset_to_top_location =
130 vtable_load_addr - 2 * addr_byte_size;
131 // Watch for underflow, offset_to_top_location should be less than
132 // vtable_load_addr
133 if (offset_to_top_location >= vtable_load_addr)
134 return false;
136 const int64_t offset_to_top = target.ReadSignedIntegerFromMemory(
137 Address(offset_to_top_location), addr_byte_size, INT64_MIN, error);
138
139 if (offset_to_top == INT64_MIN)
140 return false;
141 // So the dynamic type is a value that starts at offset_to_top above
142 // the original address.
143 lldb::addr_t dynamic_addr =
144 in_value.GetPointerValue().address + offset_to_top;
145 if (!m_process->GetTarget().ResolveLoadAddress(dynamic_addr,
146 dynamic_address)) {
147 dynamic_address.SetRawAddress(dynamic_addr);
148 }
149 return true;
150}
151
153 std::vector<const char *> &names, bool catch_bp, bool throw_bp,
154 bool for_expressions) {
155 // One complication here is that most users DON'T want to stop at
156 // __cxa_allocate_expression, but until we can do anything better with
157 // predicting unwinding the expression parser does. So we have two forms of
158 // the exception breakpoints, one for expressions that leaves out
159 // __cxa_allocate_exception, and one that includes it. The
160 // SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in
161 // the runtime the former.
162 static const char *g_catch_name = "__cxa_begin_catch";
163 static const char *g_throw_name1 = "__cxa_throw";
164 static const char *g_throw_name2 = "__cxa_rethrow";
165 static const char *g_exception_throw_name = "__cxa_allocate_exception";
166
167 if (catch_bp)
168 names.push_back(g_catch_name);
169
170 if (throw_bp) {
171 names.push_back(g_throw_name1);
172 names.push_back(g_throw_name2);
173 }
174
175 if (for_expressions)
176 names.push_back(g_exception_throw_name);
177}
178
180 FileSpecList &filter_modules, const Target &target) {
181 if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) {
182 // Limit the number of modules that are searched for these breakpoints for
183 // Apple binaries.
184 filter_modules.EmplaceBack("libc++abi.dylib");
185 filter_modules.EmplaceBack("libSystem.B.dylib");
186 filter_modules.EmplaceBack("libc++abi.1.0.dylib");
187 filter_modules.EmplaceBack("libc++abi.1.dylib");
188 }
189}
190
193 if (!thread_sp->SafeToCallFunctions())
194 return {};
195
196 TypeSystemClangSP scratch_ts_sp =
198 if (!scratch_ts_sp)
199 return {};
200
201 CompilerType voidstar =
202 scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
203
204 DiagnosticManager diagnostics;
205 ExecutionContext exe_ctx;
207
208 options.SetUnwindOnError(true);
209 options.SetIgnoreBreakpoints(true);
210 options.SetStopOthers(true);
211 options.SetTimeout(m_process->GetUtilityExpressionTimeout());
212 options.SetTryAllThreads(false);
213 thread_sp->CalculateExecutionContext(exe_ctx);
214
215 const ModuleList &modules = m_process->GetTarget().GetImages();
216 SymbolContextList contexts;
217 SymbolContext context;
218
220 ConstString("__cxa_current_exception_type"), eSymbolTypeCode, contexts);
221 contexts.GetContextAtIndex(0, context);
222 if (!context.symbol) {
223 return {};
224 }
225 Address addr = context.symbol->GetAddress();
226
228 FunctionCaller *function_caller =
229 m_process->GetTarget().GetFunctionCallerForLanguage(
230 eLanguageTypeC, voidstar, addr, ValueList(), "caller", error);
231
232 ExpressionResults func_call_ret;
233 Value results;
234 func_call_ret = function_caller->ExecuteFunction(exe_ctx, nullptr, options,
235 diagnostics, results);
236 if (func_call_ret != eExpressionCompleted || !error.Success()) {
237 return ValueObjectSP();
238 }
239
240 size_t ptr_size = m_process->GetAddressByteSize();
241 addr_t result_ptr = results.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
242 addr_t exception_addr =
243 m_process->ReadPointerFromMemory(result_ptr - ptr_size, error);
244
245 if (!error.Success()) {
246 return ValueObjectSP();
247 }
248
249 lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr,
250 *m_process);
252 "exception", exception_isw.GetAsData(m_process->GetByteOrder()), exe_ctx,
253 voidstar);
254 ValueObjectSP dyn_exception =
255 exception->GetDynamicValue(eDynamicDontRunTarget);
256 // If we succeed in making a dynamic value, return that:
257 if (dyn_exception)
258 return dyn_exception;
259
260 return exception;
261}
static llvm::raw_ostream & error(Stream &strm)
static const char * vtable_demangled_prefix
#define LLDB_LOGF(log,...)
Definition Log.h:389
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition Address.cpp:301
void SetRawAddress(lldb::addr_t addr)
Definition Address.h:441
bool IsSectionOffset() const
Check if an address is section offset.
Definition Address.h:342
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:544
void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info)
lldb::TypeSP LookupTypeByName(llvm::StringRef type_name, lldb::ModuleSP preferred_module, bool &any_found) const
Find a type by its name, preferably in preferred_module.
TypeAndOrName GetDynamicTypeInfo(const lldb_private::Address &vtable_addr)
Generic representation of a type in a programming language.
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
const char * GetCString() const
Get the string value as a C string.
const char * AsCString(const char *value_if_empty) const
Get the string value as a C string.
void SetUnwindOnError(bool unwind=false)
Definition Target.h:400
void SetTryAllThreads(bool try_others=true)
Definition Target.h:433
void SetTimeout(const Timeout< std::micro > &timeout)
Definition Target.h:421
void SetStopOthers(bool stop_others=true)
Definition Target.h:437
void SetIgnoreBreakpoints(bool ignore=false)
Definition Target.h:404
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A file collection class.
void EmplaceBack(Args &&...args)
Inserts a new FileSpec into the FileSpecList constructed in-place with the given arguments.
Encapsulates a function that can be called.
lldb::ExpressionResults ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager, Value &results)
Run the function this FunctionCaller was created with.
void AppendExceptionBreakpointFilterModules(FileSpecList &list, const Target &target) override
llvm::StringRef GetName() const override
lldb::ValueObjectSP GetExceptionObjectForThread(lldb::ThreadSP thread_sp) override
bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, const LanguageRuntime::VTableInfo &vtable_info, TypeAndOrName &class_type_or_name, Address &dynamic_address) override
TypeAndOrName GetTypeInfo(ValueObject &in_value, const LanguageRuntime::VTableInfo &vtable_info)
void AppendExceptionBreakpointFunctions(std::vector< const char * > &names, bool catch_bp, bool throw_bp, bool for_expressions) override
bool IsVTableSymbol(Mangled &manged) const override
A class that handles mangled names.
Definition Mangled.h:34
ConstString GetDemangledName() const
Demangled name get accessor.
Definition Mangled.cpp:284
A collection class for Module objects.
Definition ModuleList.h:125
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
A plug-in interface definition class for debugging a process.
Definition Process.h:359
unsigned long long ULongLong(unsigned long long fail_value=0) const
Definition Scalar.cpp:365
static lldb::TypeSystemClangSP GetForTarget(Target &target, std::optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
An error handling class.
Definition Status.h:118
Defines a list of symbol context objects.
bool GetContextAtIndex(size_t idx, SymbolContext &sc) const
Get accessor for a symbol context at index idx.
Defines a symbol context baton that can be handed other debug core functions.
Symbol * symbol
The Symbol for a given query.
lldb::ModuleSP CalculateSymbolContextModule() override
Definition Symbol.cpp:408
Mangled & GetMangled()
Definition Symbol.h:147
Address GetAddress() const
Definition Symbol.h:89
int64_t ReadSignedIntegerFromMemory(const Address &addr, size_t integer_byte_size, int64_t fail_value, Status &error, bool force_live_memory=false)
Definition Target.cpp:2397
const ArchSpec & GetArchitecture() const
Definition Target.h:1289
Sometimes you can find the name of the type corresponding to an object, but we don't have debug infor...
Definition Type.h:780
void SetName(ConstString type_name)
Definition Type.cpp:911
CompilerType GetCompilerType() const
Definition Type.h:794
void SetTypeSP(lldb::TypeSP type_sp)
Definition Type.cpp:923
static bool AreTypesSame(CompilerType type1, CompilerType type2, bool ignore_qualifiers=false)
virtual ConstString GetTypeName()
CompilerType GetCompilerType()
static lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type, ValueObject *parent=nullptr)
const Scalar & GetScalar() const
See comment on m_scalar to understand what GetScalar returns.
Definition Value.h:114
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
@ eLanguageTypeC
Non-standardized C, such as K&R.
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
std::shared_ptr< lldb_private::Type > TypeSP
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
uint64_t addr_t
Definition lldb-types.h:80
@ eDynamicDontRunTarget
Symbol * symbol
Address of the vtable's virtual function table.
DataExtractor GetAsData(lldb::ByteOrder byte_order=lldb::eByteOrderInvalid) const