Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
39648 views
1
//===-- ClangUserExpression.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 <cstdio>
10
#include <sys/types.h>
11
12
#include <cstdlib>
13
#include <map>
14
#include <string>
15
16
#include "ClangUserExpression.h"
17
18
#include "ASTResultSynthesizer.h"
19
#include "ClangASTMetadata.h"
20
#include "ClangDiagnostic.h"
21
#include "ClangExpressionDeclMap.h"
22
#include "ClangExpressionParser.h"
23
#include "ClangModulesDeclVendor.h"
24
#include "ClangPersistentVariables.h"
25
#include "CppModuleConfiguration.h"
26
27
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
28
#include "lldb/Core/Debugger.h"
29
#include "lldb/Core/Module.h"
30
#include "lldb/Core/ValueObjectConstResult.h"
31
#include "lldb/Expression/ExpressionSourceCode.h"
32
#include "lldb/Expression/IRExecutionUnit.h"
33
#include "lldb/Expression/IRInterpreter.h"
34
#include "lldb/Expression/Materializer.h"
35
#include "lldb/Host/HostInfo.h"
36
#include "lldb/Symbol/Block.h"
37
#include "lldb/Symbol/CompileUnit.h"
38
#include "lldb/Symbol/Function.h"
39
#include "lldb/Symbol/ObjectFile.h"
40
#include "lldb/Symbol/SymbolFile.h"
41
#include "lldb/Symbol/SymbolVendor.h"
42
#include "lldb/Symbol/Type.h"
43
#include "lldb/Symbol/VariableList.h"
44
#include "lldb/Target/ExecutionContext.h"
45
#include "lldb/Target/Process.h"
46
#include "lldb/Target/StackFrame.h"
47
#include "lldb/Target/Target.h"
48
#include "lldb/Target/ThreadPlan.h"
49
#include "lldb/Target/ThreadPlanCallUserExpression.h"
50
#include "lldb/Utility/ConstString.h"
51
#include "lldb/Utility/LLDBLog.h"
52
#include "lldb/Utility/Log.h"
53
#include "lldb/Utility/StreamString.h"
54
55
#include "clang/AST/DeclCXX.h"
56
#include "clang/AST/DeclObjC.h"
57
58
#include "llvm/ADT/ScopeExit.h"
59
#include "llvm/BinaryFormat/Dwarf.h"
60
61
using namespace lldb_private;
62
63
char ClangUserExpression::ID;
64
65
ClangUserExpression::ClangUserExpression(
66
ExecutionContextScope &exe_scope, llvm::StringRef expr,
67
llvm::StringRef prefix, SourceLanguage language, ResultType desired_type,
68
const EvaluateExpressionOptions &options, ValueObject *ctx_obj)
69
: LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
70
options),
71
m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
72
eExecutionPolicyTopLevel),
73
m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
74
switch (m_language.name) {
75
case llvm::dwarf::DW_LNAME_C_plus_plus:
76
m_allow_cxx = true;
77
break;
78
case llvm::dwarf::DW_LNAME_ObjC:
79
m_allow_objc = true;
80
break;
81
case llvm::dwarf::DW_LNAME_ObjC_plus_plus:
82
default:
83
m_allow_cxx = true;
84
m_allow_objc = true;
85
break;
86
}
87
}
88
89
ClangUserExpression::~ClangUserExpression() = default;
90
91
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
92
Log *log = GetLog(LLDBLog::Expressions);
93
94
LLDB_LOGF(log, "ClangUserExpression::ScanContext()");
95
96
m_target = exe_ctx.GetTargetPtr();
97
98
if (!(m_allow_cxx || m_allow_objc)) {
99
LLDB_LOGF(log, " [CUE::SC] Settings inhibit C++ and Objective-C");
100
return;
101
}
102
103
StackFrame *frame = exe_ctx.GetFramePtr();
104
if (frame == nullptr) {
105
LLDB_LOGF(log, " [CUE::SC] Null stack frame");
106
return;
107
}
108
109
SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
110
lldb::eSymbolContextBlock);
111
112
if (!sym_ctx.function) {
113
LLDB_LOGF(log, " [CUE::SC] Null function");
114
return;
115
}
116
117
// Find the block that defines the function represented by "sym_ctx"
118
Block *function_block = sym_ctx.GetFunctionBlock();
119
120
if (!function_block) {
121
LLDB_LOGF(log, " [CUE::SC] Null function block");
122
return;
123
}
124
125
CompilerDeclContext decl_context = function_block->GetDeclContext();
126
127
if (!decl_context) {
128
LLDB_LOGF(log, " [CUE::SC] Null decl context");
129
return;
130
}
131
132
if (m_ctx_obj) {
133
switch (m_ctx_obj->GetObjectRuntimeLanguage()) {
134
case lldb::eLanguageTypeC:
135
case lldb::eLanguageTypeC89:
136
case lldb::eLanguageTypeC99:
137
case lldb::eLanguageTypeC11:
138
case lldb::eLanguageTypeC_plus_plus:
139
case lldb::eLanguageTypeC_plus_plus_03:
140
case lldb::eLanguageTypeC_plus_plus_11:
141
case lldb::eLanguageTypeC_plus_plus_14:
142
m_in_cplusplus_method = true;
143
break;
144
case lldb::eLanguageTypeObjC:
145
case lldb::eLanguageTypeObjC_plus_plus:
146
m_in_objectivec_method = true;
147
break;
148
default:
149
break;
150
}
151
m_needs_object_ptr = true;
152
} else if (clang::CXXMethodDecl *method_decl =
153
TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {
154
if (m_allow_cxx && method_decl->isInstance()) {
155
if (m_enforce_valid_object) {
156
lldb::VariableListSP variable_list_sp(
157
function_block->GetBlockVariableList(true));
158
159
const char *thisErrorString = "Stopped in a C++ method, but 'this' "
160
"isn't available; pretending we are in a "
161
"generic context";
162
163
if (!variable_list_sp) {
164
err.SetErrorString(thisErrorString);
165
return;
166
}
167
168
lldb::VariableSP this_var_sp(
169
variable_list_sp->FindVariable(ConstString("this")));
170
171
if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
172
!this_var_sp->LocationIsValidForFrame(frame)) {
173
err.SetErrorString(thisErrorString);
174
return;
175
}
176
}
177
178
m_in_cplusplus_method = true;
179
m_needs_object_ptr = true;
180
}
181
} else if (clang::ObjCMethodDecl *method_decl =
182
TypeSystemClang::DeclContextGetAsObjCMethodDecl(
183
decl_context)) {
184
if (m_allow_objc) {
185
if (m_enforce_valid_object) {
186
lldb::VariableListSP variable_list_sp(
187
function_block->GetBlockVariableList(true));
188
189
const char *selfErrorString = "Stopped in an Objective-C method, but "
190
"'self' isn't available; pretending we "
191
"are in a generic context";
192
193
if (!variable_list_sp) {
194
err.SetErrorString(selfErrorString);
195
return;
196
}
197
198
lldb::VariableSP self_variable_sp =
199
variable_list_sp->FindVariable(ConstString("self"));
200
201
if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
202
!self_variable_sp->LocationIsValidForFrame(frame)) {
203
err.SetErrorString(selfErrorString);
204
return;
205
}
206
}
207
208
m_in_objectivec_method = true;
209
m_needs_object_ptr = true;
210
211
if (!method_decl->isInstanceMethod())
212
m_in_static_method = true;
213
}
214
} else if (clang::FunctionDecl *function_decl =
215
TypeSystemClang::DeclContextGetAsFunctionDecl(decl_context)) {
216
// We might also have a function that said in the debug information that it
217
// captured an object pointer. The best way to deal with getting to the
218
// ivars at present is by pretending that this is a method of a class in
219
// whatever runtime the debug info says the object pointer belongs to. Do
220
// that here.
221
222
ClangASTMetadata *metadata =
223
TypeSystemClang::DeclContextGetMetaData(decl_context, function_decl);
224
if (metadata && metadata->HasObjectPtr()) {
225
lldb::LanguageType language = metadata->GetObjectPtrLanguage();
226
if (language == lldb::eLanguageTypeC_plus_plus) {
227
if (m_enforce_valid_object) {
228
lldb::VariableListSP variable_list_sp(
229
function_block->GetBlockVariableList(true));
230
231
const char *thisErrorString = "Stopped in a context claiming to "
232
"capture a C++ object pointer, but "
233
"'this' isn't available; pretending we "
234
"are in a generic context";
235
236
if (!variable_list_sp) {
237
err.SetErrorString(thisErrorString);
238
return;
239
}
240
241
lldb::VariableSP this_var_sp(
242
variable_list_sp->FindVariable(ConstString("this")));
243
244
if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
245
!this_var_sp->LocationIsValidForFrame(frame)) {
246
err.SetErrorString(thisErrorString);
247
return;
248
}
249
}
250
251
m_in_cplusplus_method = true;
252
m_needs_object_ptr = true;
253
} else if (language == lldb::eLanguageTypeObjC) {
254
if (m_enforce_valid_object) {
255
lldb::VariableListSP variable_list_sp(
256
function_block->GetBlockVariableList(true));
257
258
const char *selfErrorString =
259
"Stopped in a context claiming to capture an Objective-C object "
260
"pointer, but 'self' isn't available; pretending we are in a "
261
"generic context";
262
263
if (!variable_list_sp) {
264
err.SetErrorString(selfErrorString);
265
return;
266
}
267
268
lldb::VariableSP self_variable_sp =
269
variable_list_sp->FindVariable(ConstString("self"));
270
271
if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
272
!self_variable_sp->LocationIsValidForFrame(frame)) {
273
err.SetErrorString(selfErrorString);
274
return;
275
}
276
277
Type *self_type = self_variable_sp->GetType();
278
279
if (!self_type) {
280
err.SetErrorString(selfErrorString);
281
return;
282
}
283
284
CompilerType self_clang_type = self_type->GetForwardCompilerType();
285
286
if (!self_clang_type) {
287
err.SetErrorString(selfErrorString);
288
return;
289
}
290
291
if (TypeSystemClang::IsObjCClassType(self_clang_type)) {
292
return;
293
} else if (TypeSystemClang::IsObjCObjectPointerType(
294
self_clang_type)) {
295
m_in_objectivec_method = true;
296
m_needs_object_ptr = true;
297
} else {
298
err.SetErrorString(selfErrorString);
299
return;
300
}
301
} else {
302
m_in_objectivec_method = true;
303
m_needs_object_ptr = true;
304
}
305
}
306
}
307
}
308
}
309
310
// This is a really nasty hack, meant to fix Objective-C expressions of the
311
// form (int)[myArray count]. Right now, because the type information for
312
// count is not available, [myArray count] returns id, which can't be directly
313
// cast to int without causing a clang error.
314
static void ApplyObjcCastHack(std::string &expr) {
315
const std::string from = "(int)[";
316
const std::string to = "(int)(long long)[";
317
318
size_t offset;
319
320
while ((offset = expr.find(from)) != expr.npos)
321
expr.replace(offset, from.size(), to);
322
}
323
324
bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
325
ExecutionContext &exe_ctx) {
326
if (Target *target = exe_ctx.GetTargetPtr()) {
327
if (PersistentExpressionState *persistent_state =
328
target->GetPersistentExpressionStateForLanguage(
329
lldb::eLanguageTypeC)) {
330
m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);
331
m_result_delegate.RegisterPersistentState(persistent_state);
332
} else {
333
diagnostic_manager.PutString(
334
lldb::eSeverityError, "couldn't start parsing (no persistent data)");
335
return false;
336
}
337
} else {
338
diagnostic_manager.PutString(lldb::eSeverityError,
339
"error: couldn't start parsing (no target)");
340
return false;
341
}
342
return true;
343
}
344
345
static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
346
DiagnosticManager &diagnostic_manager) {
347
if (!target->GetEnableAutoImportClangModules())
348
return;
349
350
auto *persistent_state = llvm::cast<ClangPersistentVariables>(
351
target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
352
if (!persistent_state)
353
return;
354
355
std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
356
persistent_state->GetClangModulesDeclVendor();
357
if (!decl_vendor)
358
return;
359
360
StackFrame *frame = exe_ctx.GetFramePtr();
361
if (!frame)
362
return;
363
364
Block *block = frame->GetFrameBlock();
365
if (!block)
366
return;
367
SymbolContext sc;
368
369
block->CalculateSymbolContext(&sc);
370
371
if (!sc.comp_unit)
372
return;
373
StreamString error_stream;
374
375
ClangModulesDeclVendor::ModuleVector modules_for_macros =
376
persistent_state->GetHandLoadedClangModules();
377
if (decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros,
378
error_stream))
379
return;
380
381
// Failed to load some modules, so emit the error stream as a diagnostic.
382
if (!error_stream.Empty()) {
383
// The error stream already contains several Clang diagnostics that might
384
// be either errors or warnings, so just print them all as one remark
385
// diagnostic to prevent that the message starts with "error: error:".
386
diagnostic_manager.PutString(lldb::eSeverityInfo, error_stream.GetString());
387
return;
388
}
389
390
diagnostic_manager.PutString(lldb::eSeverityError,
391
"Unknown error while loading modules needed for "
392
"current compilation unit.");
393
}
394
395
ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {
396
assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&
397
"Top level expressions aren't wrapped.");
398
using Kind = ClangExpressionSourceCode::WrapKind;
399
if (m_in_cplusplus_method)
400
return Kind::CppMemberFunction;
401
else if (m_in_objectivec_method) {
402
if (m_in_static_method)
403
return Kind::ObjCStaticMethod;
404
return Kind::ObjCInstanceMethod;
405
}
406
// Not in any kind of 'special' function, so just wrap it in a normal C
407
// function.
408
return Kind::Function;
409
}
410
411
void ClangUserExpression::CreateSourceCode(
412
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
413
std::vector<std::string> modules_to_import, bool for_completion) {
414
415
std::string prefix = m_expr_prefix;
416
417
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
418
m_transformed_text = m_expr_text;
419
} else {
420
m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(
421
m_filename, prefix, m_expr_text, GetWrapKind()));
422
423
if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj,
424
for_completion, modules_to_import)) {
425
diagnostic_manager.PutString(lldb::eSeverityError,
426
"couldn't construct expression body");
427
return;
428
}
429
430
// Find and store the start position of the original code inside the
431
// transformed code. We need this later for the code completion.
432
std::size_t original_start;
433
std::size_t original_end;
434
bool found_bounds = m_source_code->GetOriginalBodyBounds(
435
m_transformed_text, original_start, original_end);
436
if (found_bounds)
437
m_user_expression_start_pos = original_start;
438
}
439
}
440
441
static bool SupportsCxxModuleImport(lldb::LanguageType language) {
442
switch (language) {
443
case lldb::eLanguageTypeC_plus_plus:
444
case lldb::eLanguageTypeC_plus_plus_03:
445
case lldb::eLanguageTypeC_plus_plus_11:
446
case lldb::eLanguageTypeC_plus_plus_14:
447
case lldb::eLanguageTypeObjC_plus_plus:
448
return true;
449
default:
450
return false;
451
}
452
}
453
454
/// Utility method that puts a message into the expression log and
455
/// returns an invalid module configuration.
456
static CppModuleConfiguration LogConfigError(const std::string &msg) {
457
Log *log = GetLog(LLDBLog::Expressions);
458
LLDB_LOG(log, "[C++ module config] {0}", msg);
459
return CppModuleConfiguration();
460
}
461
462
CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
463
ExecutionContext &exe_ctx) {
464
Log *log = GetLog(LLDBLog::Expressions);
465
466
// Don't do anything if this is not a C++ module configuration.
467
if (!SupportsCxxModuleImport(language))
468
return LogConfigError("Language doesn't support C++ modules");
469
470
Target *target = exe_ctx.GetTargetPtr();
471
if (!target)
472
return LogConfigError("No target");
473
474
StackFrame *frame = exe_ctx.GetFramePtr();
475
if (!frame)
476
return LogConfigError("No frame");
477
478
Block *block = frame->GetFrameBlock();
479
if (!block)
480
return LogConfigError("No block");
481
482
SymbolContext sc;
483
block->CalculateSymbolContext(&sc);
484
if (!sc.comp_unit)
485
return LogConfigError("Couldn't calculate symbol context");
486
487
// Build a list of files we need to analyze to build the configuration.
488
FileSpecList files;
489
for (auto &f : sc.comp_unit->GetSupportFiles())
490
files.AppendIfUnique(f->Materialize());
491
// We also need to look at external modules in the case of -gmodules as they
492
// contain the support files for libc++ and the C library.
493
llvm::DenseSet<SymbolFile *> visited_symbol_files;
494
sc.comp_unit->ForEachExternalModule(
495
visited_symbol_files, [&files](Module &module) {
496
for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
497
const SupportFileList &support_files =
498
module.GetCompileUnitAtIndex(i)->GetSupportFiles();
499
for (auto &f : support_files) {
500
files.AppendIfUnique(f->Materialize());
501
}
502
}
503
return false;
504
});
505
506
LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
507
files.GetSize());
508
if (log && log->GetVerbose()) {
509
for (auto &f : files)
510
LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",
511
f.GetPath());
512
}
513
514
// Try to create a configuration from the files. If there is no valid
515
// configuration possible with the files, this just returns an invalid
516
// configuration.
517
return CppModuleConfiguration(files, target->GetArchitecture().GetTriple());
518
}
519
520
bool ClangUserExpression::PrepareForParsing(
521
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
522
bool for_completion) {
523
InstallContext(exe_ctx);
524
525
if (!SetupPersistentState(diagnostic_manager, exe_ctx))
526
return false;
527
528
Status err;
529
ScanContext(exe_ctx, err);
530
531
if (!err.Success()) {
532
diagnostic_manager.PutString(lldb::eSeverityWarning, err.AsCString());
533
}
534
535
////////////////////////////////////
536
// Generate the expression
537
//
538
539
ApplyObjcCastHack(m_expr_text);
540
541
SetupDeclVendor(exe_ctx, m_target, diagnostic_manager);
542
543
m_filename = m_clang_state->GetNextExprFileName();
544
545
if (m_target->GetImportStdModule() == eImportStdModuleTrue)
546
SetupCppModuleImports(exe_ctx);
547
548
CreateSourceCode(diagnostic_manager, exe_ctx, m_imported_cpp_modules,
549
for_completion);
550
return true;
551
}
552
553
bool ClangUserExpression::TryParse(
554
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
555
lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory,
556
bool generate_debug_info) {
557
m_materializer_up = std::make_unique<Materializer>();
558
559
ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
560
561
auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
562
563
if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
564
diagnostic_manager.PutString(
565
lldb::eSeverityError,
566
"current process state is unsuitable for expression parsing");
567
return false;
568
}
569
570
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
571
DeclMap()->SetLookupsEnabled(true);
572
}
573
574
m_parser = std::make_unique<ClangExpressionParser>(
575
exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info,
576
m_include_directories, m_filename);
577
578
unsigned num_errors = m_parser->Parse(diagnostic_manager);
579
580
// Check here for FixItHints. If there are any try to apply the fixits and
581
// set the fixed text in m_fixed_text before returning an error.
582
if (num_errors) {
583
if (diagnostic_manager.HasFixIts()) {
584
if (m_parser->RewriteExpression(diagnostic_manager)) {
585
size_t fixed_start;
586
size_t fixed_end;
587
m_fixed_text = diagnostic_manager.GetFixedExpression();
588
// Retrieve the original expression in case we don't have a top level
589
// expression (which has no surrounding source code).
590
if (m_source_code && m_source_code->GetOriginalBodyBounds(
591
m_fixed_text, fixed_start, fixed_end))
592
m_fixed_text =
593
m_fixed_text.substr(fixed_start, fixed_end - fixed_start);
594
}
595
}
596
return false;
597
}
598
599
//////////////////////////////////////////////////////////////////////////////
600
// Prepare the output of the parser for execution, evaluating it statically
601
// if possible
602
//
603
604
{
605
Status jit_error = m_parser->PrepareForExecution(
606
m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
607
m_can_interpret, execution_policy);
608
609
if (!jit_error.Success()) {
610
const char *error_cstr = jit_error.AsCString();
611
if (error_cstr && error_cstr[0])
612
diagnostic_manager.PutString(lldb::eSeverityError, error_cstr);
613
else
614
diagnostic_manager.PutString(lldb::eSeverityError,
615
"expression can't be interpreted or run");
616
return false;
617
}
618
}
619
return true;
620
}
621
622
void ClangUserExpression::SetupCppModuleImports(ExecutionContext &exe_ctx) {
623
Log *log = GetLog(LLDBLog::Expressions);
624
625
CppModuleConfiguration module_config =
626
GetModuleConfig(m_language.AsLanguageType(), exe_ctx);
627
m_imported_cpp_modules = module_config.GetImportedModules();
628
m_include_directories = module_config.GetIncludeDirs();
629
630
LLDB_LOG(log, "List of imported modules in expression: {0}",
631
llvm::make_range(m_imported_cpp_modules.begin(),
632
m_imported_cpp_modules.end()));
633
LLDB_LOG(log, "List of include directories gathered for modules: {0}",
634
llvm::make_range(m_include_directories.begin(),
635
m_include_directories.end()));
636
}
637
638
static bool shouldRetryWithCppModule(Target &target, ExecutionPolicy exe_policy) {
639
// Top-level expression don't yet support importing C++ modules.
640
if (exe_policy == ExecutionPolicy::eExecutionPolicyTopLevel)
641
return false;
642
return target.GetImportStdModule() == eImportStdModuleFallback;
643
}
644
645
bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
646
ExecutionContext &exe_ctx,
647
lldb_private::ExecutionPolicy execution_policy,
648
bool keep_result_in_memory,
649
bool generate_debug_info) {
650
Log *log = GetLog(LLDBLog::Expressions);
651
652
if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
653
return false;
654
655
LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
656
657
////////////////////////////////////
658
// Set up the target and compiler
659
//
660
661
Target *target = exe_ctx.GetTargetPtr();
662
663
if (!target) {
664
diagnostic_manager.PutString(lldb::eSeverityError, "invalid target");
665
return false;
666
}
667
668
//////////////////////////
669
// Parse the expression
670
//
671
672
bool parse_success = TryParse(diagnostic_manager, exe_ctx, execution_policy,
673
keep_result_in_memory, generate_debug_info);
674
// If the expression failed to parse, check if retrying parsing with a loaded
675
// C++ module is possible.
676
if (!parse_success && shouldRetryWithCppModule(*target, execution_policy)) {
677
// Load the loaded C++ modules.
678
SetupCppModuleImports(exe_ctx);
679
// If we did load any modules, then retry parsing.
680
if (!m_imported_cpp_modules.empty()) {
681
// Create a dedicated diagnostic manager for the second parse attempt.
682
// These diagnostics are only returned to the caller if using the fallback
683
// actually succeeded in getting the expression to parse. This prevents
684
// that module-specific issues regress diagnostic quality with the
685
// fallback mode.
686
DiagnosticManager retry_manager;
687
// The module imports are injected into the source code wrapper,
688
// so recreate those.
689
CreateSourceCode(retry_manager, exe_ctx, m_imported_cpp_modules,
690
/*for_completion*/ false);
691
parse_success = TryParse(retry_manager, exe_ctx, execution_policy,
692
keep_result_in_memory, generate_debug_info);
693
// Return the parse diagnostics if we were successful.
694
if (parse_success)
695
diagnostic_manager = std::move(retry_manager);
696
}
697
}
698
if (!parse_success)
699
return false;
700
701
if (m_execution_unit_sp) {
702
bool register_execution_unit = false;
703
704
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
705
register_execution_unit = true;
706
}
707
708
// If there is more than one external function in the execution unit, it
709
// needs to keep living even if it's not top level, because the result
710
// could refer to that function.
711
712
if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
713
register_execution_unit = true;
714
}
715
716
if (register_execution_unit) {
717
if (auto *persistent_state =
718
exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
719
m_language.AsLanguageType()))
720
persistent_state->RegisterExecutionUnit(m_execution_unit_sp);
721
}
722
}
723
724
if (generate_debug_info) {
725
lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
726
727
if (jit_module_sp) {
728
ConstString const_func_name(FunctionName());
729
FileSpec jit_file;
730
jit_file.SetFilename(const_func_name);
731
jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
732
m_jit_module_wp = jit_module_sp;
733
target->GetImages().Append(jit_module_sp);
734
}
735
}
736
737
Process *process = exe_ctx.GetProcessPtr();
738
if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
739
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
740
return true;
741
}
742
743
/// Converts an absolute position inside a given code string into
744
/// a column/line pair.
745
///
746
/// \param[in] abs_pos
747
/// A absolute position in the code string that we want to convert
748
/// to a column/line pair.
749
///
750
/// \param[in] code
751
/// A multi-line string usually representing source code.
752
///
753
/// \param[out] line
754
/// The line in the code that contains the given absolute position.
755
/// The first line in the string is indexed as 1.
756
///
757
/// \param[out] column
758
/// The column in the line that contains the absolute position.
759
/// The first character in a line is indexed as 0.
760
static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,
761
unsigned &line, unsigned &column) {
762
// Reset to code position to beginning of the file.
763
line = 0;
764
column = 0;
765
766
assert(abs_pos <= code.size() && "Absolute position outside code string?");
767
768
// We have to walk up to the position and count lines/columns.
769
for (std::size_t i = 0; i < abs_pos; ++i) {
770
// If we hit a line break, we go back to column 0 and enter a new line.
771
// We only handle \n because that's what we internally use to make new
772
// lines for our temporary code strings.
773
if (code[i] == '\n') {
774
++line;
775
column = 0;
776
continue;
777
}
778
++column;
779
}
780
}
781
782
bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
783
CompletionRequest &request,
784
unsigned complete_pos) {
785
Log *log = GetLog(LLDBLog::Expressions);
786
787
// We don't want any visible feedback when completing an expression. Mostly
788
// because the results we get from an incomplete invocation are probably not
789
// correct.
790
DiagnosticManager diagnostic_manager;
791
792
if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
793
return false;
794
795
LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
796
797
//////////////////////////
798
// Parse the expression
799
//
800
801
m_materializer_up = std::make_unique<Materializer>();
802
803
ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);
804
805
auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
806
807
if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
808
diagnostic_manager.PutString(
809
lldb::eSeverityError,
810
"current process state is unsuitable for expression parsing");
811
812
return false;
813
}
814
815
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
816
DeclMap()->SetLookupsEnabled(true);
817
}
818
819
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
820
false);
821
822
// We have to find the source code location where the user text is inside
823
// the transformed expression code. When creating the transformed text, we
824
// already stored the absolute position in the m_transformed_text string. The
825
// only thing left to do is to transform it into the line:column format that
826
// Clang expects.
827
828
// The line and column of the user expression inside the transformed source
829
// code.
830
unsigned user_expr_line, user_expr_column;
831
if (m_user_expression_start_pos)
832
AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,
833
user_expr_line, user_expr_column);
834
else
835
return false;
836
837
// The actual column where we have to complete is the start column of the
838
// user expression + the offset inside the user code that we were given.
839
const unsigned completion_column = user_expr_column + complete_pos;
840
parser.Complete(request, user_expr_line, completion_column, complete_pos);
841
842
return true;
843
}
844
845
lldb::addr_t ClangUserExpression::GetCppObjectPointer(
846
lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) {
847
auto valobj_sp =
848
GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
849
850
// We're inside a C++ class method. This could potentially be an unnamed
851
// lambda structure. If the lambda captured a "this", that should be
852
// the object pointer.
853
if (auto thisChildSP = valobj_sp->GetChildMemberWithName("this")) {
854
valobj_sp = thisChildSP;
855
}
856
857
if (!err.Success() || !valobj_sp.get())
858
return LLDB_INVALID_ADDRESS;
859
860
lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
861
862
if (ret == LLDB_INVALID_ADDRESS) {
863
err.SetErrorStringWithFormatv(
864
"Couldn't load '{0}' because its value couldn't be evaluated",
865
object_name);
866
return LLDB_INVALID_ADDRESS;
867
}
868
869
return ret;
870
}
871
872
bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
873
std::vector<lldb::addr_t> &args,
874
lldb::addr_t struct_address,
875
DiagnosticManager &diagnostic_manager) {
876
lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
877
lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
878
879
if (m_needs_object_ptr) {
880
lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
881
if (!frame_sp)
882
return true;
883
884
if (!m_in_cplusplus_method && !m_in_objectivec_method) {
885
diagnostic_manager.PutString(
886
lldb::eSeverityError,
887
"need object pointer but don't know the language");
888
return false;
889
}
890
891
static constexpr llvm::StringLiteral g_cplusplus_object_name("this");
892
static constexpr llvm::StringLiteral g_objc_object_name("self");
893
llvm::StringRef object_name =
894
m_in_cplusplus_method ? g_cplusplus_object_name : g_objc_object_name;
895
896
Status object_ptr_error;
897
898
if (m_ctx_obj) {
899
AddressType address_type;
900
object_ptr = m_ctx_obj->GetAddressOf(false, &address_type);
901
if (object_ptr == LLDB_INVALID_ADDRESS ||
902
address_type != eAddressTypeLoad)
903
object_ptr_error.SetErrorString("Can't get context object's "
904
"debuggee address");
905
} else {
906
if (m_in_cplusplus_method) {
907
object_ptr =
908
GetCppObjectPointer(frame_sp, object_name, object_ptr_error);
909
} else {
910
object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
911
}
912
}
913
914
if (!object_ptr_error.Success()) {
915
exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Format(
916
"warning: `{0}' is not accessible (substituting 0). {1}\n",
917
object_name, object_ptr_error.AsCString());
918
object_ptr = 0;
919
}
920
921
if (m_in_objectivec_method) {
922
static constexpr llvm::StringLiteral cmd_name("_cmd");
923
924
cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
925
926
if (!object_ptr_error.Success()) {
927
diagnostic_manager.Printf(
928
lldb::eSeverityWarning,
929
"couldn't get cmd pointer (substituting NULL): %s",
930
object_ptr_error.AsCString());
931
cmd_ptr = 0;
932
}
933
}
934
935
args.push_back(object_ptr);
936
937
if (m_in_objectivec_method)
938
args.push_back(cmd_ptr);
939
940
args.push_back(struct_address);
941
} else {
942
args.push_back(struct_address);
943
}
944
return true;
945
}
946
947
lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(
948
ExecutionContextScope *exe_scope) {
949
return m_result_delegate.GetVariable();
950
}
951
952
char ClangUserExpression::ClangUserExpressionHelper::ID;
953
954
void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
955
ExecutionContext &exe_ctx,
956
Materializer::PersistentVariableDelegate &delegate,
957
bool keep_result_in_memory,
958
ValueObject *ctx_obj) {
959
std::shared_ptr<ClangASTImporter> ast_importer;
960
auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
961
lldb::eLanguageTypeC);
962
if (state) {
963
auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
964
ast_importer = persistent_vars->GetClangASTImporter();
965
}
966
m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
967
keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer,
968
ctx_obj);
969
}
970
971
clang::ASTConsumer *
972
ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(
973
clang::ASTConsumer *passthrough) {
974
m_result_synthesizer_up = std::make_unique<ASTResultSynthesizer>(
975
passthrough, m_top_level, m_target);
976
977
return m_result_synthesizer_up.get();
978
}
979
980
void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
981
if (m_result_synthesizer_up) {
982
m_result_synthesizer_up->CommitPersistentDecls();
983
}
984
}
985
986
ConstString ClangUserExpression::ResultDelegate::GetName() {
987
return m_persistent_state->GetNextPersistentVariableName(false);
988
}
989
990
void ClangUserExpression::ResultDelegate::DidDematerialize(
991
lldb::ExpressionVariableSP &variable) {
992
m_variable = variable;
993
}
994
995
void ClangUserExpression::ResultDelegate::RegisterPersistentState(
996
PersistentExpressionState *persistent_state) {
997
m_persistent_state = persistent_state;
998
}
999
1000
lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() {
1001
return m_variable;
1002
}
1003
1004