xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp (revision 24bb5fcea3ed904bc467217bdaadb5dfc618d5bf)
1 //===-- ClangUtilityFunction.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 "lldb/Host/Config.h"
10 
11 #include "ClangUtilityFunction.h"
12 #include "ClangExpressionDeclMap.h"
13 #include "ClangExpressionParser.h"
14 #include "ClangExpressionSourceCode.h"
15 #include "ClangPersistentVariables.h"
16 
17 #include <stdio.h>
18 #if HAVE_SYS_TYPES_H
19 #include <sys/types.h>
20 #endif
21 
22 
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/StreamFile.h"
25 #include "lldb/Expression/IRExecutionUnit.h"
26 #include "lldb/Host/Host.h"
27 #include "lldb/Target/ExecutionContext.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/ConstString.h"
30 #include "lldb/Utility/Log.h"
31 #include "lldb/Utility/Stream.h"
32 
33 using namespace lldb_private;
34 
35 char ClangUtilityFunction::ID;
36 
37 /// Constructor
38 ///
39 /// \param[in] text
40 ///     The text of the function.  Must be a full translation unit.
41 ///
42 /// \param[in] name
43 ///     The name of the function, as used in the text.
44 ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
45                                            const char *text, const char *name)
46     : UtilityFunction(exe_scope, text, name) {
47   m_function_text.assign(ClangExpressionSourceCode::g_expression_prefix);
48   if (text && text[0])
49     m_function_text.append(text);
50 }
51 
52 ClangUtilityFunction::~ClangUtilityFunction() {}
53 
54 /// Install the utility function into a process
55 ///
56 /// \param[in] diagnostic_manager
57 ///     A diagnostic manager to report errors and warnings to.
58 ///
59 /// \param[in] exe_ctx
60 ///     The execution context to install the utility function to.
61 ///
62 /// \return
63 ///     True on success (no errors); false otherwise.
64 bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
65                                    ExecutionContext &exe_ctx) {
66   if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
67     diagnostic_manager.PutString(eDiagnosticSeverityWarning,
68                                  "already installed");
69     return false;
70   }
71 
72   ////////////////////////////////////
73   // Set up the target and compiler
74   //
75 
76   Target *target = exe_ctx.GetTargetPtr();
77 
78   if (!target) {
79     diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
80     return false;
81   }
82 
83   Process *process = exe_ctx.GetProcessPtr();
84 
85   if (!process) {
86     diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid process");
87     return false;
88   }
89 
90   //////////////////////////
91   // Parse the expression
92   //
93 
94   bool keep_result_in_memory = false;
95 
96   ResetDeclMap(exe_ctx, keep_result_in_memory);
97 
98   if (!DeclMap()->WillParse(exe_ctx, nullptr)) {
99     diagnostic_manager.PutString(
100         eDiagnosticSeverityError,
101         "current process state is unsuitable for expression parsing");
102     return false;
103   }
104 
105   const bool generate_debug_info = true;
106   ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
107                                generate_debug_info);
108 
109   unsigned num_errors = parser.Parse(diagnostic_manager);
110 
111   if (num_errors) {
112     ResetDeclMap();
113 
114     return false;
115   }
116 
117   //////////////////////////////////
118   // JIT the output of the parser
119   //
120 
121   bool can_interpret = false; // should stay that way
122 
123   Status jit_error = parser.PrepareForExecution(
124       m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
125       can_interpret, eExecutionPolicyAlways);
126 
127   if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
128     m_jit_process_wp = process->shared_from_this();
129     if (parser.GetGenerateDebugInfo()) {
130       lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
131 
132       if (jit_module_sp) {
133         ConstString const_func_name(FunctionName());
134         FileSpec jit_file;
135         jit_file.GetFilename() = const_func_name;
136         jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
137         m_jit_module_wp = jit_module_sp;
138         target->GetImages().Append(jit_module_sp);
139       }
140     }
141   }
142 
143   DeclMap()->DidParse();
144 
145   ResetDeclMap();
146 
147   if (jit_error.Success()) {
148     return true;
149   } else {
150     const char *error_cstr = jit_error.AsCString();
151     if (error_cstr && error_cstr[0]) {
152       diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
153     } else {
154       diagnostic_manager.PutString(eDiagnosticSeverityError,
155                                    "expression can't be interpreted or run");
156     }
157     return false;
158   }
159 }
160 
161 void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
162     ExecutionContext &exe_ctx, bool keep_result_in_memory) {
163   std::shared_ptr<ClangASTImporter> ast_importer;
164   auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
165       lldb::eLanguageTypeC);
166   if (state) {
167     auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
168     ast_importer = persistent_vars->GetClangASTImporter();
169   }
170   m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
171       keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(), ast_importer,
172       nullptr);
173 }
174