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