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