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/Mangled.h" |
22 | #include "lldb/Core/Module.h" |
23 | #include "lldb/Core/ModuleSpec.h" |
24 | #include "lldb/Expression/DiagnosticManager.h" |
25 | #include "lldb/Expression/Materializer.h" |
26 | #include "lldb/Symbol/CompileUnit.h" |
27 | #include "lldb/Symbol/CompilerDecl.h" |
28 | #include "lldb/Symbol/CompilerDeclContext.h" |
29 | #include "lldb/Symbol/Function.h" |
30 | #include "lldb/Symbol/ObjectFile.h" |
31 | #include "lldb/Symbol/SymbolContext.h" |
32 | #include "lldb/Symbol/SymbolFile.h" |
33 | #include "lldb/Symbol/SymbolVendor.h" |
34 | #include "lldb/Symbol/Type.h" |
35 | #include "lldb/Symbol/TypeList.h" |
36 | #include "lldb/Symbol/Variable.h" |
37 | #include "lldb/Symbol/VariableList.h" |
38 | #include "lldb/Target/ExecutionContext.h" |
39 | #include "lldb/Target/Language.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/ValueObject/ValueObjectConstResult.h" |
51 | #include "lldb/ValueObject/ValueObjectVariable.h" |
52 | #include "lldb/lldb-private-types.h" |
53 | #include "lldb/lldb-private.h" |
54 | #include "clang/AST/ASTConsumer.h" |
55 | #include "clang/AST/ASTContext.h" |
56 | #include "clang/AST/ASTImporter.h" |
57 | #include "clang/AST/Decl.h" |
58 | #include "clang/AST/DeclarationName.h" |
59 | #include "clang/AST/RecursiveASTVisitor.h" |
60 | |
61 | #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" |
62 | #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" |
63 | |
64 | using namespace lldb; |
65 | using namespace lldb_private; |
66 | using namespace clang; |
67 | |
68 | static const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars" ; |
69 | |
70 | namespace { |
71 | /// A lambda is represented by Clang as an artifical class whose |
72 | /// members are the lambda captures. If we capture a 'this' pointer, |
73 | /// the artifical class will contain a member variable named 'this'. |
74 | /// The function returns a ValueObject for the captured 'this' if such |
75 | /// member exists. If no 'this' was captured, return a nullptr. |
76 | lldb::ValueObjectSP GetCapturedThisValueObject(StackFrame *frame) { |
77 | assert(frame); |
78 | |
79 | if (auto thisValSP = frame->FindVariable(name: ConstString("this" ))) |
80 | if (auto thisThisValSP = thisValSP->GetChildMemberWithName(name: "this" )) |
81 | return thisThisValSP; |
82 | |
83 | return nullptr; |
84 | } |
85 | } // namespace |
86 | |
87 | ClangExpressionDeclMap::ClangExpressionDeclMap( |
88 | bool keep_result_in_memory, |
89 | Materializer::PersistentVariableDelegate *result_delegate, |
90 | const lldb::TargetSP &target, |
91 | const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj) |
92 | : ClangASTSource(target, importer), m_found_entities(), m_struct_members(), |
93 | m_keep_result_in_memory(keep_result_in_memory), |
94 | m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(), |
95 | m_struct_vars() { |
96 | EnableStructVars(); |
97 | } |
98 | |
99 | ClangExpressionDeclMap::~ClangExpressionDeclMap() { |
100 | // Note: The model is now that the parser's AST context and all associated |
101 | // data does not vanish until the expression has been executed. This means |
102 | // that valuable lookup data (like namespaces) doesn't vanish, but |
103 | |
104 | DidParse(); |
105 | DisableStructVars(); |
106 | } |
107 | |
108 | bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, |
109 | Materializer *materializer) { |
110 | EnableParserVars(); |
111 | m_parser_vars->m_exe_ctx = exe_ctx; |
112 | |
113 | Target *target = exe_ctx.GetTargetPtr(); |
114 | if (exe_ctx.GetFramePtr()) |
115 | m_parser_vars->m_sym_ctx = |
116 | exe_ctx.GetFramePtr()->GetSymbolContext(resolve_scope: lldb::eSymbolContextEverything); |
117 | else if (exe_ctx.GetThreadPtr() && |
118 | exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx: 0)) |
119 | m_parser_vars->m_sym_ctx = |
120 | exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx: 0)->GetSymbolContext( |
121 | resolve_scope: lldb::eSymbolContextEverything); |
122 | else if (exe_ctx.GetProcessPtr()) { |
123 | m_parser_vars->m_sym_ctx.Clear(clear_target: true); |
124 | m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); |
125 | } else if (target) { |
126 | m_parser_vars->m_sym_ctx.Clear(clear_target: true); |
127 | m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); |
128 | } |
129 | |
130 | if (target) { |
131 | m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>( |
132 | Val: target->GetPersistentExpressionStateForLanguage(language: eLanguageTypeC)); |
133 | |
134 | if (!ScratchTypeSystemClang::GetForTarget(target&: *target)) |
135 | return false; |
136 | } |
137 | |
138 | m_parser_vars->m_target_info = GetTargetInfo(); |
139 | m_parser_vars->m_materializer = materializer; |
140 | |
141 | return true; |
142 | } |
143 | |
144 | void ClangExpressionDeclMap::InstallCodeGenerator( |
145 | clang::ASTConsumer *code_gen) { |
146 | assert(m_parser_vars); |
147 | m_parser_vars->m_code_gen = code_gen; |
148 | } |
149 | |
150 | void ClangExpressionDeclMap::InstallDiagnosticManager( |
151 | DiagnosticManager &diag_manager) { |
152 | assert(m_parser_vars); |
153 | m_parser_vars->m_diagnostics = &diag_manager; |
154 | } |
155 | |
156 | void ClangExpressionDeclMap::DidParse() { |
157 | if (m_parser_vars && m_parser_vars->m_persistent_vars) { |
158 | for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); |
159 | entity_index < num_entities; ++entity_index) { |
160 | ExpressionVariableSP var_sp( |
161 | m_found_entities.GetVariableAtIndex(index: entity_index)); |
162 | if (var_sp) |
163 | llvm::cast<ClangExpressionVariable>(Val: var_sp.get()) |
164 | ->DisableParserVars(parser_id: GetParserID()); |
165 | } |
166 | |
167 | for (size_t pvar_index = 0, |
168 | num_pvars = m_parser_vars->m_persistent_vars->GetSize(); |
169 | pvar_index < num_pvars; ++pvar_index) { |
170 | ExpressionVariableSP pvar_sp( |
171 | m_parser_vars->m_persistent_vars->GetVariableAtIndex(index: pvar_index)); |
172 | if (ClangExpressionVariable *clang_var = |
173 | llvm::dyn_cast<ClangExpressionVariable>(Val: pvar_sp.get())) |
174 | clang_var->DisableParserVars(parser_id: GetParserID()); |
175 | } |
176 | |
177 | DisableParserVars(); |
178 | } |
179 | } |
180 | |
181 | // Interface for IRForTarget |
182 | |
183 | ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { |
184 | assert(m_parser_vars.get()); |
185 | |
186 | TargetInfo ret; |
187 | |
188 | ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; |
189 | |
190 | Process *process = exe_ctx.GetProcessPtr(); |
191 | if (process) { |
192 | ret.byte_order = process->GetByteOrder(); |
193 | ret.address_byte_size = process->GetAddressByteSize(); |
194 | } else { |
195 | Target *target = exe_ctx.GetTargetPtr(); |
196 | if (target) { |
197 | ret.byte_order = target->GetArchitecture().GetByteOrder(); |
198 | ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); |
199 | } |
200 | } |
201 | |
202 | return ret; |
203 | } |
204 | |
205 | TypeFromUser ClangExpressionDeclMap::DeportType(TypeSystemClang &target, |
206 | TypeSystemClang &source, |
207 | TypeFromParser parser_type) { |
208 | assert(&target == GetScratchContext(*m_target).get()); |
209 | assert((TypeSystem *)&source == |
210 | parser_type.GetTypeSystem().GetSharedPointer().get()); |
211 | assert(&source.getASTContext() == m_ast_context); |
212 | |
213 | return TypeFromUser(m_ast_importer_sp->DeportType(dst&: target, src_type: parser_type)); |
214 | } |
215 | |
216 | bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, |
217 | ConstString name, |
218 | TypeFromParser parser_type, |
219 | bool is_result, |
220 | bool is_lvalue) { |
221 | assert(m_parser_vars.get()); |
222 | auto ast = parser_type.GetTypeSystem<TypeSystemClang>(); |
223 | if (ast == nullptr) |
224 | return false; |
225 | |
226 | // Check if we already declared a persistent variable with the same name. |
227 | if (lldb::ExpressionVariableSP conflicting_var = |
228 | m_parser_vars->m_persistent_vars->GetVariable(name)) { |
229 | std::string msg = llvm::formatv(Fmt: "redefinition of persistent variable '{0}'" , |
230 | Vals&: name).str(); |
231 | m_parser_vars->m_diagnostics->AddDiagnostic( |
232 | message: msg, severity: lldb::eSeverityError, 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 Adding type for $__lldb_objc_class: {0}" , |
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 Adding type for $__lldb_objc_class: {0}" , |
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 | } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) { |
1051 | context.AddNamedDecl(decl: copied_var); |
1052 | context.m_found_variable = true; |
1053 | } |
1054 | } |
1055 | |
1056 | bool ClangExpressionDeclMap::LookupLocalVariable( |
1057 | NameSearchContext &context, ConstString name, SymbolContext &sym_ctx, |
1058 | const CompilerDeclContext &namespace_decl) { |
1059 | if (sym_ctx.block == nullptr) |
1060 | return false; |
1061 | |
1062 | CompilerDeclContext decl_context = sym_ctx.block->GetDeclContext(); |
1063 | if (!decl_context) |
1064 | return false; |
1065 | |
1066 | // Make sure that the variables are parsed so that we have the |
1067 | // declarations. |
1068 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
1069 | VariableListSP vars = frame->GetInScopeVariableList(get_file_globals: true); |
1070 | for (size_t i = 0; i < vars->GetSize(); i++) |
1071 | vars->GetVariableAtIndex(idx: i)->GetDecl(); |
1072 | |
1073 | // Search for declarations matching the name. Do not include imported |
1074 | // decls in the search if we are looking for decls in the artificial |
1075 | // namespace $__lldb_local_vars. |
1076 | std::vector<CompilerDecl> found_decls = |
1077 | decl_context.FindDeclByName(name, ignore_using_decls: namespace_decl.IsValid()); |
1078 | |
1079 | VariableSP var; |
1080 | bool variable_found = false; |
1081 | for (CompilerDecl decl : found_decls) { |
1082 | for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) { |
1083 | VariableSP candidate_var = vars->GetVariableAtIndex(idx: vi); |
1084 | if (candidate_var->GetDecl() == decl) { |
1085 | var = candidate_var; |
1086 | break; |
1087 | } |
1088 | } |
1089 | |
1090 | if (var && !variable_found) { |
1091 | variable_found = true; |
1092 | ValueObjectSP valobj = ValueObjectVariable::Create(exe_scope: frame, var_sp: var); |
1093 | AddOneVariable(context, var, valobj); |
1094 | context.m_found_variable = true; |
1095 | } |
1096 | } |
1097 | |
1098 | // We're in a local_var_lookup but haven't found any local variables |
1099 | // so far. When performing a variable lookup from within the context of |
1100 | // a lambda, we count the lambda captures as local variables. Thus, |
1101 | // see if we captured any variables with the requested 'name'. |
1102 | if (!variable_found) { |
1103 | auto find_capture = [](ConstString varname, |
1104 | StackFrame *frame) -> ValueObjectSP { |
1105 | if (auto lambda = ClangExpressionUtil::GetLambdaValueObject(frame)) { |
1106 | if (auto capture = lambda->GetChildMemberWithName(name: varname)) { |
1107 | return capture; |
1108 | } |
1109 | } |
1110 | |
1111 | return nullptr; |
1112 | }; |
1113 | |
1114 | if (auto capture = find_capture(name, frame)) { |
1115 | variable_found = true; |
1116 | context.m_found_variable = true; |
1117 | AddOneVariable(context, valobj: std::move(capture), valobj_provider: std::move(find_capture)); |
1118 | } |
1119 | } |
1120 | |
1121 | return variable_found; |
1122 | } |
1123 | |
1124 | /// Structure to hold the info needed when comparing function |
1125 | /// declarations. |
1126 | namespace { |
1127 | struct FuncDeclInfo { |
1128 | ConstString m_name; |
1129 | CompilerType m_copied_type; |
1130 | uint32_t m_decl_lvl; |
1131 | SymbolContext m_sym_ctx; |
1132 | }; |
1133 | } // namespace |
1134 | |
1135 | SymbolContextList ClangExpressionDeclMap::SearchFunctionsInSymbolContexts( |
1136 | const SymbolContextList &sc_list, |
1137 | const CompilerDeclContext &frame_decl_context) { |
1138 | // First, symplify things by looping through the symbol contexts to |
1139 | // remove unwanted functions and separate out the functions we want to |
1140 | // compare and prune into a separate list. Cache the info needed about |
1141 | // the function declarations in a vector for efficiency. |
1142 | SymbolContextList sc_sym_list; |
1143 | std::vector<FuncDeclInfo> decl_infos; |
1144 | decl_infos.reserve(n: sc_list.GetSize()); |
1145 | clang::DeclContext *frame_decl_ctx = |
1146 | (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); |
1147 | TypeSystemClang *ast = llvm::dyn_cast_or_null<TypeSystemClang>( |
1148 | Val: frame_decl_context.GetTypeSystem()); |
1149 | |
1150 | for (const SymbolContext &sym_ctx : sc_list) { |
1151 | FuncDeclInfo fdi; |
1152 | |
1153 | // We don't know enough about symbols to compare them, but we should |
1154 | // keep them in the list. |
1155 | Function *function = sym_ctx.function; |
1156 | if (!function) { |
1157 | sc_sym_list.Append(sc: sym_ctx); |
1158 | continue; |
1159 | } |
1160 | // Filter out functions without declaration contexts, as well as |
1161 | // class/instance methods, since they'll be skipped in the code that |
1162 | // follows anyway. |
1163 | CompilerDeclContext func_decl_context = function->GetDeclContext(); |
1164 | if (!func_decl_context || func_decl_context.IsClassMethod()) |
1165 | continue; |
1166 | // We can only prune functions for which we can copy the type. |
1167 | CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); |
1168 | CompilerType copied_func_type = GuardedCopyType(src_type: func_clang_type); |
1169 | if (!copied_func_type) { |
1170 | sc_sym_list.Append(sc: sym_ctx); |
1171 | continue; |
1172 | } |
1173 | |
1174 | fdi.m_sym_ctx = sym_ctx; |
1175 | fdi.m_name = function->GetName(); |
1176 | fdi.m_copied_type = copied_func_type; |
1177 | fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; |
1178 | if (fdi.m_copied_type && func_decl_context) { |
1179 | // Call CountDeclLevels to get the number of parent scopes we have |
1180 | // to look through before we find the function declaration. When |
1181 | // comparing functions of the same type, the one with a lower count |
1182 | // will be closer to us in the lookup scope and shadows the other. |
1183 | clang::DeclContext *func_decl_ctx = |
1184 | (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); |
1185 | fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, child_decl_ctx: func_decl_ctx, |
1186 | child_name: &fdi.m_name, child_type: &fdi.m_copied_type); |
1187 | } |
1188 | decl_infos.emplace_back(args&: fdi); |
1189 | } |
1190 | |
1191 | // Loop through the functions in our cache looking for matching types, |
1192 | // then compare their scope levels to see which is closer. |
1193 | std::multimap<CompilerType, const FuncDeclInfo *> matches; |
1194 | for (const FuncDeclInfo &fdi : decl_infos) { |
1195 | const CompilerType t = fdi.m_copied_type; |
1196 | auto q = matches.find(x: t); |
1197 | if (q != matches.end()) { |
1198 | if (q->second->m_decl_lvl > fdi.m_decl_lvl) |
1199 | // This function is closer; remove the old set. |
1200 | matches.erase(x: t); |
1201 | else if (q->second->m_decl_lvl < fdi.m_decl_lvl) |
1202 | // The functions in our set are closer - skip this one. |
1203 | continue; |
1204 | } |
1205 | matches.insert(x: std::make_pair(x: t, y: &fdi)); |
1206 | } |
1207 | |
1208 | // Loop through our matches and add their symbol contexts to our list. |
1209 | SymbolContextList sc_func_list; |
1210 | for (const auto &q : matches) |
1211 | sc_func_list.Append(sc: q.second->m_sym_ctx); |
1212 | |
1213 | // Rejoin the lists with the functions in front. |
1214 | sc_func_list.Append(sc_list: sc_sym_list); |
1215 | return sc_func_list; |
1216 | } |
1217 | |
1218 | bool ClangExpressionDeclMap::LookupFunction( |
1219 | NameSearchContext &context, lldb::ModuleSP module_sp, ConstString name, |
1220 | const CompilerDeclContext &namespace_decl) { |
1221 | if (!m_parser_vars) |
1222 | return false; |
1223 | |
1224 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1225 | |
1226 | std::vector<clang::NamedDecl *> decls_from_modules; |
1227 | |
1228 | if (target) { |
1229 | if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor = |
1230 | GetClangModulesDeclVendor()) { |
1231 | decl_vendor->FindDecls(name, append: false, UINT32_MAX, decls&: decls_from_modules); |
1232 | } |
1233 | } |
1234 | |
1235 | SymbolContextList sc_list; |
1236 | if (namespace_decl && module_sp) { |
1237 | ModuleFunctionSearchOptions function_options; |
1238 | function_options.include_inlines = false; |
1239 | function_options.include_symbols = false; |
1240 | |
1241 | module_sp->FindFunctions(name, parent_decl_ctx: namespace_decl, name_type_mask: eFunctionNameTypeBase, |
1242 | options: function_options, sc_list); |
1243 | } else if (target && !namespace_decl) { |
1244 | ModuleFunctionSearchOptions function_options; |
1245 | function_options.include_inlines = false; |
1246 | function_options.include_symbols = true; |
1247 | |
1248 | // TODO Fix FindFunctions so that it doesn't return |
1249 | // instance methods for eFunctionNameTypeBase. |
1250 | |
1251 | target->GetImages().FindFunctions( |
1252 | name, name_type_mask: eFunctionNameTypeFull | eFunctionNameTypeBase, options: function_options, |
1253 | sc_list); |
1254 | } |
1255 | |
1256 | // If we found more than one function, see if we can use the frame's decl |
1257 | // context to remove functions that are shadowed by other functions which |
1258 | // match in type but are nearer in scope. |
1259 | // |
1260 | // AddOneFunction will not add a function whose type has already been |
1261 | // added, so if there's another function in the list with a matching type, |
1262 | // check to see if their decl context is a parent of the current frame's or |
1263 | // was imported via a and using statement, and pick the best match |
1264 | // according to lookup rules. |
1265 | if (sc_list.GetSize() > 1) { |
1266 | // Collect some info about our frame's context. |
1267 | StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
1268 | SymbolContext frame_sym_ctx; |
1269 | if (frame != nullptr) |
1270 | frame_sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
1271 | lldb::eSymbolContextBlock); |
1272 | CompilerDeclContext frame_decl_context = |
1273 | frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() |
1274 | : CompilerDeclContext(); |
1275 | |
1276 | // We can't do this without a compiler decl context for our frame. |
1277 | if (frame_decl_context) { |
1278 | sc_list = SearchFunctionsInSymbolContexts(sc_list, frame_decl_context); |
1279 | } |
1280 | } |
1281 | |
1282 | bool found_function_with_type_info = false; |
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 | 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 (!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 | found_function_with_type_info = true; |
1324 | } |
1325 | } |
1326 | } |
1327 | } |
1328 | |
1329 | if (!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 | return found_function_with_type_info; |
1339 | } |
1340 | |
1341 | void ClangExpressionDeclMap::FindExternalVisibleDecls( |
1342 | NameSearchContext &context, lldb::ModuleSP module_sp, |
1343 | const CompilerDeclContext &namespace_decl) { |
1344 | assert(m_ast_context); |
1345 | |
1346 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1347 | |
1348 | const ConstString name(context.m_decl_name.getAsString().c_str()); |
1349 | if (IgnoreName(name, ignore_all_dollar_names: false)) |
1350 | return; |
1351 | |
1352 | // Only look for functions by name out in our symbols if the function doesn't |
1353 | // start with our phony prefix of '$' |
1354 | |
1355 | Target *target = nullptr; |
1356 | StackFrame *frame = nullptr; |
1357 | SymbolContext sym_ctx; |
1358 | if (m_parser_vars) { |
1359 | target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1360 | frame = m_parser_vars->m_exe_ctx.GetFramePtr(); |
1361 | } |
1362 | if (frame != nullptr) |
1363 | sym_ctx = frame->GetSymbolContext(resolve_scope: lldb::eSymbolContextFunction | |
1364 | lldb::eSymbolContextBlock); |
1365 | |
1366 | // Try the persistent decls, which take precedence over all else. |
1367 | if (!namespace_decl) |
1368 | SearchPersistenDecls(context, name); |
1369 | |
1370 | if (name.GetStringRef().starts_with(Prefix: "$" ) && !namespace_decl) { |
1371 | if (name == "$__lldb_class" ) { |
1372 | LookUpLldbClass(context); |
1373 | return; |
1374 | } |
1375 | |
1376 | if (name == "$__lldb_objc_class" ) { |
1377 | LookUpLldbObjCClass(context); |
1378 | return; |
1379 | } |
1380 | if (name == g_lldb_local_vars_namespace_cstr) { |
1381 | LookupLocalVarNamespace(sym_ctx, name_context&: context); |
1382 | return; |
1383 | } |
1384 | |
1385 | // any other $__lldb names should be weeded out now |
1386 | if (name.GetStringRef().starts_with(Prefix: "$__lldb" )) |
1387 | return; |
1388 | |
1389 | // No ParserVars means we can't do register or variable lookup. |
1390 | if (!m_parser_vars || !m_parser_vars->m_persistent_vars) |
1391 | return; |
1392 | |
1393 | ExpressionVariableSP pvar_sp( |
1394 | m_parser_vars->m_persistent_vars->GetVariable(name)); |
1395 | |
1396 | if (pvar_sp) { |
1397 | AddOneVariable(context, pvar_sp); |
1398 | return; |
1399 | } |
1400 | |
1401 | assert(name.GetStringRef().starts_with("$" )); |
1402 | llvm::StringRef reg_name = name.GetStringRef().substr(Start: 1); |
1403 | |
1404 | if (m_parser_vars->m_exe_ctx.GetRegisterContext()) { |
1405 | const RegisterInfo *reg_info( |
1406 | m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName( |
1407 | reg_name)); |
1408 | |
1409 | if (reg_info) { |
1410 | LLDB_LOG(log, " CEDM::FEVD Found register {0}" , reg_info->name); |
1411 | |
1412 | AddOneRegister(context, reg_info); |
1413 | } |
1414 | } |
1415 | return; |
1416 | } |
1417 | |
1418 | bool local_var_lookup = !namespace_decl || (namespace_decl.GetName() == |
1419 | g_lldb_local_vars_namespace_cstr); |
1420 | if (frame && local_var_lookup) |
1421 | if (LookupLocalVariable(context, name, sym_ctx, namespace_decl)) |
1422 | return; |
1423 | |
1424 | if (target) { |
1425 | ValueObjectSP valobj; |
1426 | VariableSP var; |
1427 | var = FindGlobalVariable(target&: *target, module&: module_sp, name, namespace_decl); |
1428 | |
1429 | if (var) { |
1430 | valobj = ValueObjectVariable::Create(exe_scope: target, var_sp: var); |
1431 | AddOneVariable(context, var, valobj); |
1432 | context.m_found_variable = true; |
1433 | return; |
1434 | } |
1435 | } |
1436 | |
1437 | if (!LookupFunction(context, module_sp, name, namespace_decl)) |
1438 | LookupInModulesDeclVendor(context, name); |
1439 | |
1440 | if (target && !context.m_found_variable && !namespace_decl) { |
1441 | // We couldn't find a non-symbol variable for this. Now we'll hunt for a |
1442 | // generic data symbol, and -- if it is found -- treat it as a variable. |
1443 | Status error; |
1444 | |
1445 | const Symbol *data_symbol = |
1446 | m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error); |
1447 | |
1448 | if (!error.Success()) { |
1449 | const unsigned diag_id = |
1450 | m_ast_context->getDiagnostics().getCustomDiagID( |
1451 | L: clang::DiagnosticsEngine::Level::Error, FormatString: "%0" ); |
1452 | m_ast_context->getDiagnostics().Report(DiagID: diag_id) << error.AsCString(); |
1453 | } |
1454 | |
1455 | if (data_symbol) { |
1456 | std::string warning("got name from symbols: " ); |
1457 | warning.append(s: name.AsCString()); |
1458 | const unsigned diag_id = |
1459 | m_ast_context->getDiagnostics().getCustomDiagID( |
1460 | L: clang::DiagnosticsEngine::Level::Warning, FormatString: "%0" ); |
1461 | m_ast_context->getDiagnostics().Report(DiagID: diag_id) << warning.c_str(); |
1462 | AddOneGenericVariable(context, symbol: *data_symbol); |
1463 | context.m_found_variable = true; |
1464 | } |
1465 | } |
1466 | } |
1467 | |
1468 | bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, |
1469 | lldb_private::Value &var_location, |
1470 | TypeFromUser *user_type, |
1471 | TypeFromParser *parser_type) { |
1472 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1473 | |
1474 | Type *var_type = var->GetType(); |
1475 | |
1476 | if (!var_type) { |
1477 | LLDB_LOG(log, "Skipped a definition because it has no type" ); |
1478 | return false; |
1479 | } |
1480 | |
1481 | CompilerType var_clang_type = var_type->GetFullCompilerType(); |
1482 | |
1483 | if (!var_clang_type) { |
1484 | LLDB_LOG(log, "Skipped a definition because it has no Clang type" ); |
1485 | return false; |
1486 | } |
1487 | |
1488 | auto clang_ast = |
1489 | var_type->GetForwardCompilerType().GetTypeSystem<TypeSystemClang>(); |
1490 | |
1491 | if (!clang_ast) { |
1492 | LLDB_LOG(log, "Skipped a definition because it has no Clang AST" ); |
1493 | return false; |
1494 | } |
1495 | |
1496 | DWARFExpressionList &var_location_list = var->LocationExpressionList(); |
1497 | |
1498 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1499 | Status err; |
1500 | |
1501 | if (var->GetLocationIsConstantValueData()) { |
1502 | DataExtractor ; |
1503 | if (var_location_list.GetExpressionData(data&: const_value_extractor)) { |
1504 | var_location = Value(const_value_extractor.GetDataStart(), |
1505 | const_value_extractor.GetByteSize()); |
1506 | var_location.SetValueType(Value::ValueType::HostAddress); |
1507 | } else { |
1508 | LLDB_LOG(log, "Error evaluating constant variable: {0}" , err.AsCString()); |
1509 | return false; |
1510 | } |
1511 | } |
1512 | |
1513 | CompilerType type_to_use = GuardedCopyType(src_type: var_clang_type); |
1514 | |
1515 | if (!type_to_use) { |
1516 | LLDB_LOG(log, |
1517 | "Couldn't copy a variable's type into the parser's AST context" ); |
1518 | |
1519 | return false; |
1520 | } |
1521 | |
1522 | if (parser_type) |
1523 | *parser_type = TypeFromParser(type_to_use); |
1524 | |
1525 | if (var_location.GetContextType() == Value::ContextType::Invalid) |
1526 | var_location.SetCompilerType(type_to_use); |
1527 | |
1528 | if (var_location.GetValueType() == Value::ValueType::FileAddress) { |
1529 | SymbolContext var_sc; |
1530 | var->CalculateSymbolContext(sc: &var_sc); |
1531 | |
1532 | if (!var_sc.module_sp) |
1533 | return false; |
1534 | |
1535 | Address so_addr(var_location.GetScalar().ULongLong(), |
1536 | var_sc.module_sp->GetSectionList()); |
1537 | |
1538 | lldb::addr_t load_addr = so_addr.GetLoadAddress(target); |
1539 | |
1540 | if (load_addr != LLDB_INVALID_ADDRESS) { |
1541 | var_location.GetScalar() = load_addr; |
1542 | var_location.SetValueType(Value::ValueType::LoadAddress); |
1543 | } |
1544 | } |
1545 | |
1546 | if (user_type) |
1547 | *user_type = TypeFromUser(var_clang_type); |
1548 | |
1549 | return true; |
1550 | } |
1551 | |
1552 | ClangExpressionVariable::ParserVars * |
1553 | ClangExpressionDeclMap::AddExpressionVariable(NameSearchContext &context, |
1554 | TypeFromParser const &pt, |
1555 | ValueObjectSP valobj) { |
1556 | clang::QualType parser_opaque_type = |
1557 | QualType::getFromOpaquePtr(Ptr: pt.GetOpaqueQualType()); |
1558 | |
1559 | if (parser_opaque_type.isNull()) |
1560 | return nullptr; |
1561 | |
1562 | if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) { |
1563 | if (const TagType *tag_type = dyn_cast<TagType>(Val: parser_type)) |
1564 | CompleteType(Tag: tag_type->getDecl()); |
1565 | if (const ObjCObjectPointerType *objc_object_ptr_type = |
1566 | dyn_cast<ObjCObjectPointerType>(Val: parser_type)) |
1567 | CompleteType(Class: objc_object_ptr_type->getInterfaceDecl()); |
1568 | } |
1569 | |
1570 | bool is_reference = pt.IsReferenceType(); |
1571 | |
1572 | NamedDecl *var_decl = nullptr; |
1573 | if (is_reference) |
1574 | var_decl = context.AddVarDecl(type: pt); |
1575 | else |
1576 | var_decl = context.AddVarDecl(type: pt.GetLValueReferenceType()); |
1577 | |
1578 | std::string decl_name(context.m_decl_name.getAsString()); |
1579 | ConstString entity_name(decl_name.c_str()); |
1580 | ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); |
1581 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1582 | |
1583 | assert(entity); |
1584 | entity->EnableParserVars(parser_id: GetParserID()); |
1585 | ClangExpressionVariable::ParserVars *parser_vars = |
1586 | entity->GetParserVars(parser_id: GetParserID()); |
1587 | |
1588 | parser_vars->m_named_decl = var_decl; |
1589 | |
1590 | if (is_reference) |
1591 | entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; |
1592 | |
1593 | return parser_vars; |
1594 | } |
1595 | |
1596 | void ClangExpressionDeclMap::AddOneVariable( |
1597 | NameSearchContext &context, ValueObjectSP valobj, |
1598 | ValueObjectProviderTy valobj_provider) { |
1599 | assert(m_parser_vars.get()); |
1600 | assert(valobj); |
1601 | |
1602 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1603 | |
1604 | Value var_location = valobj->GetValue(); |
1605 | |
1606 | TypeFromUser user_type = valobj->GetCompilerType(); |
1607 | |
1608 | auto clang_ast = user_type.GetTypeSystem<TypeSystemClang>(); |
1609 | |
1610 | if (!clang_ast) { |
1611 | LLDB_LOG(log, "Skipped a definition because it has no Clang AST" ); |
1612 | return; |
1613 | } |
1614 | |
1615 | TypeFromParser parser_type = GuardedCopyType(src_type: user_type); |
1616 | |
1617 | if (!parser_type) { |
1618 | LLDB_LOG(log, |
1619 | "Couldn't copy a variable's type into the parser's AST context" ); |
1620 | |
1621 | return; |
1622 | } |
1623 | |
1624 | if (var_location.GetContextType() == Value::ContextType::Invalid) |
1625 | var_location.SetCompilerType(parser_type); |
1626 | |
1627 | ClangExpressionVariable::ParserVars *parser_vars = |
1628 | AddExpressionVariable(context, pt: parser_type, valobj); |
1629 | |
1630 | if (!parser_vars) |
1631 | return; |
1632 | |
1633 | LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})" , |
1634 | context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), |
1635 | ClangUtil::ToString(user_type)); |
1636 | |
1637 | parser_vars->m_llvm_value = nullptr; |
1638 | parser_vars->m_lldb_value = std::move(var_location); |
1639 | parser_vars->m_lldb_valobj_provider = std::move(valobj_provider); |
1640 | } |
1641 | |
1642 | void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, |
1643 | VariableSP var, |
1644 | ValueObjectSP valobj) { |
1645 | assert(m_parser_vars.get()); |
1646 | |
1647 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1648 | |
1649 | TypeFromUser ut; |
1650 | TypeFromParser pt; |
1651 | Value var_location; |
1652 | |
1653 | if (!GetVariableValue(var, var_location, user_type: &ut, parser_type: &pt)) |
1654 | return; |
1655 | |
1656 | ClangExpressionVariable::ParserVars *parser_vars = |
1657 | AddExpressionVariable(context, pt, valobj: std::move(valobj)); |
1658 | |
1659 | if (!parser_vars) |
1660 | return; |
1661 | |
1662 | LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})" , |
1663 | context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), |
1664 | ClangUtil::ToString(ut)); |
1665 | |
1666 | parser_vars->m_llvm_value = nullptr; |
1667 | parser_vars->m_lldb_value = var_location; |
1668 | parser_vars->m_lldb_var = var; |
1669 | } |
1670 | |
1671 | void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, |
1672 | ExpressionVariableSP &pvar_sp) { |
1673 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1674 | |
1675 | TypeFromUser user_type( |
1676 | llvm::cast<ClangExpressionVariable>(Val: pvar_sp.get())->GetTypeFromUser()); |
1677 | |
1678 | TypeFromParser parser_type(GuardedCopyType(src_type: user_type)); |
1679 | |
1680 | if (!parser_type.GetOpaqueQualType()) { |
1681 | LLDB_LOG(log, " CEDM::FEVD Couldn't import type for pvar {0}" , |
1682 | pvar_sp->GetName()); |
1683 | return; |
1684 | } |
1685 | |
1686 | NamedDecl *var_decl = |
1687 | context.AddVarDecl(type: parser_type.GetLValueReferenceType()); |
1688 | |
1689 | llvm::cast<ClangExpressionVariable>(Val: pvar_sp.get()) |
1690 | ->EnableParserVars(parser_id: GetParserID()); |
1691 | ClangExpressionVariable::ParserVars *parser_vars = |
1692 | llvm::cast<ClangExpressionVariable>(Val: pvar_sp.get()) |
1693 | ->GetParserVars(parser_id: GetParserID()); |
1694 | parser_vars->m_named_decl = var_decl; |
1695 | parser_vars->m_llvm_value = nullptr; |
1696 | parser_vars->m_lldb_value.Clear(); |
1697 | |
1698 | LLDB_LOG(log, " CEDM::FEVD Added pvar {0}, returned\n{1}" , |
1699 | pvar_sp->GetName(), ClangUtil::DumpDecl(var_decl)); |
1700 | } |
1701 | |
1702 | void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, |
1703 | const Symbol &symbol) { |
1704 | assert(m_parser_vars.get()); |
1705 | |
1706 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1707 | |
1708 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1709 | |
1710 | if (target == nullptr) |
1711 | return; |
1712 | |
1713 | auto scratch_ast_context = GetScratchContext(target&: *target); |
1714 | if (!scratch_ast_context) |
1715 | return; |
1716 | |
1717 | TypeFromUser user_type(scratch_ast_context->GetBasicType(type: eBasicTypeVoid) |
1718 | .GetPointerType() |
1719 | .GetLValueReferenceType()); |
1720 | TypeFromParser parser_type(m_clang_ast_context->GetBasicType(type: eBasicTypeVoid) |
1721 | .GetPointerType() |
1722 | .GetLValueReferenceType()); |
1723 | NamedDecl *var_decl = context.AddVarDecl(type: parser_type); |
1724 | |
1725 | std::string decl_name(context.m_decl_name.getAsString()); |
1726 | ConstString entity_name(decl_name.c_str()); |
1727 | ClangExpressionVariable *entity(new ClangExpressionVariable( |
1728 | m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), entity_name, |
1729 | user_type, m_parser_vars->m_target_info.byte_order, |
1730 | m_parser_vars->m_target_info.address_byte_size)); |
1731 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1732 | |
1733 | entity->EnableParserVars(parser_id: GetParserID()); |
1734 | ClangExpressionVariable::ParserVars *parser_vars = |
1735 | entity->GetParserVars(parser_id: GetParserID()); |
1736 | |
1737 | const Address symbol_address = symbol.GetAddress(); |
1738 | lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); |
1739 | |
1740 | // parser_vars->m_lldb_value.SetContext(Value::ContextType::ClangType, |
1741 | // user_type.GetOpaqueQualType()); |
1742 | parser_vars->m_lldb_value.SetCompilerType(user_type); |
1743 | parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; |
1744 | parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress); |
1745 | |
1746 | parser_vars->m_named_decl = var_decl; |
1747 | parser_vars->m_llvm_value = nullptr; |
1748 | parser_vars->m_lldb_sym = &symbol; |
1749 | |
1750 | LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1}" , decl_name, |
1751 | ClangUtil::DumpDecl(var_decl)); |
1752 | } |
1753 | |
1754 | void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, |
1755 | const RegisterInfo *reg_info) { |
1756 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1757 | |
1758 | CompilerType clang_type = |
1759 | m_clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( |
1760 | encoding: reg_info->encoding, bit_size: reg_info->byte_size * 8); |
1761 | |
1762 | if (!clang_type) { |
1763 | LLDB_LOG(log, " Tried to add a type for {0}, but couldn't get one" , |
1764 | context.m_decl_name.getAsString()); |
1765 | return; |
1766 | } |
1767 | |
1768 | TypeFromParser parser_clang_type(clang_type); |
1769 | |
1770 | NamedDecl *var_decl = context.AddVarDecl(type: parser_clang_type); |
1771 | |
1772 | ClangExpressionVariable *entity(new ClangExpressionVariable( |
1773 | m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), |
1774 | m_parser_vars->m_target_info.byte_order, |
1775 | m_parser_vars->m_target_info.address_byte_size)); |
1776 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1777 | |
1778 | std::string decl_name(context.m_decl_name.getAsString()); |
1779 | entity->SetName(ConstString(decl_name.c_str())); |
1780 | entity->SetRegisterInfo(reg_info); |
1781 | entity->EnableParserVars(parser_id: GetParserID()); |
1782 | ClangExpressionVariable::ParserVars *parser_vars = |
1783 | entity->GetParserVars(parser_id: GetParserID()); |
1784 | parser_vars->m_named_decl = var_decl; |
1785 | parser_vars->m_llvm_value = nullptr; |
1786 | parser_vars->m_lldb_value.Clear(); |
1787 | entity->m_flags |= ClangExpressionVariable::EVBareRegister; |
1788 | |
1789 | LLDB_LOG(log, " CEDM::FEVD Added register {0}, returned\n{1}" , |
1790 | context.m_decl_name.getAsString(), ClangUtil::DumpDecl(var_decl)); |
1791 | } |
1792 | |
1793 | void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, |
1794 | Function *function, |
1795 | Symbol *symbol) { |
1796 | assert(m_parser_vars.get()); |
1797 | |
1798 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1799 | |
1800 | NamedDecl *function_decl = nullptr; |
1801 | Address fun_address; |
1802 | CompilerType function_clang_type; |
1803 | |
1804 | bool is_indirect_function = false; |
1805 | |
1806 | if (function) { |
1807 | Type *function_type = function->GetType(); |
1808 | |
1809 | const auto lang = function->GetCompileUnit()->GetLanguage(); |
1810 | const auto name = function->GetMangled().GetMangledName().AsCString(); |
1811 | const bool extern_c = |
1812 | (Language::LanguageIsC(language: lang) && !Mangled::IsMangledName(name)) || |
1813 | (Language::LanguageIsObjC(language: lang) && |
1814 | !Language::LanguageIsCPlusPlus(language: lang)); |
1815 | |
1816 | if (!extern_c) { |
1817 | TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); |
1818 | if (llvm::isa<TypeSystemClang>(Val: type_system)) { |
1819 | clang::DeclContext *src_decl_context = |
1820 | (clang::DeclContext *)function->GetDeclContext() |
1821 | .GetOpaqueDeclContext(); |
1822 | clang::FunctionDecl *src_function_decl = |
1823 | llvm::dyn_cast_or_null<clang::FunctionDecl>(Val: src_decl_context); |
1824 | if (src_function_decl && |
1825 | src_function_decl->getTemplateSpecializationInfo()) { |
1826 | clang::FunctionTemplateDecl *function_template = |
1827 | src_function_decl->getTemplateSpecializationInfo()->getTemplate(); |
1828 | clang::FunctionTemplateDecl *copied_function_template = |
1829 | llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>( |
1830 | Val: CopyDecl(function_template)); |
1831 | if (copied_function_template) { |
1832 | if (log) { |
1833 | StreamString ss; |
1834 | |
1835 | function->DumpSymbolContext(s: &ss); |
1836 | |
1837 | LLDB_LOG(log, |
1838 | " CEDM::FEVD Imported decl for function template" |
1839 | " {0} (description {1}), returned\n{2}" , |
1840 | copied_function_template->getNameAsString(), |
1841 | ss.GetData(), |
1842 | ClangUtil::DumpDecl(copied_function_template)); |
1843 | } |
1844 | |
1845 | context.AddNamedDecl(copied_function_template); |
1846 | } |
1847 | } else if (src_function_decl) { |
1848 | if (clang::FunctionDecl *copied_function_decl = |
1849 | llvm::dyn_cast_or_null<clang::FunctionDecl>( |
1850 | Val: CopyDecl(src_function_decl))) { |
1851 | if (log) { |
1852 | StreamString ss; |
1853 | |
1854 | function->DumpSymbolContext(s: &ss); |
1855 | |
1856 | LLDB_LOG(log, |
1857 | " CEDM::FEVD Imported decl for function {0} " |
1858 | "(description {1}), returned\n{2}" , |
1859 | copied_function_decl->getNameAsString(), ss.GetData(), |
1860 | ClangUtil::DumpDecl(copied_function_decl)); |
1861 | } |
1862 | |
1863 | context.AddNamedDecl(copied_function_decl); |
1864 | return; |
1865 | } else { |
1866 | LLDB_LOG(log, " Failed to import the function decl for '{0}'" , |
1867 | src_function_decl->getName()); |
1868 | } |
1869 | } |
1870 | } |
1871 | } |
1872 | |
1873 | if (!function_type) { |
1874 | LLDB_LOG(log, " Skipped a function because it has no type" ); |
1875 | return; |
1876 | } |
1877 | |
1878 | function_clang_type = function_type->GetFullCompilerType(); |
1879 | |
1880 | if (!function_clang_type) { |
1881 | LLDB_LOG(log, " Skipped a function because it has no Clang type" ); |
1882 | return; |
1883 | } |
1884 | |
1885 | fun_address = function->GetAddress(); |
1886 | |
1887 | CompilerType copied_function_type = GuardedCopyType(src_type: function_clang_type); |
1888 | if (copied_function_type) { |
1889 | function_decl = context.AddFunDecl(type: copied_function_type, extern_c); |
1890 | |
1891 | if (!function_decl) { |
1892 | LLDB_LOG(log, " Failed to create a function decl for '{0}' ({1:x})" , |
1893 | function_type->GetName(), function_type->GetID()); |
1894 | |
1895 | return; |
1896 | } |
1897 | } else { |
1898 | // We failed to copy the type we found |
1899 | LLDB_LOG(log, |
1900 | " Failed to import the function type '{0}' ({1:x})" |
1901 | " into the expression parser AST context" , |
1902 | function_type->GetName(), function_type->GetID()); |
1903 | |
1904 | return; |
1905 | } |
1906 | } else if (symbol) { |
1907 | fun_address = symbol->GetAddress(); |
1908 | function_decl = context.AddGenericFunDecl(); |
1909 | is_indirect_function = symbol->IsIndirect(); |
1910 | } else { |
1911 | LLDB_LOG(log, " AddOneFunction called with no function and no symbol" ); |
1912 | return; |
1913 | } |
1914 | |
1915 | Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); |
1916 | |
1917 | lldb::addr_t load_addr = |
1918 | fun_address.GetCallableLoadAddress(target, is_indirect: is_indirect_function); |
1919 | |
1920 | ClangExpressionVariable *entity(new ClangExpressionVariable( |
1921 | m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), |
1922 | m_parser_vars->m_target_info.byte_order, |
1923 | m_parser_vars->m_target_info.address_byte_size)); |
1924 | m_found_entities.AddNewlyConstructedVariable(var: entity); |
1925 | |
1926 | std::string decl_name(context.m_decl_name.getAsString()); |
1927 | entity->SetName(ConstString(decl_name.c_str())); |
1928 | entity->SetCompilerType(function_clang_type); |
1929 | entity->EnableParserVars(parser_id: GetParserID()); |
1930 | |
1931 | ClangExpressionVariable::ParserVars *parser_vars = |
1932 | entity->GetParserVars(parser_id: GetParserID()); |
1933 | |
1934 | if (load_addr != LLDB_INVALID_ADDRESS) { |
1935 | parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress); |
1936 | parser_vars->m_lldb_value.GetScalar() = load_addr; |
1937 | } else { |
1938 | // We have to try finding a file address. |
1939 | |
1940 | lldb::addr_t file_addr = fun_address.GetFileAddress(); |
1941 | |
1942 | parser_vars->m_lldb_value.SetValueType(Value::ValueType::FileAddress); |
1943 | parser_vars->m_lldb_value.GetScalar() = file_addr; |
1944 | } |
1945 | |
1946 | parser_vars->m_named_decl = function_decl; |
1947 | parser_vars->m_llvm_value = nullptr; |
1948 | |
1949 | if (log) { |
1950 | StreamString ss; |
1951 | |
1952 | fun_address.Dump(s: &ss, |
1953 | exe_scope: m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), |
1954 | style: Address::DumpStyleResolvedDescription); |
1955 | |
1956 | LLDB_LOG(log, |
1957 | " CEDM::FEVD Found {0} function {1} (description {2}), " |
1958 | "returned\n{3}" , |
1959 | (function ? "specific" : "generic" ), decl_name, ss.GetData(), |
1960 | ClangUtil::DumpDecl(function_decl)); |
1961 | } |
1962 | } |
1963 | |
1964 | void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, |
1965 | const TypeFromUser &ut) { |
1966 | CompilerType copied_clang_type = GuardedCopyType(src_type: ut); |
1967 | |
1968 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1969 | |
1970 | if (!copied_clang_type) { |
1971 | LLDB_LOG(log, |
1972 | "ClangExpressionDeclMap::AddThisType - Couldn't import the type" ); |
1973 | |
1974 | return; |
1975 | } |
1976 | |
1977 | if (copied_clang_type.IsAggregateType() && |
1978 | copied_clang_type.GetCompleteType()) { |
1979 | CompilerType void_clang_type = |
1980 | m_clang_ast_context->GetBasicType(type: eBasicTypeVoid); |
1981 | std::array<CompilerType, 1> args{void_clang_type.GetPointerType()}; |
1982 | |
1983 | CompilerType method_type = m_clang_ast_context->CreateFunctionType( |
1984 | result_type: void_clang_type, args, is_variadic: false, type_quals: 0); |
1985 | |
1986 | const bool is_virtual = false; |
1987 | const bool is_static = false; |
1988 | const bool is_inline = false; |
1989 | const bool is_explicit = false; |
1990 | const bool is_attr_used = true; |
1991 | const bool is_artificial = false; |
1992 | |
1993 | CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType( |
1994 | type: copied_clang_type.GetOpaqueQualType(), name: "$__lldb_expr" , mangled_name: nullptr, |
1995 | method_type, access: lldb::eAccessPublic, is_virtual, is_static, is_inline, |
1996 | is_explicit, is_attr_used, is_artificial); |
1997 | |
1998 | LLDB_LOG(log, |
1999 | " CEDM::AddThisType Added function $__lldb_expr " |
2000 | "(description {0}) for this type\n{1}" , |
2001 | ClangUtil::ToString(copied_clang_type), |
2002 | ClangUtil::DumpDecl(method_decl)); |
2003 | } |
2004 | |
2005 | if (!copied_clang_type.IsValid()) |
2006 | return; |
2007 | |
2008 | TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo( |
2009 | T: QualType::getFromOpaquePtr(Ptr: copied_clang_type.GetOpaqueQualType())); |
2010 | |
2011 | if (!type_source_info) |
2012 | return; |
2013 | |
2014 | // Construct a typedef type because if "*this" is a templated type we can't |
2015 | // just return ClassTemplateSpecializationDecls in response to name queries. |
2016 | // Using a typedef makes this much more robust. |
2017 | |
2018 | TypedefDecl *typedef_decl = TypedefDecl::Create( |
2019 | *m_ast_context, m_ast_context->getTranslationUnitDecl(), SourceLocation(), |
2020 | SourceLocation(), context.m_decl_name.getAsIdentifierInfo(), |
2021 | type_source_info); |
2022 | |
2023 | if (!typedef_decl) |
2024 | return; |
2025 | |
2026 | context.AddNamedDecl(typedef_decl); |
2027 | } |
2028 | |
2029 | void ClangExpressionDeclMap::AddOneType(NameSearchContext &context, |
2030 | const TypeFromUser &ut) { |
2031 | CompilerType copied_clang_type = GuardedCopyType(src_type: ut); |
2032 | |
2033 | if (!copied_clang_type) { |
2034 | Log *log = GetLog(mask: LLDBLog::Expressions); |
2035 | |
2036 | LLDB_LOG(log, |
2037 | "ClangExpressionDeclMap::AddOneType - Couldn't import the type" ); |
2038 | |
2039 | return; |
2040 | } |
2041 | |
2042 | context.AddTypeDecl(compiler_type: copied_clang_type); |
2043 | } |
2044 | |