1 //===-- ClangUtilityFunction.cpp ---------------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ClangUtilityFunction.h"
11 #include "ClangExpressionDeclMap.h"
12 #include "ClangExpressionParser.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/ExpressionSourceCode.h"
23 #include "lldb/Expression/IRExecutionUnit.h"
24 #include "lldb/Host/Host.h"
25 #include "lldb/Target/ExecutionContext.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Utility/ConstString.h"
28 #include "lldb/Utility/Log.h"
29 #include "lldb/Utility/Stream.h"
30
31 using namespace lldb_private;
32
33 //------------------------------------------------------------------
34 /// Constructor
35 ///
36 /// @param[in] text
37 /// The text of the function. Must be a full translation unit.
38 ///
39 /// @param[in] name
40 /// The name of the function, as used in the text.
41 //------------------------------------------------------------------
ClangUtilityFunction(ExecutionContextScope & exe_scope,const char * text,const char * name)42 ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
43 const char *text, const char *name)
44 : UtilityFunction(exe_scope, text, name) {}
45
~ClangUtilityFunction()46 ClangUtilityFunction::~ClangUtilityFunction() {}
47
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 //------------------------------------------------------------------
Install(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx)60 bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
61 ExecutionContext &exe_ctx) {
62 if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
63 diagnostic_manager.PutString(eDiagnosticSeverityWarning,
64 "already installed");
65 return false;
66 }
67
68 ////////////////////////////////////
69 // Set up the target and compiler
70 //
71
72 Target *target = exe_ctx.GetTargetPtr();
73
74 if (!target) {
75 diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
76 return false;
77 }
78
79 Process *process = exe_ctx.GetProcessPtr();
80
81 if (!process) {
82 diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid process");
83 return false;
84 }
85
86 //////////////////////////
87 // Parse the expression
88 //
89
90 bool keep_result_in_memory = false;
91
92 ResetDeclMap(exe_ctx, keep_result_in_memory);
93
94 if (!DeclMap()->WillParse(exe_ctx, NULL)) {
95 diagnostic_manager.PutString(
96 eDiagnosticSeverityError,
97 "current process state is unsuitable for expression parsing");
98 return false;
99 }
100
101 const bool generate_debug_info = true;
102 ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
103 generate_debug_info);
104
105 unsigned num_errors = parser.Parse(diagnostic_manager);
106
107 if (num_errors) {
108 ResetDeclMap();
109
110 return false;
111 }
112
113 //////////////////////////////////
114 // JIT the output of the parser
115 //
116
117 bool can_interpret = false; // should stay that way
118
119 Status jit_error = parser.PrepareForExecution(
120 m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
121 can_interpret, eExecutionPolicyAlways);
122
123 if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
124 m_jit_process_wp = process->shared_from_this();
125 if (parser.GetGenerateDebugInfo()) {
126 lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
127
128 if (jit_module_sp) {
129 ConstString const_func_name(FunctionName());
130 FileSpec jit_file;
131 jit_file.GetFilename() = const_func_name;
132 jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
133 m_jit_module_wp = jit_module_sp;
134 target->GetImages().Append(jit_module_sp);
135 }
136 }
137 }
138
139 DeclMap()->DidParse();
140
141 ResetDeclMap();
142
143 if (jit_error.Success()) {
144 return true;
145 } else {
146 const char *error_cstr = jit_error.AsCString();
147 if (error_cstr && error_cstr[0]) {
148 diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
149 } else {
150 diagnostic_manager.PutString(eDiagnosticSeverityError,
151 "expression can't be interpreted or run");
152 }
153 return false;
154 }
155 }
156
ResetDeclMap(ExecutionContext & exe_ctx,bool keep_result_in_memory)157 void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
158 ExecutionContext &exe_ctx, bool keep_result_in_memory) {
159 m_expr_decl_map_up.reset(
160 new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx));
161 }
162