1 | //===-- ClangExpressionDeclMap.cpp ----------------------------------------===// |
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 "ClangExpressionDeclMap.h" |
10 | |
11 | #include "ClangASTSource.h" |
12 | #include "ClangExpressionUtil.h" |
13 | #include "ClangExpressionVariable.h" |
14 | #include "ClangModulesDeclVendor.h" |
15 | #include "ClangPersistentVariables.h" |
16 | #include "ClangUtil.h" |
17 | |
18 | #include "NameSearchContext.h" |
19 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
20 | #include "lldb/Core/Address.h" |
21 | #include "lldb/Core/Module.h" |
22 | #include "lldb/Core/ModuleSpec.h" |
23 | #include "lldb/Core/ValueObjectConstResult.h" |
24 | #include "lldb/Core/ValueObjectVariable.h" |
25 | #include "lldb/Expression/DiagnosticManager.h" |
26 | #include "lldb/Expression/Materializer.h" |
27 | #include "lldb/Symbol/CompileUnit.h" |
28 | #include "lldb/Symbol/CompilerDecl.h" |
29 | #include "lldb/Symbol/CompilerDeclContext.h" |
30 | #include "lldb/Symbol/Function.h" |
31 | #include "lldb/Symbol/ObjectFile.h" |
32 | #include "lldb/Symbol/SymbolContext.h" |
33 | #include "lldb/Symbol/SymbolFile.h" |
34 | #include "lldb/Symbol/SymbolVendor.h" |
35 | #include "lldb/Symbol/Type.h" |
36 | #include "lldb/Symbol/TypeList.h" |
37 | #include "lldb/Symbol/Variable.h" |
38 | #include "lldb/Symbol/VariableList.h" |
39 | #include "lldb/Target/ExecutionContext.h" |
40 | #include "lldb/Target/Process.h" |
41 | #include "lldb/Target/RegisterContext.h" |
42 | #include "lldb/Target/StackFrame.h" |
43 | #include "lldb/Target/Target.h" |
44 | #include "lldb/Target/Thread.h" |
45 | #include "lldb/Utility/Endian.h" |
46 | #include "lldb/Utility/LLDBLog.h" |
47 | #include "lldb/Utility/Log.h" |
48 | #include "lldb/Utility/RegisterValue.h" |
49 | #include "lldb/Utility/Status.h" |
50 | #include "lldb/lldb-private-types.h" |
51 | #include "lldb/lldb-private.h" |
52 | #include "clang/AST/ASTConsumer.h" |
53 | #include "clang/AST/ASTContext.h" |
54 | #include "clang/AST/ASTImporter.h" |
55 | #include "clang/AST/Decl.h" |
56 | #include "clang/AST/DeclarationName.h" |
57 | #include "clang/AST/RecursiveASTVisitor.h" |
58 | |
59 | #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" |
60 | #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" |
61 | #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" |
62 | |
63 | using namespace lldb; |
64 | using namespace lldb_private; |
65 | using namespace clang; |
66 | |
67 | static const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars" ; |
68 | |
69 | namespace { |
70 | /// A lambda is represented by Clang as an artifical class whose |
71 | /// members are the lambda captures. If we capture a 'this' pointer, |
72 | /// the artifical class will contain a member variable named 'this'. |
73 | /// The function returns a ValueObject for the captured 'this' if such |
74 | /// member exists. If no 'this' was captured, return a nullptr. |
75 | lldb::ValueObjectSP GetCapturedThisValueObject(StackFrame *frame) { |
76 | assert(frame); |
77 | |
78 | if (auto thisValSP = frame->FindVariable(name: ConstString("this" ))) |
79 | if (auto thisThisValSP = thisValSP->GetChildMemberWithName(name: "this" )) |
80 | return thisThisValSP; |
81 | |
82 | return nullptr; |
83 | } |
84 | } // namespace |
85 | |
86 | ClangExpressionDeclMap::ClangExpressionDeclMap( |
87 | bool keep_result_in_memory, |
88 | Materializer::PersistentVariableDelegate *result_delegate, |
89 | const lldb::TargetSP &target, |
90 | const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj) |
91 | : ClangASTSource(target, importer), m_found_entities(), m_struct_members(), |
92 | m_keep_result_in_memory(keep_result_in_memory), |
93 | m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(), |
94 | m_struct_vars() { |
95 | EnableStructVars(); |
96 | } |
97 | |
98 | ClangExpressionDeclMap::~ClangExpressionDeclMap() { |
99 | // Note: The model is now that the parser's AST context and all associated |
100 | // data does not vanish until the expression has been executed. This means |
101 | // that valuable lookup data (like namespaces) doesn't vanish, but |
102 | |
103 | DidParse(); |
104 | DisableStructVars(); |
105 | } |
106 | |
107 | bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, |
108 | Materializer *materializer) { |
109 | EnableParserVars(); |
110 | m_parser_vars->m_exe_ctx = exe_ctx; |
111 | |
112 | Target *target = exe_ctx.GetTargetPtr(); |
113 | if (exe_ctx.GetFramePtr()) |
114 | m_parser_vars->m_sym_ctx = |
115 | exe_ctx.GetFramePtr()->GetSymbolContext(resolve_scope: lldb::eSymbolContextEverything); |
116 | else if (exe_ctx.GetThreadPtr() && |
117 | exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx: 0)) |
118 | m_parser_vars->m_sym_ctx = |
119 | exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx: 0)->GetSymbolContext( |
120 | resolve_scope: lldb::eSymbolContextEverything); |
121 | else if (exe_ctx.GetProcessPtr()) { |
122 | m_parser_vars->m_sym_ctx.Clear(clear_target: true); |
123 | m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); |
124 | } else if (target) { |
125 | m_parser_vars->m_sym_ctx.Clear(clear_target: true); |
126 | m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); |
127 | } |
128 | |
129 | if (target) { |
130 | m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>( |
131 | Val: target->GetPersistentExpressionStateForLanguage(language: eLanguageTypeC)); |
132 | |
133 | if (!ScratchTypeSystemClang::GetForTarget(target&: *target)) |
134 | return false; |
135 | } |
136 | |
137 | m_parser_vars->m_target_info = GetTargetInfo(); |
138 | m_parser_vars->m_materializer = materializer; |
139 | |
140 | return true; |
141 | } |
142 | |
143 | void ClangExpressionDeclMap::InstallCodeGenerator( |
144 | clang::ASTConsumer *code_gen) { |
145 | assert(m_parser_vars); |
146 | m_parser_vars->m_code_gen = code_gen; |
147 | } |
148 | |
149 | void ClangExpressionDeclMap::InstallDiagnosticManager( |
150 | DiagnosticManager &diag_manager) { |
151 | assert(m_parser_vars); |
152 | m_parser_vars->m_diagnostics = &diag_manager; |
153 | } |
154 | |
155 | void ClangExpressionDeclMap::DidParse() { |
156 | if (m_parser_vars && m_parser_vars->m_persistent_vars) { |
157 | for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); |
158 | entity_index < num_entities; ++entity_index) { |
159 | ExpressionVariableSP var_sp( |
160 | m_found_entities.GetVariableAtIndex(index: entity_index)); |
161 | if (var_sp) |
162 | llvm::cast<ClangExpressionVariable>(Val: var_sp.get()) |
163 | ->DisableParserVars(parser_id: GetParserID()); |
164 | } |
165 | |
166 | for (size_t pvar_index = 0, |
167 | num_pvars = m_parser_vars->m_persistent_vars->GetSize(); |
168 | pvar_index < num_pvars; ++pvar_index) { |
169 | ExpressionVariableSP pvar_sp( |
170 | m_parser_vars->m_persistent_vars->GetVariableAtIndex(index: pvar_index)); |
171 | if (ClangExpressionVariable *clang_var = |
172 | llvm::dyn_cast<ClangExpressionVariable>(Val: pvar_sp.get())) |
173 | clang_var->DisableParserVars(parser_id: GetParserID()); |
174 | } |
175 | |
176 | DisableParserVars(); |
177 | } |
178 | } |
179 | |
180 | // Interface for IRForTarget |
181 | |
182 | ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { |
183 | assert(m_parser_vars.get()); |
184 | |
185 | TargetInfo ret; |
186 | |
187 | ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; |
188 | |
189 | Process *process = exe_ctx.GetProcessPtr(); |
190 | if (process) { |
191 | ret.byte_order = process->GetByteOrder(); |
192 | ret.address_byte_size = process->GetAddressByteSize(); |
193 | } else { |
194 | Target *target = exe_ctx.GetTargetPtr(); |
195 | if (target) { |
196 | ret.byte_order = target->GetArchitecture().GetByteOrder(); |
197 | ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); |
198 | } |
199 | } |
200 | |
201 | return ret; |
202 | } |
203 | |
204 | TypeFromUser ClangExpressionDeclMap::DeportType(TypeSystemClang &target, |
205 | TypeSystemClang &source, |
206 | TypeFromParser parser_type) { |
207 | assert(&target == GetScratchContext(*m_target).get()); |
208 | assert((TypeSystem *)&source == |
209 | parser_type.GetTypeSystem().GetSharedPointer().get()); |
210 | assert(&source.getASTContext() == m_ast_context); |
211 | |
212 | return TypeFromUser(m_ast_importer_sp->DeportType(dst&: target, src_type: parser_type)); |
213 | } |
214 | |
215 | bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, |
216 | ConstString name, |
217 | TypeFromParser parser_type, |
218 | bool is_result, |
219 | bool is_lvalue) { |
220 | assert(m_parser_vars.get()); |
221 | auto ast = parser_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); |
222 | if (ast == nullptr) |
223 | return false; |
224 | |
225 | // Check if we already declared a persistent variable with the same name. |
226 | if (lldb::ExpressionVariableSP conflicting_var = |
227 | m_parser_vars->m_persistent_vars->GetVariable(name)) { |
228 | std::string msg = llvm::formatv(Fmt: "redefinition of persistent variable '{0}'" , |
229 | Vals&: name).str(); |
230 | m_parser_vars->m_diagnostics->AddDiagnostic( |
231 | message: msg, severity: DiagnosticSeverity::eDiagnosticSeverityError, |
232 | origin: DiagnosticOrigin::eDiagnosticOriginLLDB); |
233 | return false; |
234 | } |
235 | |
236 | if (m_parser_vars->m_materializer && is_result) { |
237 | Status err; |
238 | |
239 | ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; |
240 | Target *target = exe_ctx.GetTargetPtr(); |
241 | if (target == nullptr) |
242 | return false; |
243 | |
244 | auto clang_ast_context = GetScratchContext(target&: *target); |
245 | if (!clang_ast_context) |
246 | return false; |
247 | |
248 | TypeFromUser user_type = DeportType(target&: *clang_ast_context, source&: *ast, parser_type); |
249 | |
250 | uint32_t offset = m_parser_vars->m_materializer->AddResultVariable( |
251 | type: user_type, is_lvalue, keep_in_memory: m_keep_result_in_memory, delegate: m_result_delegate, err); |
252 | |
253 | ClangExpressionVariable *var = new ClangExpressionVariable( |
254 | exe_ctx.GetBestExecutionContextScope(), name, user_type, |
255 | m_parser_vars->m_target_info.byte_order, |
256 | m_parser_vars->m_target_info.address_byte_size); |
257 | |
258 | m_found_entities.AddNewlyConstructedVariable(var); |
259 | |
260 | var->EnableParserVars(parser_id: GetParserID()); |
261 | |
262 | ClangExpressionVariable::ParserVars *parser_vars = |
263 | var->GetParserVars(parser_id: GetParserID()); |
264 | |
265 | parser_vars->m_named_decl = decl; |
266 | |
267 | var->EnableJITVars(parser_id: GetParserID()); |
268 | |
269 | ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(parser_id: GetParserID()); |
270 | |
271 | jit_vars->m_offset = offset; |
272 | |
273 | return true; |
274 | } |
275 | |
276 | Log *log = GetLog(mask: LLDBLog::Expressions); |
277 | ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; |
278 | Target *target = exe_ctx.GetTargetPtr(); |
279 | if (target == nullptr) |
280 | return false; |
281 | |
282 | auto context = GetScratchContext(target&: *target); |
283 | if (!context) |
284 | return false; |
285 | |
286 | TypeFromUser user_type = DeportType(target&: *context, source&: *ast, parser_type); |
287 | |
288 | if (!user_type.GetOpaqueQualType()) { |
289 | LLDB_LOG(log, "Persistent variable's type wasn't copied successfully" ); |
290 | return false; |
291 | } |
292 | |
293 | if (!m_parser_vars->m_target_info.IsValid()) |
294 | return false; |
295 | |
296 | if (!m_parser_vars->m_persistent_vars) |
297 | return false; |
298 | |
299 | ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>( |
300 | Val: m_parser_vars->m_persistent_vars |
301 | ->CreatePersistentVariable( |
302 | exe_scope: exe_ctx.GetBestExecutionContextScope(), name, compiler_type: user_type, |
303 | byte_order: m_parser_vars->m_target_info.byte_order, |
304 | addr_byte_size: m_parser_vars->m_target_info.address_byte_size) |
305 | .get()); |
306 | |
307 | if (!var) |
308 | return false; |
309 | |
310 | var->m_frozen_sp->SetHasCompleteType(); |
311 | |
312 | if (is_result) |
313 | var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; |
314 | else |
315 | var->m_flags |= |
316 | ClangExpressionVariable::EVKeepInTarget; // explicitly-declared |
317 | // persistent variables should |
318 | // persist |
319 | |
320 | if (is_lvalue) { |
321 | var->m_flags |= ClangExpressionVariable::EVIsProgramReference; |
322 | } else { |
323 | var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; |
324 | var->m_flags |= ClangExpressionVariable::EVNeedsAllocation; |
325 | } |
326 | |
327 | if (m_keep_result_in_memory) { |
328 | var->m_flags |= ClangExpressionVariable::EVKeepInTarget; |
329 | } |
330 | |
331 | LLDB_LOG(log, "Created persistent variable with flags {0:x}" , var->m_flags); |
332 | |
333 | var->EnableParserVars(parser_id: GetParserID()); |
334 | |
335 | ClangExpressionVariable::ParserVars *parser_vars = |
336 | var->GetParserVars(parser_id: GetParserID()); |
337 | |
338 | parser_vars->m_named_decl = decl; |
339 | |
340 | return true; |
341 | } |
342 | |
343 | bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, |
344 | ConstString name, |
345 | llvm::Value *value, size_t size, |
346 | lldb::offset_t alignment) { |
347 | assert(m_struct_vars.get()); |
348 | assert(m_parser_vars.get()); |
349 | |
350 | bool is_persistent_variable = false; |
351 | |
352 | Log *log = GetLog(mask: LLDBLog::Expressions); |
353 | |
354 | m_struct_vars->m_struct_laid_out = false; |
355 | |
356 | if (ClangExpressionVariable::FindVariableInList(list&: m_struct_members, decl, |
357 | parser_id: GetParserID())) |
358 | return true; |
359 | |
360 | ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList( |
361 | list&: m_found_entities, decl, parser_id: GetParserID())); |
362 | |
363 | if (!var && m_parser_vars->m_persistent_vars) { |
364 | var = ClangExpressionVariable::FindVariableInList( |
365 | list&: *m_parser_vars->m_persistent_vars, decl, parser_id: GetParserID()); |
366 | is_persistent_variable = true; |
367 | } |
368 | |
369 | if (!var) |
370 | return false; |
371 | |
372 | LLDB_LOG(log, "Adding value for (NamedDecl*){0} [{1} - {2}] to the structure" , |
373 | decl, name, var->GetName()); |
374 | |
375 | // We know entity->m_parser_vars is valid because we used a parser variable |
376 | // to find it |
377 | |
378 | ClangExpressionVariable::ParserVars *parser_vars = |
379 | llvm::cast<ClangExpressionVariable>(Val: var)->GetParserVars(parser_id: GetParserID()); |
380 | |
381 | parser_vars->m_llvm_value = value; |
382 | |
383 | if (ClangExpressionVariable::JITVars *jit_vars = |
384 | llvm::cast<ClangExpressionVariable>(Val: var)->GetJITVars(parser_id: GetParserID())) { |
385 | // We already laid this out; do not touch |
386 | |
387 | LLDB_LOG(log, "Already placed at {0:x}" , jit_vars->m_offset); |
388 | } |
389 | |
390 | llvm::cast<ClangExpressionVariable>(Val: var)->EnableJITVars(parser_id: GetParserID()); |
391 | |
392 | ClangExpressionVariable::JITVars *jit_vars = |
393 | llvm::cast<ClangExpressionVariable>(Val: var)->GetJITVars(parser_id: GetParserID()); |
394 | |
395 | jit_vars->m_alignment = alignment; |
396 | jit_vars->m_size = size; |
397 | |
398 | m_struct_members.AddVariable(var_sp: var->shared_from_this()); |
399 | |
400 | if (m_parser_vars->m_materializer) { |
401 | uint32_t offset = 0; |
402 | |
403 | Status err; |
404 | |
405 | if (is_persistent_variable) { |
406 | ExpressionVariableSP var_sp(var->shared_from_this()); |
407 | offset = m_parser_vars->m_materializer->AddPersistentVariable( |
408 | persistent_variable_sp&: var_sp, delegate: nullptr, err); |
409 | } else { |
410 | if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) |
411 | offset = m_parser_vars->m_materializer->AddSymbol(symbol_sp: *sym, err); |
412 | else if (const RegisterInfo *reg_info = var->GetRegisterInfo()) |
413 | offset = m_parser_vars->m_materializer->AddRegister(register_info: *reg_info, err); |
414 | else if (parser_vars->m_lldb_var) |
415 | offset = m_parser_vars->m_materializer->AddVariable( |
416 | variable_sp&: parser_vars->m_lldb_var, err); |
417 | else if (parser_vars->m_lldb_valobj_provider) { |
418 | offset = m_parser_vars->m_materializer->AddValueObject( |
419 | name, valobj_provider: parser_vars->m_lldb_valobj_provider, err); |
420 | } |
421 | } |
422 | |
423 | if (!err.Success()) |
424 | return false; |
425 | |
426 | LLDB_LOG(log, "Placed at {0:x}" , offset); |
427 | |
428 | jit_vars->m_offset = |
429 | offset; // TODO DoStructLayout() should not change this. |
430 | } |
431 | |
432 | return true; |
433 | } |
434 | |
435 | bool ClangExpressionDeclMap::DoStructLayout() { |
436 | assert(m_struct_vars.get()); |
437 | |
438 | if (m_struct_vars->m_struct_laid_out) |
439 | return true; |
440 | |
441 | if (!m_parser_vars->m_materializer) |
442 | return false; |
443 | |
444 | m_struct_vars->m_struct_alignment = |
445 | m_parser_vars->m_materializer->GetStructAlignment(); |
446 | m_struct_vars->m_struct_size = |
447 | m_parser_vars->m_materializer->GetStructByteSize(); |
448 | m_struct_vars->m_struct_laid_out = true; |
449 | return true; |
450 | } |
451 | |
452 | bool ClangExpressionDeclMap::GetStructInfo(uint32_t &num_elements, size_t &size, |
453 | lldb::offset_t &alignment) { |
454 | assert(m_struct_vars.get()); |
455 | |
456 | if (!m_struct_vars->m_struct_laid_out) |
457 | return false; |
458 | |
459 | num_elements = m_struct_members.GetSize(); |
460 | size = m_struct_vars->m_struct_size; |
461 | alignment = m_struct_vars->m_struct_alignment; |
462 | |
463 | return true; |
464 | } |
465 | |
466 | bool ClangExpressionDeclMap::GetStructElement(const NamedDecl *&decl, |
467 | llvm::Value *&value, |
468 | lldb::offset_t &offset, |
469 | ConstString &name, |
470 | uint32_t index) { |
471 | assert(m_struct_vars.get()); |
472 | |
473 | if (!m_struct_vars->m_struct_laid_out) |
474 | return false; |
475 | |
476 | if (index >= m_struct_members.GetSize()) |
477 | return false; |
478 | |
479 | ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); |
480 | |
481 | if (!member_sp) |
482 | return false; |
483 | |
484 | ClangExpressionVariable::ParserVars *parser_vars = |
485 | llvm::cast<ClangExpressionVariable>(Val: member_sp.get()) |
486 | ->GetParserVars(parser_id: GetParserID()); |
487 | ClangExpressionVariable::JITVars *jit_vars = |
488 | llvm::cast<ClangExpressionVariable>(Val: member_sp.get()) |
489 | ->GetJITVars(parser_id: GetParserID()); |
490 | |
491 | if (!parser_vars || !jit_vars || !member_sp->GetValueObject()) |
492 | return false; |
493 | |
494 | decl = parser_vars->m_named_decl; |
495 | value = parser_vars->m_llvm_value; |
496 | offset = jit_vars->m_offset; |
497 | name = member_sp->GetName(); |
498 | |
499 | return true; |
500 | } |
501 | |
502 | bool ClangExpressionDeclMap::GetFunctionInfo(const NamedDecl *decl, |
503 | uint64_t &ptr) { |
504 | ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList( |
505 | list&: m_found_entities, decl, parser_id: GetParserID())); |
506 | |
507 | if (!entity) |
508 | return false; |
509 | |
510 | // We know m_parser_vars is valid since we searched for the variable by its |
511 | // NamedDecl |
512 | |
513 | ClangExpressionVariable::ParserVars *parser_vars = |
514 | entity->GetParserVars(parser_id: GetParserID()); |
515 | |
516 | ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); |
517 | |
518 | return true; |
519 | } |
520 | |
521 | addr_t ClangExpressionDeclMap::GetSymbolAddress(Target &target, |
522 | Process *process, |
523 | ConstString name, |
524 | lldb::SymbolType symbol_type, |
525 | lldb_private::Module *module) { |
526 | SymbolContextList sc_list; |
527 | |
528 | if (module) |
529 | module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); |
530 | else |
531 | target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); |
532 | |
533 | addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; |
534 | |
535 | for (const SymbolContext &sym_ctx : sc_list) { |
536 | if (symbol_load_addr != 0 && symbol_load_addr != LLDB_INVALID_ADDRESS) |
537 | break; |
538 | |
539 | const Address sym_address = sym_ctx.symbol->GetAddress(); |
540 | |
541 | if (!sym_address.IsValid()) |
542 | continue; |
543 | |
544 | switch (sym_ctx.symbol->GetType()) { |
545 | case eSymbolTypeCode: |
546 | case eSymbolTypeTrampoline: |
547 | symbol_load_addr = sym_address.GetCallableLoadAddress(target: &target); |
548 | break; |
549 | |
550 | case eSymbolTypeResolver: |
551 | symbol_load_addr = sym_address.GetCallableLoadAddress(target: &target, is_indirect: true); |
552 | break; |
553 | |
554 | case eSymbolTypeReExported: { |
555 | ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); |
556 | if (reexport_name) { |
557 | ModuleSP reexport_module_sp; |
558 | ModuleSpec reexport_module_spec; |
559 | reexport_module_spec.GetPlatformFileSpec() = |
560 | sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); |
561 | if (reexport_module_spec.GetPlatformFileSpec()) { |
562 | reexport_module_sp = |
563 | target.GetImages().FindFirstModule(module_spec: reexport_module_spec); |
564 | if (!reexport_module_sp) { |
565 | reexport_module_spec.GetPlatformFileSpec().ClearDirectory(); |
566 | reexport_module_sp = |
567 | target.GetImages().FindFirstModule(module_spec: reexport_module_spec); |
568 | } |
569 | } |
570 | symbol_load_addr = GetSymbolAddress( |
571 | target, process, name: sym_ctx.symbol->GetReExportedSymbolName(), |
572 | symbol_type, module: reexport_module_sp.get()); |
573 | } |
574 | } break; |
575 | |
576 | case eSymbolTypeData: |
577 | case eSymbolTypeRuntime: |
578 | case eSymbolTypeVariable: |
579 | case eSymbolTypeLocal: |
580 | case eSymbolTypeParam: |
581 | case eSymbolTypeInvalid: |
582 | case eSymbolTypeAbsolute: |
583 | case eSymbolTypeException: |
584 | case eSymbolTypeSourceFile: |
585 | case eSymbolTypeHeaderFile: |
586 | case eSymbolTypeObjectFile: |
587 | case eSymbolTypeCommonBlock: |
588 | case eSymbolTypeBlock: |
589 | case eSymbolTypeVariableType: |
590 | case eSymbolTypeLineEntry: |
591 | case eSymbolTypeLineHeader: |
592 | case eSymbolTypeScopeBegin: |
593 | case eSymbolTypeScopeEnd: |
594 | case eSymbolTypeAdditional: |
595 | case eSymbolTypeCompiler: |
596 | case eSymbolTypeInstrumentation: |
597 | case eSymbolTypeUndefined: |
598 | case eSymbolTypeObjCClass: |
599 | case eSymbolTypeObjCMetaClass: |
600 | case eSymbolTypeObjCIVar: |
601 | symbol_load_addr = sym_address.GetLoadAddress(target: &target); |
602 | break; |
603 | } |
604 | } |
605 | |
606 | if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) { |
607 | ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(process&: *process); |
608 | |
609 | if (runtime) { |
610 | symbol_load_addr = runtime->LookupRuntimeSymbol(name); |
611 | } |
612 | } |
613 | |
614 | return symbol_load_addr; |
615 | } |
616 | |
617 | addr_t ClangExpressionDeclMap::GetSymbolAddress(ConstString name, |
618 | lldb::SymbolType symbol_type) { |
619 | assert(m_parser_vars.get()); |
620 | |
621 | if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) |
622 | return false; |
623 | |
624 | return GetSymbolAddress(target&: m_parser_vars->m_exe_ctx.GetTargetRef(), |
625 | process: m_parser_vars->m_exe_ctx.GetProcessPtr(), name, |
626 | symbol_type); |
627 | } |
628 | |
629 | lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable( |
630 | Target &target, ModuleSP &module, ConstString name, |
631 | const CompilerDeclContext &namespace_decl) { |
632 | VariableList vars; |
633 | |
634 | if (module && namespace_decl) |
635 | module->FindGlobalVariables(name, parent_decl_ctx: namespace_decl, max_matches: -1, variable_list&: vars); |
636 | else |
637 | target.GetImages().FindGlobalVariables(name, max_matches: -1, variable_list&: vars); |
638 | |
639 | if (vars.GetSize() == 0) |
640 | return VariableSP(); |
641 | return vars.GetVariableAtIndex(idx: 0); |
642 | } |
643 | |
644 | TypeSystemClang *ClangExpressionDeclMap::GetTypeSystemClang() { |
645 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
646 | if (frame == nullptr) |
647 | return nullptr; |
648 | |
649 | SymbolContext sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
650 | lldb::eSymbolContextBlock); |
651 | if (sym_ctx.block == nullptr) |
652 | return nullptr; |
653 | |
654 | CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); |
655 | if (!frame_decl_context) |
656 | return nullptr; |
657 | |
658 | return llvm::dyn_cast_or_null<TypeSystemClang>( |
659 | Val: frame_decl_context.GetTypeSystem()); |
660 | } |
661 | |
662 | // Interface for ClangASTSource |
663 | |
664 | void ClangExpressionDeclMap::FindExternalVisibleDecls( |
665 | NameSearchContext &context) { |
666 | assert(m_ast_context); |
667 | |
668 | const ConstString name(context.m_decl_name.getAsString().c_str()); |
669 | |
670 | Log *log = GetLog(mask: LLDBLog::Expressions); |
671 | |
672 | if (log) { |
673 | if (!context.m_decl_context) |
674 | LLDB_LOG(log, |
675 | "ClangExpressionDeclMap::FindExternalVisibleDecls for " |
676 | "'{0}' in a NULL DeclContext" , |
677 | name); |
678 | else if (const NamedDecl *context_named_decl = |
679 | dyn_cast<NamedDecl>(Val: context.m_decl_context)) |
680 | LLDB_LOG(log, |
681 | "ClangExpressionDeclMap::FindExternalVisibleDecls for " |
682 | "'{0}' in '{1}'" , |
683 | name, context_named_decl->getNameAsString()); |
684 | else |
685 | LLDB_LOG(log, |
686 | "ClangExpressionDeclMap::FindExternalVisibleDecls for " |
687 | "'{0}' in a '{1}'" , |
688 | name, context.m_decl_context->getDeclKindName()); |
689 | } |
690 | |
691 | if (const NamespaceDecl *namespace_context = |
692 | dyn_cast<NamespaceDecl>(Val: context.m_decl_context)) { |
693 | if (namespace_context->getName().str() == |
694 | std::string(g_lldb_local_vars_namespace_cstr)) { |
695 | CompilerDeclContext compiler_decl_ctx = |
696 | m_clang_ast_context->CreateDeclContext( |
697 | ctx: const_cast<clang::DeclContext *>(context.m_decl_context)); |
698 | FindExternalVisibleDecls(context, module: lldb::ModuleSP(), namespace_decl: compiler_decl_ctx); |
699 | return; |
700 | } |
701 | |
702 | ClangASTImporter::NamespaceMapSP namespace_map = |
703 | m_ast_importer_sp->GetNamespaceMap(decl: namespace_context); |
704 | |
705 | if (!namespace_map) |
706 | return; |
707 | |
708 | LLDB_LOGV(log, " CEDM::FEVD Inspecting (NamespaceMap*){0:x} ({1} entries)" , |
709 | namespace_map.get(), namespace_map->size()); |
710 | |
711 | for (ClangASTImporter::NamespaceMapItem &n : *namespace_map) { |
712 | LLDB_LOG(log, " CEDM::FEVD Searching namespace {0} in module {1}" , |
713 | n.second.GetName(), n.first->GetFileSpec().GetFilename()); |
714 | |
715 | FindExternalVisibleDecls(context, module: n.first, namespace_decl: n.second); |
716 | } |
717 | } else if (isa<TranslationUnitDecl>(Val: context.m_decl_context)) { |
718 | CompilerDeclContext namespace_decl; |
719 | |
720 | LLDB_LOG(log, " CEDM::FEVD Searching the root namespace" ); |
721 | |
722 | FindExternalVisibleDecls(context, module: lldb::ModuleSP(), namespace_decl); |
723 | } |
724 | |
725 | ClangASTSource::FindExternalVisibleDecls(context); |
726 | } |
727 | |
728 | void ClangExpressionDeclMap::MaybeRegisterFunctionBody( |
729 | FunctionDecl *copied_function_decl) { |
730 | if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) { |
731 | clang::DeclGroupRef decl_group_ref(copied_function_decl); |
732 | m_parser_vars->m_code_gen->HandleTopLevelDecl(D: decl_group_ref); |
733 | } |
734 | } |
735 | |
736 | clang::NamedDecl *ClangExpressionDeclMap::GetPersistentDecl(ConstString name) { |
737 | if (!m_parser_vars) |
738 | return nullptr; |
739 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
740 | if (!target) |
741 | return nullptr; |
742 | |
743 | ScratchTypeSystemClang::GetForTarget(target&: *target); |
744 | |
745 | if (!m_parser_vars->m_persistent_vars) |
746 | return nullptr; |
747 | return m_parser_vars->m_persistent_vars->GetPersistentDecl(name); |
748 | } |
749 | |
750 | void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context, |
751 | const ConstString name) { |
752 | Log *log = GetLog(mask: LLDBLog::Expressions); |
753 | |
754 | NamedDecl *persistent_decl = GetPersistentDecl(name); |
755 | |
756 | if (!persistent_decl) |
757 | return; |
758 | |
759 | Decl *parser_persistent_decl = CopyDecl(persistent_decl); |
760 | |
761 | if (!parser_persistent_decl) |
762 | return; |
763 | |
764 | NamedDecl *parser_named_decl = dyn_cast<NamedDecl>(Val: parser_persistent_decl); |
765 | |
766 | if (!parser_named_decl) |
767 | return; |
768 | |
769 | if (clang::FunctionDecl *parser_function_decl = |
770 | llvm::dyn_cast<clang::FunctionDecl>(Val: parser_named_decl)) { |
771 | MaybeRegisterFunctionBody(copied_function_decl: parser_function_decl); |
772 | } |
773 | |
774 | LLDB_LOG(log, " CEDM::FEVD Found persistent decl {0}" , name); |
775 | |
776 | context.AddNamedDecl(decl: parser_named_decl); |
777 | } |
778 | |
779 | void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) { |
780 | Log *log = GetLog(mask: LLDBLog::Expressions); |
781 | |
782 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
783 | SymbolContext sym_ctx; |
784 | if (frame != nullptr) |
785 | sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
786 | lldb::eSymbolContextBlock); |
787 | |
788 | if (m_ctx_obj) { |
789 | Status status; |
790 | lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(error&: status); |
791 | if (!ctx_obj_ptr || status.Fail()) |
792 | return; |
793 | |
794 | AddContextClassType(context, type: TypeFromUser(m_ctx_obj->GetCompilerType())); |
795 | return; |
796 | } |
797 | |
798 | // Clang is looking for the type of "this" |
799 | |
800 | if (frame == nullptr) |
801 | return; |
802 | |
803 | // Find the block that defines the function represented by "sym_ctx" |
804 | Block *function_block = sym_ctx.GetFunctionBlock(); |
805 | |
806 | if (!function_block) |
807 | return; |
808 | |
809 | CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); |
810 | |
811 | if (!function_decl_ctx) |
812 | return; |
813 | |
814 | clang::CXXMethodDecl *method_decl = |
815 | TypeSystemClang::DeclContextGetAsCXXMethodDecl(dc: function_decl_ctx); |
816 | |
817 | if (method_decl) { |
818 | if (auto capturedThis = GetCapturedThisValueObject(frame)) { |
819 | // We're inside a lambda and we captured a 'this'. |
820 | // Import the outer class's AST instead of the |
821 | // (unnamed) lambda structure AST so unqualified |
822 | // member lookups are understood by the Clang parser. |
823 | // |
824 | // If we're in a lambda which didn't capture 'this', |
825 | // $__lldb_class will correspond to the lambda closure |
826 | // AST and references to captures will resolve like |
827 | // regular member varaiable accesses do. |
828 | TypeFromUser pointee_type = |
829 | capturedThis->GetCompilerType().GetPointeeType(); |
830 | |
831 | LLDB_LOG(log, |
832 | " CEDM::FEVD Adding captured type ({0} for" |
833 | " $__lldb_class: {1}" , |
834 | capturedThis->GetTypeName(), capturedThis->GetName()); |
835 | |
836 | AddContextClassType(context, type: pointee_type); |
837 | return; |
838 | } |
839 | |
840 | clang::CXXRecordDecl *class_decl = method_decl->getParent(); |
841 | |
842 | QualType class_qual_type(class_decl->getTypeForDecl(), 0); |
843 | |
844 | TypeFromUser class_user_type( |
845 | class_qual_type.getAsOpaquePtr(), |
846 | function_decl_ctx.GetTypeSystem()->weak_from_this()); |
847 | |
848 | LLDB_LOG(log, " CEDM::FEVD Adding type for $__lldb_class: {0}" , |
849 | class_qual_type.getAsString()); |
850 | |
851 | AddContextClassType(context, type: class_user_type); |
852 | return; |
853 | } |
854 | |
855 | // This branch will get hit if we are executing code in the context of |
856 | // a function that claims to have an object pointer (through |
857 | // DW_AT_object_pointer?) but is not formally a method of the class. |
858 | // In that case, just look up the "this" variable in the current scope |
859 | // and use its type. |
860 | // FIXME: This code is formally correct, but clang doesn't currently |
861 | // emit DW_AT_object_pointer |
862 | // for C++ so it hasn't actually been tested. |
863 | |
864 | VariableList *vars = frame->GetVariableList(get_file_globals: false, error_ptr: nullptr); |
865 | |
866 | lldb::VariableSP this_var = vars->FindVariable(name: ConstString("this" )); |
867 | |
868 | if (this_var && this_var->IsInScope(frame) && |
869 | this_var->LocationIsValidForFrame(frame)) { |
870 | Type *this_type = this_var->GetType(); |
871 | |
872 | if (!this_type) |
873 | return; |
874 | |
875 | TypeFromUser pointee_type = |
876 | this_type->GetForwardCompilerType().GetPointeeType(); |
877 | |
878 | LLDB_LOG(log, " FEVD Adding type for $__lldb_class: {0}" , |
879 | ClangUtil::GetQualType(pointee_type).getAsString()); |
880 | |
881 | AddContextClassType(context, type: pointee_type); |
882 | } |
883 | } |
884 | |
885 | void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context) { |
886 | Log *log = GetLog(mask: LLDBLog::Expressions); |
887 | |
888 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
889 | |
890 | if (m_ctx_obj) { |
891 | Status status; |
892 | lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(error&: status); |
893 | if (!ctx_obj_ptr || status.Fail()) |
894 | return; |
895 | |
896 | AddOneType(context, type: TypeFromUser(m_ctx_obj->GetCompilerType())); |
897 | return; |
898 | } |
899 | |
900 | // Clang is looking for the type of "*self" |
901 | |
902 | if (!frame) |
903 | return; |
904 | |
905 | SymbolContext sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
906 | lldb::eSymbolContextBlock); |
907 | |
908 | // Find the block that defines the function represented by "sym_ctx" |
909 | Block *function_block = sym_ctx.GetFunctionBlock(); |
910 | |
911 | if (!function_block) |
912 | return; |
913 | |
914 | CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); |
915 | |
916 | if (!function_decl_ctx) |
917 | return; |
918 | |
919 | clang::ObjCMethodDecl *method_decl = |
920 | TypeSystemClang::DeclContextGetAsObjCMethodDecl(dc: function_decl_ctx); |
921 | |
922 | if (method_decl) { |
923 | ObjCInterfaceDecl *self_interface = method_decl->getClassInterface(); |
924 | |
925 | if (!self_interface) |
926 | return; |
927 | |
928 | const clang::Type *interface_type = self_interface->getTypeForDecl(); |
929 | |
930 | if (!interface_type) |
931 | return; // This is unlikely, but we have seen crashes where this |
932 | // occurred |
933 | |
934 | TypeFromUser class_user_type( |
935 | QualType(interface_type, 0).getAsOpaquePtr(), |
936 | function_decl_ctx.GetTypeSystem()->weak_from_this()); |
937 | |
938 | LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}" , |
939 | ClangUtil::ToString(interface_type)); |
940 | |
941 | AddOneType(context, type: class_user_type); |
942 | return; |
943 | } |
944 | // This branch will get hit if we are executing code in the context of |
945 | // a function that claims to have an object pointer (through |
946 | // DW_AT_object_pointer?) but is not formally a method of the class. |
947 | // In that case, just look up the "self" variable in the current scope |
948 | // and use its type. |
949 | |
950 | VariableList *vars = frame->GetVariableList(get_file_globals: false, error_ptr: nullptr); |
951 | |
952 | lldb::VariableSP self_var = vars->FindVariable(name: ConstString("self" )); |
953 | |
954 | if (!self_var) |
955 | return; |
956 | if (!self_var->IsInScope(frame)) |
957 | return; |
958 | if (!self_var->LocationIsValidForFrame(frame)) |
959 | return; |
960 | |
961 | Type *self_type = self_var->GetType(); |
962 | |
963 | if (!self_type) |
964 | return; |
965 | |
966 | CompilerType self_clang_type = self_type->GetFullCompilerType(); |
967 | |
968 | if (TypeSystemClang::IsObjCClassType(type: self_clang_type)) { |
969 | return; |
970 | } |
971 | if (!TypeSystemClang::IsObjCObjectPointerType(type: self_clang_type)) |
972 | return; |
973 | self_clang_type = self_clang_type.GetPointeeType(); |
974 | |
975 | if (!self_clang_type) |
976 | return; |
977 | |
978 | LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}" , |
979 | ClangUtil::ToString(self_type->GetFullCompilerType())); |
980 | |
981 | TypeFromUser class_user_type(self_clang_type); |
982 | |
983 | AddOneType(context, type: class_user_type); |
984 | } |
985 | |
986 | void ClangExpressionDeclMap::LookupLocalVarNamespace( |
987 | SymbolContext &sym_ctx, NameSearchContext &name_context) { |
988 | if (sym_ctx.block == nullptr) |
989 | return; |
990 | |
991 | CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); |
992 | if (!frame_decl_context) |
993 | return; |
994 | |
995 | TypeSystemClang *frame_ast = llvm::dyn_cast_or_null<TypeSystemClang>( |
996 | Val: frame_decl_context.GetTypeSystem()); |
997 | if (!frame_ast) |
998 | return; |
999 | |
1000 | clang::NamespaceDecl *namespace_decl = |
1001 | m_clang_ast_context->GetUniqueNamespaceDeclaration( |
1002 | name: g_lldb_local_vars_namespace_cstr, decl_ctx: nullptr, owning_module: OptionalClangModuleID()); |
1003 | if (!namespace_decl) |
1004 | return; |
1005 | |
1006 | name_context.AddNamedDecl(namespace_decl); |
1007 | clang::DeclContext *ctxt = clang::Decl::castToDeclContext(namespace_decl); |
1008 | ctxt->setHasExternalVisibleStorage(true); |
1009 | name_context.m_found_local_vars_nsp = true; |
1010 | } |
1011 | |
1012 | void ClangExpressionDeclMap::LookupInModulesDeclVendor( |
1013 | NameSearchContext &context, ConstString name) { |
1014 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1015 | |
1016 | if (!m_target) |
1017 | return; |
1018 | |
1019 | std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor = |
1020 | GetClangModulesDeclVendor(); |
1021 | if (!modules_decl_vendor) |
1022 | return; |
1023 | |
1024 | bool append = false; |
1025 | uint32_t max_matches = 1; |
1026 | std::vector<clang::NamedDecl *> decls; |
1027 | |
1028 | if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls)) |
1029 | return; |
1030 | |
1031 | assert(!decls.empty() && "FindDecls returned true but no decls?" ); |
1032 | clang::NamedDecl *const decl_from_modules = decls[0]; |
1033 | |
1034 | LLDB_LOG(log, |
1035 | " CAS::FEVD Matching decl found for " |
1036 | "\"{0}\" in the modules" , |
1037 | name); |
1038 | |
1039 | clang::Decl *copied_decl = CopyDecl(decl_from_modules); |
1040 | if (!copied_decl) { |
1041 | LLDB_LOG(log, " CAS::FEVD - Couldn't export a " |
1042 | "declaration from the modules" ); |
1043 | return; |
1044 | } |
1045 | |
1046 | if (auto copied_function = dyn_cast<clang::FunctionDecl>(copied_decl)) { |
1047 | MaybeRegisterFunctionBody(copied_function_decl: copied_function); |
1048 | |
1049 | context.AddNamedDecl(decl: copied_function); |
1050 | |
1051 | context.m_found_function_with_type_info = true; |
1052 | } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) { |
1053 | context.AddNamedDecl(decl: copied_var); |
1054 | context.m_found_variable = true; |
1055 | } |
1056 | } |
1057 | |
1058 | bool ClangExpressionDeclMap::LookupLocalVariable( |
1059 | NameSearchContext &context, ConstString name, SymbolContext &sym_ctx, |
1060 | const CompilerDeclContext &namespace_decl) { |
1061 | if (sym_ctx.block == nullptr) |
1062 | return false; |
1063 | |
1064 | CompilerDeclContext decl_context = sym_ctx.block->GetDeclContext(); |
1065 | if (!decl_context) |
1066 | return false; |
1067 | |
1068 | // Make sure that the variables are parsed so that we have the |
1069 | // declarations. |
1070 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
1071 | VariableListSP vars = frame->GetInScopeVariableList(get_file_globals: true); |
1072 | for (size_t i = 0; i < vars->GetSize(); i++) |
1073 | vars->GetVariableAtIndex(idx: i)->GetDecl(); |
1074 | |
1075 | // Search for declarations matching the name. Do not include imported |
1076 | // decls in the search if we are looking for decls in the artificial |
1077 | // namespace $__lldb_local_vars. |
1078 | std::vector<CompilerDecl> found_decls = |
1079 | decl_context.FindDeclByName(name, ignore_using_decls: namespace_decl.IsValid()); |
1080 | |
1081 | VariableSP var; |
1082 | bool variable_found = false; |
1083 | for (CompilerDecl decl : found_decls) { |
1084 | for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) { |
1085 | VariableSP candidate_var = vars->GetVariableAtIndex(idx: vi); |
1086 | if (candidate_var->GetDecl() == decl) { |
1087 | var = candidate_var; |
1088 | break; |
1089 | } |
1090 | } |
1091 | |
1092 | if (var && !variable_found) { |
1093 | variable_found = true; |
1094 | ValueObjectSP valobj = ValueObjectVariable::Create(exe_scope: frame, var_sp: var); |
1095 | AddOneVariable(context, var, valobj); |
1096 | context.m_found_variable = true; |
1097 | } |
1098 | } |
1099 | |
1100 | // We're in a local_var_lookup but haven't found any local variables |
1101 | // so far. When performing a variable lookup from within the context of |
1102 | // a lambda, we count the lambda captures as local variables. Thus, |
1103 | // see if we captured any variables with the requested 'name'. |
1104 | if (!variable_found) { |
1105 | auto find_capture = [](ConstString varname, |
1106 | StackFrame *frame) -> ValueObjectSP { |
1107 | if (auto lambda = ClangExpressionUtil::GetLambdaValueObject(frame)) { |
1108 | if (auto capture = lambda->GetChildMemberWithName(name: varname)) { |
1109 | return capture; |
1110 | } |
1111 | } |
1112 | |
1113 | return nullptr; |
1114 | }; |
1115 | |
1116 | if (auto capture = find_capture(name, frame)) { |
1117 | variable_found = true; |
1118 | context.m_found_variable = true; |
1119 | AddOneVariable(context, valobj: std::move(capture), valobj_provider: std::move(find_capture)); |
1120 | } |
1121 | } |
1122 | |
1123 | return variable_found; |
1124 | } |
1125 | |
1126 | /// Structure to hold the info needed when comparing function |
1127 | /// declarations. |
1128 | namespace { |
1129 | struct FuncDeclInfo { |
1130 | ConstString m_name; |
1131 | CompilerType m_copied_type; |
1132 | uint32_t m_decl_lvl; |
1133 | SymbolContext m_sym_ctx; |
1134 | }; |
1135 | } // namespace |
1136 | |
1137 | SymbolContextList ClangExpressionDeclMap::SearchFunctionsInSymbolContexts( |
1138 | const SymbolContextList &sc_list, |
1139 | const CompilerDeclContext &frame_decl_context) { |
1140 | // First, symplify things by looping through the symbol contexts to |
1141 | // remove unwanted functions and separate out the functions we want to |
1142 | // compare and prune into a separate list. Cache the info needed about |
1143 | // the function declarations in a vector for efficiency. |
1144 | SymbolContextList sc_sym_list; |
1145 | std::vector<FuncDeclInfo> decl_infos; |
1146 | decl_infos.reserve(n: sc_list.GetSize()); |
1147 | clang::DeclContext *frame_decl_ctx = |
1148 | (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); |
1149 | TypeSystemClang *ast = llvm::dyn_cast_or_null<TypeSystemClang>( |
1150 | Val: frame_decl_context.GetTypeSystem()); |
1151 | |
1152 | for (const SymbolContext &sym_ctx : sc_list) { |
1153 | FuncDeclInfo fdi; |
1154 | |
1155 | // We don't know enough about symbols to compare them, but we should |
1156 | // keep them in the list. |
1157 | Function *function = sym_ctx.function; |
1158 | if (!function) { |
1159 | sc_sym_list.Append(sc: sym_ctx); |
1160 | continue; |
1161 | } |
1162 | // Filter out functions without declaration contexts, as well as |
1163 | // class/instance methods, since they'll be skipped in the code that |
1164 | // follows anyway. |
1165 | CompilerDeclContext func_decl_context = function->GetDeclContext(); |
1166 | if (!func_decl_context || func_decl_context.IsClassMethod()) |
1167 | continue; |
1168 | // We can only prune functions for which we can copy the type. |
1169 | CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); |
1170 | CompilerType copied_func_type = GuardedCopyType(src_type: func_clang_type); |
1171 | if (!copied_func_type) { |
1172 | sc_sym_list.Append(sc: sym_ctx); |
1173 | continue; |
1174 | } |
1175 | |
1176 | fdi.m_sym_ctx = sym_ctx; |
1177 | fdi.m_name = function->GetName(); |
1178 | fdi.m_copied_type = copied_func_type; |
1179 | fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; |
1180 | if (fdi.m_copied_type && func_decl_context) { |
1181 | // Call CountDeclLevels to get the number of parent scopes we have |
1182 | // to look through before we find the function declaration. When |
1183 | // comparing functions of the same type, the one with a lower count |
1184 | // will be closer to us in the lookup scope and shadows the other. |
1185 | clang::DeclContext *func_decl_ctx = |
1186 | (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); |
1187 | fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, child_decl_ctx: func_decl_ctx, |
1188 | child_name: &fdi.m_name, child_type: &fdi.m_copied_type); |
1189 | } |
1190 | decl_infos.emplace_back(args&: fdi); |
1191 | } |
1192 | |
1193 | // Loop through the functions in our cache looking for matching types, |
1194 | // then compare their scope levels to see which is closer. |
1195 | std::multimap<CompilerType, const FuncDeclInfo *> matches; |
1196 | for (const FuncDeclInfo &fdi : decl_infos) { |
1197 | const CompilerType t = fdi.m_copied_type; |
1198 | auto q = matches.find(x: t); |
1199 | if (q != matches.end()) { |
1200 | if (q->second->m_decl_lvl > fdi.m_decl_lvl) |
1201 | // This function is closer; remove the old set. |
1202 | matches.erase(x: t); |
1203 | else if (q->second->m_decl_lvl < fdi.m_decl_lvl) |
1204 | // The functions in our set are closer - skip this one. |
1205 | continue; |
1206 | } |
1207 | matches.insert(x: std::make_pair(x: t, y: &fdi)); |
1208 | } |
1209 | |
1210 | // Loop through our matches and add their symbol contexts to our list. |
1211 | SymbolContextList sc_func_list; |
1212 | for (const auto &q : matches) |
1213 | sc_func_list.Append(sc: q.second->m_sym_ctx); |
1214 | |
1215 | // Rejoin the lists with the functions in front. |
1216 | sc_func_list.Append(sc_list: sc_sym_list); |
1217 | return sc_func_list; |
1218 | } |
1219 | |
1220 | void ClangExpressionDeclMap::LookupFunction( |
1221 | NameSearchContext &context, lldb::ModuleSP module_sp, ConstString name, |
1222 | const CompilerDeclContext &namespace_decl) { |
1223 | if (!m_parser_vars) |
1224 | return; |
1225 | |
1226 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1227 | |
1228 | std::vector<clang::NamedDecl *> decls_from_modules; |
1229 | |
1230 | if (target) { |
1231 | if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor = |
1232 | GetClangModulesDeclVendor()) { |
1233 | decl_vendor->FindDecls(name, append: false, UINT32_MAX, decls&: decls_from_modules); |
1234 | } |
1235 | } |
1236 | |
1237 | SymbolContextList sc_list; |
1238 | if (namespace_decl && module_sp) { |
1239 | ModuleFunctionSearchOptions function_options; |
1240 | function_options.include_inlines = false; |
1241 | function_options.include_symbols = false; |
1242 | |
1243 | module_sp->FindFunctions(name, parent_decl_ctx: namespace_decl, name_type_mask: eFunctionNameTypeBase, |
1244 | options: function_options, sc_list); |
1245 | } else if (target && !namespace_decl) { |
1246 | ModuleFunctionSearchOptions function_options; |
1247 | function_options.include_inlines = false; |
1248 | function_options.include_symbols = true; |
1249 | |
1250 | // TODO Fix FindFunctions so that it doesn't return |
1251 | // instance methods for eFunctionNameTypeBase. |
1252 | |
1253 | target->GetImages().FindFunctions( |
1254 | name, name_type_mask: eFunctionNameTypeFull | eFunctionNameTypeBase, options: function_options, |
1255 | sc_list); |
1256 | } |
1257 | |
1258 | // If we found more than one function, see if we can use the frame's decl |
1259 | // context to remove functions that are shadowed by other functions which |
1260 | // match in type but are nearer in scope. |
1261 | // |
1262 | // AddOneFunction will not add a function whose type has already been |
1263 | // added, so if there's another function in the list with a matching type, |
1264 | // check to see if their decl context is a parent of the current frame's or |
1265 | // was imported via a and using statement, and pick the best match |
1266 | // according to lookup rules. |
1267 | if (sc_list.GetSize() > 1) { |
1268 | // Collect some info about our frame's context. |
1269 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
1270 | SymbolContext frame_sym_ctx; |
1271 | if (frame != nullptr) |
1272 | frame_sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
1273 | lldb::eSymbolContextBlock); |
1274 | CompilerDeclContext frame_decl_context = |
1275 | frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() |
1276 | : CompilerDeclContext(); |
1277 | |
1278 | // We can't do this without a compiler decl context for our frame. |
1279 | if (frame_decl_context) { |
1280 | sc_list = SearchFunctionsInSymbolContexts(sc_list, frame_decl_context); |
1281 | } |
1282 | } |
1283 | |
1284 | if (sc_list.GetSize()) { |
1285 | Symbol *extern_symbol = nullptr; |
1286 | Symbol *non_extern_symbol = nullptr; |
1287 | |
1288 | for (const SymbolContext &sym_ctx : sc_list) { |
1289 | if (sym_ctx.function) { |
1290 | CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); |
1291 | |
1292 | if (!decl_ctx) |
1293 | continue; |
1294 | |
1295 | // Filter out class/instance methods. |
1296 | if (decl_ctx.IsClassMethod()) |
1297 | continue; |
1298 | |
1299 | AddOneFunction(context, fun: sym_ctx.function, sym: nullptr); |
1300 | context.m_found_function_with_type_info = true; |
1301 | } else if (sym_ctx.symbol) { |
1302 | Symbol *symbol = sym_ctx.symbol; |
1303 | if (target && symbol->GetType() == eSymbolTypeReExported) { |
1304 | symbol = symbol->ResolveReExportedSymbol(target&: *target); |
1305 | if (symbol == nullptr) |
1306 | continue; |
1307 | } |
1308 | |
1309 | if (symbol->IsExternal()) |
1310 | extern_symbol = symbol; |
1311 | else |
1312 | non_extern_symbol = symbol; |
1313 | } |
1314 | } |
1315 | |
1316 | if (!context.m_found_function_with_type_info) { |
1317 | for (clang::NamedDecl *decl : decls_from_modules) { |
1318 | if (llvm::isa<clang::FunctionDecl>(Val: decl)) { |
1319 | clang::NamedDecl *copied_decl = |
1320 | llvm::cast_or_null<FunctionDecl>(Val: CopyDecl(decl)); |
1321 | if (copied_decl) { |
1322 | context.AddNamedDecl(decl: copied_decl); |
1323 | context.m_found_function_with_type_info = true; |
1324 | } |
1325 | } |
1326 | } |
1327 | } |
1328 | |
1329 | if (!context.m_found_function_with_type_info) { |
1330 | if (extern_symbol) { |
1331 | AddOneFunction(context, fun: nullptr, sym: extern_symbol); |
1332 | } else if (non_extern_symbol) { |
1333 | AddOneFunction(context, fun: nullptr, sym: non_extern_symbol); |
1334 | } |
1335 | } |
1336 | } |
1337 | } |
1338 | |
1339 | void ClangExpressionDeclMap::FindExternalVisibleDecls( |
1340 | NameSearchContext &context, lldb::ModuleSP module_sp, |
1341 | const CompilerDeclContext &namespace_decl) { |
1342 | assert(m_ast_context); |
1343 | |
1344 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1345 | |
1346 | const ConstString name(context.m_decl_name.getAsString().c_str()); |
1347 | if (IgnoreName(name, ignore_all_dollar_names: false)) |
1348 | return; |
1349 | |
1350 | // Only look for functions by name out in our symbols if the function doesn't |
1351 | // start with our phony prefix of '$' |
1352 | |
1353 | Target *target = nullptr; |
1354 | StackFrame *frame = nullptr; |
1355 | SymbolContext sym_ctx; |
1356 | if (m_parser_vars) { |
1357 | target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1358 | frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
1359 | } |
1360 | if (frame != nullptr) |
1361 | sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
1362 | lldb::eSymbolContextBlock); |
1363 | |
1364 | // Try the persistent decls, which take precedence over all else. |
1365 | if (!namespace_decl) |
1366 | SearchPersistenDecls(context, name); |
1367 | |
1368 | if (name.GetStringRef().starts_with(Prefix: "$" ) && !namespace_decl) { |
1369 | if (name == "$__lldb_class" ) { |
1370 | LookUpLldbClass(context); |
1371 | return; |
1372 | } |
1373 | |
1374 | if (name == "$__lldb_objc_class" ) { |
1375 | LookUpLldbObjCClass(context); |
1376 | return; |
1377 | } |
1378 | if (name == g_lldb_local_vars_namespace_cstr) { |
1379 | LookupLocalVarNamespace(sym_ctx, name_context&: context); |
1380 | return; |
1381 | } |
1382 | |
1383 | // any other $__lldb names should be weeded out now |
1384 | if (name.GetStringRef().starts_with(Prefix: "$__lldb" )) |
1385 | return; |
1386 | |
1387 | // No ParserVars means we can't do register or variable lookup. |
1388 | if (!m_parser_vars || !m_parser_vars->m_persistent_vars) |
1389 | return; |
1390 | |
1391 | ExpressionVariableSP pvar_sp( |
1392 | m_parser_vars->m_persistent_vars->GetVariable(name)); |
1393 | |
1394 | if (pvar_sp) { |
1395 | AddOneVariable(context, pvar_sp); |
1396 | return; |
1397 | } |
1398 | |
1399 | assert(name.GetStringRef().starts_with("$" )); |
1400 | llvm::StringRef reg_name = name.GetStringRef().substr(Start: 1); |
1401 | |
1402 | if (m_parser_vars->m_exe_ctx.GetRegisterContext()) { |
1403 | const RegisterInfo *reg_info( |
1404 | m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName( |
1405 | reg_name)); |
1406 | |
1407 | if (reg_info) { |
1408 | LLDB_LOG(log, " CEDM::FEVD Found register {0}" , reg_info->name); |
1409 | |
1410 | AddOneRegister(context, reg_info); |
1411 | } |
1412 | } |
1413 | return; |
1414 | } |
1415 | |
1416 | bool local_var_lookup = !namespace_decl || (namespace_decl.GetName() == |
1417 | g_lldb_local_vars_namespace_cstr); |
1418 | if (frame && local_var_lookup) |
1419 | if (LookupLocalVariable(context, name, sym_ctx, namespace_decl)) |
1420 | return; |
1421 | |
1422 | if (target) { |
1423 | ValueObjectSP valobj; |
1424 | VariableSP var; |
1425 | var = FindGlobalVariable(target&: *target, module&: module_sp, name, namespace_decl); |
1426 | |
1427 | if (var) { |
1428 | valobj = ValueObjectVariable::Create(exe_scope: target, var_sp: var); |
1429 | AddOneVariable(context, var, valobj); |
1430 | context.m_found_variable = true; |
1431 | return; |
1432 | } |
1433 | } |
1434 | |
1435 | LookupFunction(context, module_sp, name, namespace_decl); |
1436 | |
1437 | // Try the modules next. |
1438 | if (!context.m_found_function_with_type_info) |
1439 | LookupInModulesDeclVendor(context, name); |
1440 | |
1441 | if (target && !context.m_found_variable && !namespace_decl) { |
1442 | // We couldn't find a non-symbol variable for this. Now we'll hunt for a |
1443 | // generic data symbol, and -- if it is found -- treat it as a variable. |
1444 | Status error; |
1445 | |
1446 | const Symbol *data_symbol = |
1447 | m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error); |
1448 | |
1449 | if (!error.Success()) { |
1450 | const unsigned diag_id = |
1451 | m_ast_context->getDiagnostics().getCustomDiagID( |
1452 | L: clang::DiagnosticsEngine::Level::Error, FormatString: "%0" ); |
1453 | m_ast_context->getDiagnostics().Report(DiagID: diag_id) << error.AsCString(); |
1454 | } |
1455 | |
1456 | if (data_symbol) { |
1457 | std::string warning("got name from symbols: " ); |
1458 | warning.append(s: name.AsCString()); |
1459 | const unsigned diag_id = |
1460 | m_ast_context->getDiagnostics().getCustomDiagID( |
1461 | L: clang::DiagnosticsEngine::Level::Warning, FormatString: "%0" ); |
1462 | m_ast_context->getDiagnostics().Report(DiagID: diag_id) << warning.c_str(); |
1463 | AddOneGenericVariable(context, symbol: *data_symbol); |
1464 | context.m_found_variable = true; |
1465 | } |
1466 | } |
1467 | } |
1468 | |
1469 | bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, |
1470 | lldb_private::Value &var_location, |
1471 | TypeFromUser *user_type, |
1472 | TypeFromParser *parser_type) { |
1473 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1474 | |
1475 | Type *var_type = var->GetType(); |
1476 | |
1477 | if (!var_type) { |
1478 | LLDB_LOG(log, "Skipped a definition because it has no type" ); |
1479 | return false; |
1480 | } |
1481 | |
1482 | CompilerType var_clang_type = var_type->GetFullCompilerType(); |
1483 | |
1484 | if (!var_clang_type) { |
1485 | LLDB_LOG(log, "Skipped a definition because it has no Clang type" ); |
1486 | return false; |
1487 | } |
1488 | |
1489 | auto ts = var_type->GetForwardCompilerType().GetTypeSystem(); |
1490 | auto clang_ast = ts.dyn_cast_or_null<TypeSystemClang>(); |
1491 | |
1492 | if (!clang_ast) { |
1493 | LLDB_LOG(log, "Skipped a definition because it has no Clang AST" ); |
1494 | return false; |
1495 | } |
1496 | |
1497 | DWARFExpressionList &var_location_list = var->LocationExpressionList(); |
1498 | |
1499 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1500 | Status err; |
1501 | |
1502 | if (var->GetLocationIsConstantValueData()) { |
1503 | DataExtractor ; |
1504 | if (var_location_list.GetExpressionData(data&: const_value_extractor)) { |
1505 | var_location = Value(const_value_extractor.GetDataStart(), |
1506 | const_value_extractor.GetByteSize()); |
1507 | var_location.SetValueType(Value::ValueType::HostAddress); |
1508 | } else { |
1509 | LLDB_LOG(log, "Error evaluating constant variable: {0}" , err.AsCString()); |
1510 | return false; |
1511 | } |
1512 | } |
1513 | |
1514 | CompilerType type_to_use = GuardedCopyType(src_type: var_clang_type); |
1515 | |
1516 | if (!type_to_use) { |
1517 | LLDB_LOG(log, |
1518 | "Couldn't copy a variable's type into the parser's AST context" ); |
1519 | |
1520 | return false; |
1521 | } |
1522 | |
1523 | if (parser_type) |
1524 | *parser_type = TypeFromParser(type_to_use); |
1525 | |
1526 | if (var_location.GetContextType() == Value::ContextType::Invalid) |
1527 | var_location.SetCompilerType(type_to_use); |
1528 | |
1529 | if (var_location.GetValueType() == Value::ValueType::FileAddress) { |
1530 | SymbolContext var_sc; |
1531 | var->CalculateSymbolContext(sc: &var_sc); |
1532 | |
1533 | if (!var_sc.module_sp) |
1534 | return false; |
1535 | |
1536 | Address so_addr(var_location.GetScalar().ULongLong(), |
1537 | var_sc.module_sp->GetSectionList()); |
1538 | |
1539 | lldb::addr_t load_addr = so_addr.GetLoadAddress(target); |
1540 | |
1541 | if (load_addr != LLDB_INVALID_ADDRESS) { |
1542 | var_location.GetScalar() = load_addr; |
1543 | var_location.SetValueType(Value::ValueType::LoadAddress); |
1544 | } |
1545 | } |
1546 | |
1547 | if (user_type) |
1548 | *user_type = TypeFromUser(var_clang_type); |
1549 | |
1550 | return true; |
1551 | } |
1552 | |
1553 | ClangExpressionVariable::ParserVars * |
1554 | ClangExpressionDeclMap::AddExpressionVariable(NameSearchContext &context, |
1555 | TypeFromParser const &pt, |
1556 | ValueObjectSP valobj) { |
1557 | clang::QualType parser_opaque_type = |
1558 | QualType::getFromOpaquePtr(Ptr: pt.GetOpaqueQualType()); |
1559 | |
1560 | if (parser_opaque_type.isNull()) |
1561 | return nullptr; |
1562 | |
1563 | if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) { |
1564 | if (const TagType *tag_type = dyn_cast<TagType>(Val: parser_type)) |
1565 | CompleteType(Tag: tag_type->getDecl()); |
1566 | if (const ObjCObjectPointerType *objc_object_ptr_type = |
1567 | dyn_cast<ObjCObjectPointerType>(Val: parser_type)) |
1568 | CompleteType(Class: objc_object_ptr_type->getInterfaceDecl()); |
1569 | } |
1570 | |
1571 | bool is_reference = pt.IsReferenceType(); |
1572 | |
1573 | NamedDecl *var_decl = nullptr; |
1574 | if (is_reference) |
1575 | var_decl = context.AddVarDecl(type: pt); |
1576 | else |
1577 | var_decl = context.AddVarDecl(type: pt.GetLValueReferenceType()); |
1578 | |
1579 | std::string decl_name(context.m_decl_name.getAsString()); |
1580 | ConstString entity_name(decl_name.c_str()); |
1581 | ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); |
1582 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1583 | |
1584 | assert(entity); |
1585 | entity->EnableParserVars(parser_id: GetParserID()); |
1586 | ClangExpressionVariable::ParserVars *parser_vars = |
1587 | entity->GetParserVars(parser_id: GetParserID()); |
1588 | |
1589 | parser_vars->m_named_decl = var_decl; |
1590 | |
1591 | if (is_reference) |
1592 | entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; |
1593 | |
1594 | return parser_vars; |
1595 | } |
1596 | |
1597 | void ClangExpressionDeclMap::AddOneVariable( |
1598 | NameSearchContext &context, ValueObjectSP valobj, |
1599 | ValueObjectProviderTy valobj_provider) { |
1600 | assert(m_parser_vars.get()); |
1601 | assert(valobj); |
1602 | |
1603 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1604 | |
1605 | Value var_location = valobj->GetValue(); |
1606 | |
1607 | TypeFromUser user_type = valobj->GetCompilerType(); |
1608 | |
1609 | auto clang_ast = |
1610 | user_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); |
1611 | |
1612 | if (!clang_ast) { |
1613 | LLDB_LOG(log, "Skipped a definition because it has no Clang AST" ); |
1614 | return; |
1615 | } |
1616 | |
1617 | TypeFromParser parser_type = GuardedCopyType(src_type: user_type); |
1618 | |
1619 | if (!parser_type) { |
1620 | LLDB_LOG(log, |
1621 | "Couldn't copy a variable's type into the parser's AST context" ); |
1622 | |
1623 | return; |
1624 | } |
1625 | |
1626 | if (var_location.GetContextType() == Value::ContextType::Invalid) |
1627 | var_location.SetCompilerType(parser_type); |
1628 | |
1629 | ClangExpressionVariable::ParserVars *parser_vars = |
1630 | AddExpressionVariable(context, pt: parser_type, valobj); |
1631 | |
1632 | if (!parser_vars) |
1633 | return; |
1634 | |
1635 | LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})" , |
1636 | context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), |
1637 | ClangUtil::ToString(user_type)); |
1638 | |
1639 | parser_vars->m_llvm_value = nullptr; |
1640 | parser_vars->m_lldb_value = std::move(var_location); |
1641 | parser_vars->m_lldb_valobj_provider = std::move(valobj_provider); |
1642 | } |
1643 | |
1644 | void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, |
1645 | VariableSP var, |
1646 | ValueObjectSP valobj) { |
1647 | assert(m_parser_vars.get()); |
1648 | |
1649 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1650 | |
1651 | TypeFromUser ut; |
1652 | TypeFromParser pt; |
1653 | Value var_location; |
1654 | |
1655 | if (!GetVariableValue(var, var_location, user_type: &ut, parser_type: &pt)) |
1656 | return; |
1657 | |
1658 | ClangExpressionVariable::ParserVars *parser_vars = |
1659 | AddExpressionVariable(context, pt, valobj: std::move(valobj)); |
1660 | |
1661 | if (!parser_vars) |
1662 | return; |
1663 | |
1664 | LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})" , |
1665 | context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), |
1666 | ClangUtil::ToString(ut)); |
1667 | |
1668 | parser_vars->m_llvm_value = nullptr; |
1669 | parser_vars->m_lldb_value = var_location; |
1670 | parser_vars->m_lldb_var = var; |
1671 | } |
1672 | |
1673 | void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, |
1674 | ExpressionVariableSP &pvar_sp) { |
1675 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1676 | |
1677 | TypeFromUser user_type( |
1678 | llvm::cast<ClangExpressionVariable>(Val: pvar_sp.get())->GetTypeFromUser()); |
1679 | |
1680 | TypeFromParser parser_type(GuardedCopyType(src_type: user_type)); |
1681 | |
1682 | if (!parser_type.GetOpaqueQualType()) { |
1683 | LLDB_LOG(log, " CEDM::FEVD Couldn't import type for pvar {0}" , |
1684 | pvar_sp->GetName()); |
1685 | return; |
1686 | } |
1687 | |
1688 | NamedDecl *var_decl = |
1689 | context.AddVarDecl(type: parser_type.GetLValueReferenceType()); |
1690 | |
1691 | llvm::cast<ClangExpressionVariable>(Val: pvar_sp.get()) |
1692 | ->EnableParserVars(parser_id: GetParserID()); |
1693 | ClangExpressionVariable::ParserVars *parser_vars = |
1694 | llvm::cast<ClangExpressionVariable>(Val: pvar_sp.get()) |
1695 | ->GetParserVars(parser_id: GetParserID()); |
1696 | parser_vars->m_named_decl = var_decl; |
1697 | parser_vars->m_llvm_value = nullptr; |
1698 | parser_vars->m_lldb_value.Clear(); |
1699 | |
1700 | LLDB_LOG(log, " CEDM::FEVD Added pvar {0}, returned\n{1}" , |
1701 | pvar_sp->GetName(), ClangUtil::DumpDecl(var_decl)); |
1702 | } |
1703 | |
1704 | void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, |
1705 | const Symbol &symbol) { |
1706 | assert(m_parser_vars.get()); |
1707 | |
1708 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1709 | |
1710 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1711 | |
1712 | if (target == nullptr) |
1713 | return; |
1714 | |
1715 | auto scratch_ast_context = GetScratchContext(target&: *target); |
1716 | if (!scratch_ast_context) |
1717 | return; |
1718 | |
1719 | TypeFromUser user_type(scratch_ast_context->GetBasicType(type: eBasicTypeVoid) |
1720 | .GetPointerType() |
1721 | .GetLValueReferenceType()); |
1722 | TypeFromParser parser_type(m_clang_ast_context->GetBasicType(type: eBasicTypeVoid) |
1723 | .GetPointerType() |
1724 | .GetLValueReferenceType()); |
1725 | NamedDecl *var_decl = context.AddVarDecl(type: parser_type); |
1726 | |
1727 | std::string decl_name(context.m_decl_name.getAsString()); |
1728 | ConstString entity_name(decl_name.c_str()); |
1729 | ClangExpressionVariable *entity(new ClangExpressionVariable( |
1730 | m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), entity_name, |
1731 | user_type, m_parser_vars->m_target_info.byte_order, |
1732 | m_parser_vars->m_target_info.address_byte_size)); |
1733 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1734 | |
1735 | entity->EnableParserVars(parser_id: GetParserID()); |
1736 | ClangExpressionVariable::ParserVars *parser_vars = |
1737 | entity->GetParserVars(parser_id: GetParserID()); |
1738 | |
1739 | const Address symbol_address = symbol.GetAddress(); |
1740 | lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); |
1741 | |
1742 | // parser_vars->m_lldb_value.SetContext(Value::ContextType::ClangType, |
1743 | // user_type.GetOpaqueQualType()); |
1744 | parser_vars->m_lldb_value.SetCompilerType(user_type); |
1745 | parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; |
1746 | parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress); |
1747 | |
1748 | parser_vars->m_named_decl = var_decl; |
1749 | parser_vars->m_llvm_value = nullptr; |
1750 | parser_vars->m_lldb_sym = &symbol; |
1751 | |
1752 | LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1}" , decl_name, |
1753 | ClangUtil::DumpDecl(var_decl)); |
1754 | } |
1755 | |
1756 | void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, |
1757 | const RegisterInfo *reg_info) { |
1758 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1759 | |
1760 | CompilerType clang_type = |
1761 | m_clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( |
1762 | encoding: reg_info->encoding, bit_size: reg_info->byte_size * 8); |
1763 | |
1764 | if (!clang_type) { |
1765 | LLDB_LOG(log, " Tried to add a type for {0}, but couldn't get one" , |
1766 | context.m_decl_name.getAsString()); |
1767 | return; |
1768 | } |
1769 | |
1770 | TypeFromParser parser_clang_type(clang_type); |
1771 | |
1772 | NamedDecl *var_decl = context.AddVarDecl(type: parser_clang_type); |
1773 | |
1774 | ClangExpressionVariable *entity(new ClangExpressionVariable( |
1775 | m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), |
1776 | m_parser_vars->m_target_info.byte_order, |
1777 | m_parser_vars->m_target_info.address_byte_size)); |
1778 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1779 | |
1780 | std::string decl_name(context.m_decl_name.getAsString()); |
1781 | entity->SetName(ConstString(decl_name.c_str())); |
1782 | entity->SetRegisterInfo(reg_info); |
1783 | entity->EnableParserVars(parser_id: GetParserID()); |
1784 | ClangExpressionVariable::ParserVars *parser_vars = |
1785 | entity->GetParserVars(parser_id: GetParserID()); |
1786 | parser_vars->m_named_decl = var_decl; |
1787 | parser_vars->m_llvm_value = nullptr; |
1788 | parser_vars->m_lldb_value.Clear(); |
1789 | entity->m_flags |= ClangExpressionVariable::EVBareRegister; |
1790 | |
1791 | LLDB_LOG(log, " CEDM::FEVD Added register {0}, returned\n{1}" , |
1792 | context.m_decl_name.getAsString(), ClangUtil::DumpDecl(var_decl)); |
1793 | } |
1794 | |
1795 | void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, |
1796 | Function *function, |
1797 | Symbol *symbol) { |
1798 | assert(m_parser_vars.get()); |
1799 | |
1800 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1801 | |
1802 | NamedDecl *function_decl = nullptr; |
1803 | Address fun_address; |
1804 | CompilerType function_clang_type; |
1805 | |
1806 | bool is_indirect_function = false; |
1807 | |
1808 | if (function) { |
1809 | Type *function_type = function->GetType(); |
1810 | |
1811 | const auto lang = function->GetCompileUnit()->GetLanguage(); |
1812 | const auto name = function->GetMangled().GetMangledName().AsCString(); |
1813 | const bool extern_c = (Language::LanguageIsC(language: lang) && |
1814 | !CPlusPlusLanguage::IsCPPMangledName(name)) || |
1815 | (Language::LanguageIsObjC(language: lang) && |
1816 | !Language::LanguageIsCPlusPlus(language: lang)); |
1817 | |
1818 | if (!extern_c) { |
1819 | TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); |
1820 | if (llvm::isa<TypeSystemClang>(Val: type_system)) { |
1821 | clang::DeclContext *src_decl_context = |
1822 | (clang::DeclContext *)function->GetDeclContext() |
1823 | .GetOpaqueDeclContext(); |
1824 | clang::FunctionDecl *src_function_decl = |
1825 | llvm::dyn_cast_or_null<clang::FunctionDecl>(Val: src_decl_context); |
1826 | if (src_function_decl && |
1827 | src_function_decl->getTemplateSpecializationInfo()) { |
1828 | clang::FunctionTemplateDecl *function_template = |
1829 | src_function_decl->getTemplateSpecializationInfo()->getTemplate(); |
1830 | clang::FunctionTemplateDecl *copied_function_template = |
1831 | llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>( |
1832 | Val: CopyDecl(function_template)); |
1833 | if (copied_function_template) { |
1834 | if (log) { |
1835 | StreamString ss; |
1836 | |
1837 | function->DumpSymbolContext(s: &ss); |
1838 | |
1839 | LLDB_LOG(log, |
1840 | " CEDM::FEVD Imported decl for function template" |
1841 | " {0} (description {1}), returned\n{2}" , |
1842 | copied_function_template->getNameAsString(), |
1843 | ss.GetData(), |
1844 | ClangUtil::DumpDecl(copied_function_template)); |
1845 | } |
1846 | |
1847 | context.AddNamedDecl(copied_function_template); |
1848 | } |
1849 | } else if (src_function_decl) { |
1850 | if (clang::FunctionDecl *copied_function_decl = |
1851 | llvm::dyn_cast_or_null<clang::FunctionDecl>( |
1852 | Val: CopyDecl(src_function_decl))) { |
1853 | if (log) { |
1854 | StreamString ss; |
1855 | |
1856 | function->DumpSymbolContext(s: &ss); |
1857 | |
1858 | LLDB_LOG(log, |
1859 | " CEDM::FEVD Imported decl for function {0} " |
1860 | "(description {1}), returned\n{2}" , |
1861 | copied_function_decl->getNameAsString(), ss.GetData(), |
1862 | ClangUtil::DumpDecl(copied_function_decl)); |
1863 | } |
1864 | |
1865 | context.AddNamedDecl(copied_function_decl); |
1866 | return; |
1867 | } else { |
1868 | LLDB_LOG(log, " Failed to import the function decl for '{0}'" , |
1869 | src_function_decl->getName()); |
1870 | } |
1871 | } |
1872 | } |
1873 | } |
1874 | |
1875 | if (!function_type) { |
1876 | LLDB_LOG(log, " Skipped a function because it has no type" ); |
1877 | return; |
1878 | } |
1879 | |
1880 | function_clang_type = function_type->GetFullCompilerType(); |
1881 | |
1882 | if (!function_clang_type) { |
1883 | LLDB_LOG(log, " Skipped a function because it has no Clang type" ); |
1884 | return; |
1885 | } |
1886 | |
1887 | fun_address = function->GetAddressRange().GetBaseAddress(); |
1888 | |
1889 | CompilerType copied_function_type = GuardedCopyType(src_type: function_clang_type); |
1890 | if (copied_function_type) { |
1891 | function_decl = context.AddFunDecl(type: copied_function_type, extern_c); |
1892 | |
1893 | if (!function_decl) { |
1894 | LLDB_LOG(log, " Failed to create a function decl for '{0}' ({1:x})" , |
1895 | function_type->GetName(), function_type->GetID()); |
1896 | |
1897 | return; |
1898 | } |
1899 | } else { |
1900 | // We failed to copy the type we found |
1901 | LLDB_LOG(log, |
1902 | " Failed to import the function type '{0}' ({1:x})" |
1903 | " into the expression parser AST context" , |
1904 | function_type->GetName(), function_type->GetID()); |
1905 | |
1906 | return; |
1907 | } |
1908 | } else if (symbol) { |
1909 | fun_address = symbol->GetAddress(); |
1910 | function_decl = context.AddGenericFunDecl(); |
1911 | is_indirect_function = symbol->IsIndirect(); |
1912 | } else { |
1913 | LLDB_LOG(log, " AddOneFunction called with no function and no symbol" ); |
1914 | return; |
1915 | } |
1916 | |
1917 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1918 | |
1919 | lldb::addr_t load_addr = |
1920 | fun_address.GetCallableLoadAddress(target, is_indirect: is_indirect_function); |
1921 | |
1922 | ClangExpressionVariable *entity(new ClangExpressionVariable( |
1923 | m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), |
1924 | m_parser_vars->m_target_info.byte_order, |
1925 | m_parser_vars->m_target_info.address_byte_size)); |
1926 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1927 | |
1928 | std::string decl_name(context.m_decl_name.getAsString()); |
1929 | entity->SetName(ConstString(decl_name.c_str())); |
1930 | entity->SetCompilerType(function_clang_type); |
1931 | entity->EnableParserVars(parser_id: GetParserID()); |
1932 | |
1933 | ClangExpressionVariable::ParserVars *parser_vars = |
1934 | entity->GetParserVars(parser_id: GetParserID()); |
1935 | |
1936 | if (load_addr != LLDB_INVALID_ADDRESS) { |
1937 | parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress); |
1938 | parser_vars->m_lldb_value.GetScalar() = load_addr; |
1939 | } else { |
1940 | // We have to try finding a file address. |
1941 | |
1942 | lldb::addr_t file_addr = fun_address.GetFileAddress(); |
1943 | |
1944 | parser_vars->m_lldb_value.SetValueType(Value::ValueType::FileAddress); |
1945 | parser_vars->m_lldb_value.GetScalar() = file_addr; |
1946 | } |
1947 | |
1948 | parser_vars->m_named_decl = function_decl; |
1949 | parser_vars->m_llvm_value = nullptr; |
1950 | |
1951 | if (log) { |
1952 | StreamString ss; |
1953 | |
1954 | fun_address.Dump(s: &ss, |
1955 | exe_scope: m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), |
1956 | style: Address::DumpStyleResolvedDescription); |
1957 | |
1958 | LLDB_LOG(log, |
1959 | " CEDM::FEVD Found {0} function {1} (description {2}), " |
1960 | "returned\n{3}" , |
1961 | (function ? "specific" : "generic" ), decl_name, ss.GetData(), |
1962 | ClangUtil::DumpDecl(function_decl)); |
1963 | } |
1964 | } |
1965 | |
1966 | void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, |
1967 | const TypeFromUser &ut) { |
1968 | CompilerType copied_clang_type = GuardedCopyType(src_type: ut); |
1969 | |
1970 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1971 | |
1972 | if (!copied_clang_type) { |
1973 | LLDB_LOG(log, |
1974 | "ClangExpressionDeclMap::AddThisType - Couldn't import the type" ); |
1975 | |
1976 | return; |
1977 | } |
1978 | |
1979 | if (copied_clang_type.IsAggregateType() && |
1980 | copied_clang_type.GetCompleteType()) { |
1981 | CompilerType void_clang_type = |
1982 | m_clang_ast_context->GetBasicType(type: eBasicTypeVoid); |
1983 | CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); |
1984 | |
1985 | CompilerType method_type = m_clang_ast_context->CreateFunctionType( |
1986 | result_type: void_clang_type, args: &void_ptr_clang_type, num_args: 1, is_variadic: false, type_quals: 0); |
1987 | |
1988 | const bool is_virtual = false; |
1989 | const bool is_static = false; |
1990 | const bool is_inline = false; |
1991 | const bool is_explicit = false; |
1992 | const bool is_attr_used = true; |
1993 | const bool is_artificial = false; |
1994 | |
1995 | CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType( |
1996 | type: copied_clang_type.GetOpaqueQualType(), name: "$__lldb_expr" , mangled_name: nullptr, |
1997 | method_type, access: lldb::eAccessPublic, is_virtual, is_static, is_inline, |
1998 | is_explicit, is_attr_used, is_artificial); |
1999 | |
2000 | LLDB_LOG(log, |
2001 | " CEDM::AddThisType Added function $__lldb_expr " |
2002 | "(description {0}) for this type\n{1}" , |
2003 | ClangUtil::ToString(copied_clang_type), |
2004 | ClangUtil::DumpDecl(method_decl)); |
2005 | } |
2006 | |
2007 | if (!copied_clang_type.IsValid()) |
2008 | return; |
2009 | |
2010 | TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo( |
2011 | T: QualType::getFromOpaquePtr(Ptr: copied_clang_type.GetOpaqueQualType())); |
2012 | |
2013 | if (!type_source_info) |
2014 | return; |
2015 | |
2016 | // Construct a typedef type because if "*this" is a templated type we can't |
2017 | // just return ClassTemplateSpecializationDecls in response to name queries. |
2018 | // Using a typedef makes this much more robust. |
2019 | |
2020 | TypedefDecl *typedef_decl = TypedefDecl::Create( |
2021 | *m_ast_context, m_ast_context->getTranslationUnitDecl(), SourceLocation(), |
2022 | SourceLocation(), context.m_decl_name.getAsIdentifierInfo(), |
2023 | type_source_info); |
2024 | |
2025 | if (!typedef_decl) |
2026 | return; |
2027 | |
2028 | context.AddNamedDecl(typedef_decl); |
2029 | } |
2030 | |
2031 | void ClangExpressionDeclMap::AddOneType(NameSearchContext &context, |
2032 | const TypeFromUser &ut) { |
2033 | CompilerType copied_clang_type = GuardedCopyType(src_type: ut); |
2034 | |
2035 | if (!copied_clang_type) { |
2036 | Log *log = GetLog(mask: LLDBLog::Expressions); |
2037 | |
2038 | LLDB_LOG(log, |
2039 | "ClangExpressionDeclMap::AddOneType - Couldn't import the type" ); |
2040 | |
2041 | return; |
2042 | } |
2043 | |
2044 | context.AddTypeDecl(compiler_type: copied_clang_type); |
2045 | } |
2046 | |